NumericalIntegrator

NumericalIntegrator()

A numerical integrator for high-dimensional integrals.

Methods

Name Description
add_training_samples Add the samples and their corresponding function evaluations to the grid.
continuous Create a new continuous grid for the numerical integrator.
discrete Create a new discrete grid for the numerical integrator. Each
export_grid Export the grid, so that it can be sent to another thread or machine.
get_live_estimate Get the estamate of the average, error, chi-squared, maximum negative and positive evaluations, and the number of processed samples
import_grid Import an exported grid from another thread or machine.
integrate Integrate the function integrand that maps a list of Samples to a list of floats.
merge Add the accumulated training samples from the grid other to the current grid.
rng Create a new random number generator, suitable for use with the integrator.
sample Sample num_samples points from the grid using the random number generator
update Update the grid using the learning_rate.

add_training_samples

NumericalIntegrator.add_training_samples(samples, evals)

Add the samples and their corresponding function evaluations to the grid. Call update after to update the grid and to obtain the new expected value for the integral.

continuous

NumericalIntegrator.continuous(_cls, n_dims, n_bins=128, min_samples_for_update=100, bin_number_evolution=None, train_on_avg=False)

Create a new continuous grid for the numerical integrator.

discrete

NumericalIntegrator.discrete(_cls, bins, max_prob_ratio=100.0, train_on_avg=False)

Create a new discrete grid for the numerical integrator. Each bin can have a sub-grid.

Examples

>>> def integrand(samples: list[Sample]):
>>>     res = []
>>>     for sample in samples:
>>>         if sample.d[0] == 0:
>>>             res.append(sample.c[0]**2)
>>>         else:
>>>             res.append(sample.c[0]**1/2)
>>>     return res
>>>
>>> integrator = NumericalIntegrator.discrete(
>>>     [NumericalIntegrator.continuous(1), NumericalIntegrator.continuous(1)])
>>> integrator.integrate(integrand, True, 10, 10000)

export_grid

NumericalIntegrator.export_grid()

Export the grid, so that it can be sent to another thread or machine. Use import_grid to load the grid.

get_live_estimate

NumericalIntegrator.get_live_estimate()

Get the estamate of the average, error, chi-squared, maximum negative and positive evaluations, and the number of processed samples for the current iteration, including the points submitted in the current iteration.

import_grid

NumericalIntegrator.import_grid(_cls, grid)

Import an exported grid from another thread or machine. Use export_grid to export the grid.

integrate

NumericalIntegrator.integrate(integrand, max_n_iter=10000000, min_error=0.01, n_samples_per_iter=10000, seed=0, show_stats=True)

Integrate the function integrand that maps a list of Samples to a list of floats. The return value is the average, the statistical error, and chi-squared of the integral.

With show_stats=True, intermediate statistics will be printed. max_n_iter determines the number of iterations and n_samples_per_iter determine the number of samples per iteration. This is the same amount of samples that the integrand function will be called with.

For more flexibility, use sample, add_training_samples and update. See update for an example.

Examples

>>> from symbolica import NumericalIntegrator, Sample
>>>
>>> def integrand(samples: list[Sample]):
>>>     res = []
>>>     for sample in samples:
>>>         res.append(sample.c[0]**2+sample.c[1]**2)
>>>     return res
>>>
>>> avg, err = NumericalIntegrator.continuous(2).integrate(integrand, True, 10, 100000)
>>> print('Result: {} +- {}'.format(avg, err))

merge

NumericalIntegrator.merge(other)

Add the accumulated training samples from the grid other to the current grid. The grid structure of self and other must be equivalent.

rng

NumericalIntegrator.rng(_cls, seed, stream_id)

Create a new random number generator, suitable for use with the integrator. Each thread of instance of the integrator should have its own random number generator, that is initialized with the same seed but with a different stream id.

sample

NumericalIntegrator.sample(num_samples, rng)

Sample num_samples points from the grid using the random number generator rng. See rng() for how to create a random number generator.

update

NumericalIntegrator.update(learning_rate)

Update the grid using the learning_rate.

Examples

>>> from symbolica import NumericalIntegrator, Sample
>>>
>>> def integrand(samples: list[Sample]):
>>>     res = []
>>>     for sample in samples:
>>>         res.append(sample.c[0]**2+sample.c[1]**2)
>>>     return res
>>>
>>> integrator = NumericalIntegrator.continuous(2)
>>> for i in range(10):
>>>     samples = integrator.sample(10000 + i * 1000)
>>>     res = integrand(samples)
>>>     integrator.add_training_samples(samples, res)
>>>     avg, err, chi_sq = integrator.update(1.5)
>>>     print('Iteration {}: {:.6} +- {:.6}, chi={:.6}'.format(i+1, avg, err, chi_sq))