Coder Social home page Coder Social logo

mike-gimelfarb / numerical-integration Goto Github PK

View Code? Open in Web Editor NEW
2.0 2.0 1.0 172 KB

a curated collection of algorithms for performing numerical integration of black-box functions and estimating limits of series and sequences with high precision in Java

License: GNU Lesser General Public License v2.1

Java 100.00%
quadrature integrals numerical-integration convergence-acceleration-algorithm infinite-sequences infinite-series limits numerical-methods estimating-integrals estimating-limits

numerical-integration's Introduction

Summary

This library contains standard and state-of-the-art algorithms for estimating integrals of functions in 1D and limits of sequences and series in Java, many of which are not currently implemented in Commons Math.

The main features are:

  • over a dozen algorithms for estimating integrals of 1D functions
  • support for variable transformations, oscillatory and indefinite integrals
  • algorithms for estimating limits of sequences and series in double and high (e.g. arbitrary) precision

Examples

The necessary packages from the library to run the examples can be imported as follows

import java.util.function.Function;
import integral.*;
import series.dp.*;
import utils.Sequences;

Limits and Series -- Simple Example

The framework currently supports many algorithms for accelerating convergence of infinite series, including methods of Aitken, Cohen, Theta (Brezinski and iterated), Levin (D, T, U and V transforms), Richardson, Wynn's Epsilon and Wynn's Rho, and an ensemble method.

Consider the following infinite series:

The Ensemble algorithm is the best bet if additional information about the series is not provided:

// define the series terms
Iterable<Double> iter = Sequences.toIterable(k -> 1.0 / Math.pow(k, 2), 1);

// find limit
SeriesAlgorithm alg = new Ensemble(1e-8, 1000, 5);
System.out.println(alg.limit(iter, true));

The estimate of the limit is 1.64493406, the exact value is 1.64493406 (to 8 decimal places).

Limits and Series -- Complex Example

Sometimes existing methods fail if the series is very slowly converging. Consider the following very difficult series:

Applying the Ensemble algorithm directly will return 2.06035757 which is not the correct limit. However, using a trick of van Wijngaarden, we can convert the series to an alternating series with the same limit:

// define the series terms
Function<Long, Double> f = k -> 1.0 / k / Math.pow(Math.log(k), 2);
	
// create transform of original series
Function<Long, Double> f2 = (new Ensemble(1e-8, 100, 2)).toAlternatingSeries(f, 2);
Iterable<Double> iter = Sequences.toIterable(f2, 1);
	
// find limit of transformed series
SeriesAlgorithm alg = new Ensemble(1e-8, 1000, 5);
System.out.println(alg.limit(iter, true));

Now, the estimate of the limit is 2.10973574, which is correct to 5 decimal places.

However, for terms that are sufficiently smooth and have an analytic continuation to the real numbers, it is possible to use the Euler-Maclaurin method to approximate the series by an imporoper integral, which often provides a more precise result. To run this, a method for evaluating integrals must be defined, how to break the improper integral up into proper integrals, and how to accelerate the resulting sequence of integral estimates.

import series.special.EulerMaclaurin;

// define the series terms
Function<Double, Double> f = k -> 1.0 / k / Math.pow(Math.log(k), 2);
	
// find limit of transformed series
EulerMaclaurin algorithm = new EulerMaclaurin(1e-8, new GaussKronrod(1e-8, 1000), new Ensemble(1e-8, 1000, 5), k -> Math.pow(2, k));
System.out.println(algorithm.limit(f, 2L));

This time, the estimate of the limit is 2.10974280 and is correct to 8 decimals.

Definite Integrals -- Simple Example

The framework is also very capable of numerically evaluating integrals of 1d functions, including adaptive Clenshaw-Curtis, adaptive Gaussian (Gauss-Kronrod, Gauss-Legendre, Gauss-Lobatto, RMS improvement of Gauss-Kronrod), Newton-Cotes, Romberg, adaptive Simpson (global and local versions), and Tanh-Sinh quadrature schemes.

Consider the following definite integral:

We will use Gaussian quadrature (Gauss-Kronrod) to evaluate this integral:

// define the integrand
Function<Double, Double> f = x -> 1.0 / (1.0 + x * x);
	
// integrate
Quadrature integrator = new GaussKronrod(1e-8, 1000);
System.out.println(integrator.integrate(f, -100.0, 100.0));

The predicted value is 3.12159332, which is correct to 8 decimal places.

Definite Integrals -- Infinite Bounds Example

The following integral is improper and hard to evaluate directly:

However, the package provides a transformation of variables to deal with integrals of this form:

Integrals over [-infinity, infinity] are broken into two intervals at zero.

// define the integrand
Function<Double, Double> f = x -> Math.exp(x) / x;

// split the integration region into subregions
Quadrature integrator = new TanhSinh(1e-8, 1000);
System.out.println(integrator.integrate(f, Double.NEGATIVE_INFINITY, -1.0));

The estimated value of the integral is -0.21938393, correct to 8 decimals.

Definite Integrals -- Oscillatory with Infinite Bounds Example

The following integral is improper, and is also highly oscillatory:

It is impossible to evaluate using any single integrator. However, it is possible to break up this integral over integration regions separated by the roots of the function, and estimate the above integral by evaluating an infinite series. The package provides a convenience method to do this, but requires the roots of the integrand to be fed to the method. The following example illustrates this:

// define the integrand
Function<Double, Double> f = x -> Math.cos(x * x);

// split the integration region into subregions
Iterable<Double> roots = Sequences.toIterable(k -> Math.sqrt(Math.PI * k), 0L);
Quadrature integrator = new GaussKronrod(1e-8, 1000);
Iterable<Double> integrals = integrator.integratePiecewise(f, roots);
	
// evaluate the integral as an alternating series
SeriesAlgorithm accelerator = new Cohen(1e-8, 1000, 1);
System.out.println(accelerator.limit(integrals, true));

The estimated value of the integral is 0.62665707, which is correct to 8 decimal places.

numerical-integration's People

Contributors

mike-gimelfarb avatar

Stargazers

 avatar  avatar

Watchers

 avatar  avatar

Forkers

hasakilol

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.