Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Bq test problems #838

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
53 commits
Select commit Hold shift + click to select a range
8e65e99
first Genz function
fxbriol Dec 2, 2021
b41ec51
another Genz function
fxbriol Dec 2, 2021
2845cca
Test functions for integration on [0,1]^d
fxbriol Dec 6, 2021
6489362
Function to transform integrands from the cube to R^d
fxbriol Dec 6, 2021
e79b2e9
Integration test functions for Gaussian distributions
fxbriol Dec 6, 2021
12092a6
Monte Carlo tests for integrands and their integrals against uniform …
fxbriol Dec 6, 2021
3c42123
adding missing packages for Monte Carlo tests
fxbriol Dec 6, 2021
94b177e
missing directory for Monte Carlo tests
fxbriol Dec 6, 2021
17ea35f
Update test_quadproblems_uniform.py
fxbriol Dec 6, 2021
31c35f6
Merge branch 'main' into bq-test-problems
fxbriol Dec 7, 2021
2d580ed
Apply suggestions from code review
fxbriol Dec 15, 2021
6542b2b
Apply suggestions from code review
fxbriol Dec 15, 2021
cca0fa3
Apply suggestions from code review
fxbriol Dec 15, 2021
33887a9
add rst file for documentation
fxbriol Dec 15, 2021
a56033b
Implemented Marvin's suggestions
fxbriol Dec 16, 2021
d4a4c4f
Merge branch 'main' into bq-test-problems
fxbriol Dec 16, 2021
c21a1a5
fixed uniform_to_gaussian according to Marvin's comments
fxbriol Dec 16, 2021
f13ffb0
fixed sum_polynomials according to Marvin's comments
fxbriol Dec 16, 2021
1316f97
fixed sum_polynomials function
fxbriol Dec 16, 2021
fc9ca77
moved uniform_to_gaussian function to quadproblems_gaussian and added…
fxbriol Dec 16, 2021
b2cfe5b
Update _quadproblems_gaussian.py
fxbriol Dec 16, 2021
f673733
Fixed uniform_to_gaussian_quadprob
fxbriol Dec 16, 2021
7a47403
Updated the documentation for quadproblems_gaussian
fxbriol Dec 16, 2021
7b0e812
added shapes to documentation following Maren's comment
fxbriol Dec 16, 2021
bbc8a38
updated tests and removed stochasticity
fxbriol Dec 16, 2021
25c8731
load QuadratureProblems in all files where needed
fxbriol Dec 16, 2021
5b01547
Remove .DS_Store files
marvinpfoertner Dec 21, 2021
28cd3f0
Fix tests
marvinpfoertner Dec 21, 2021
3d7207e
Fix pylint messages in `_quadproblems_uniform.py`
marvinpfoertner Dec 21, 2021
df71c43
Merge remote-tracking branch 'origin/main' into bq-test-problems
marvinpfoertner Dec 22, 2021
6136065
Fix more pylint messages
marvinpfoertner Dec 22, 2021
035626d
fix more pylint messages
marvinpfoertner Dec 22, 2021
d241d57
Fix docs
marvinpfoertner Dec 22, 2021
ed0b086
Fix final pylint message
marvinpfoertner Dec 22, 2021
f2b2dad
Merge branch 'main' into bq-test-problems
marvinpfoertner Feb 25, 2022
78dc273
Merge remote-tracking branch 'origin/main' into bq-test-problems
marvinpfoertner Apr 26, 2022
bc1cc85
Fix `black` error
marvinpfoertner Apr 26, 2022
3e54726
`Float{ArgType->Like}`
marvinpfoertner Apr 26, 2022
7515564
PyLint fixes
marvinpfoertner Apr 26, 2022
19573a1
Add some more coverage
marvinpfoertner Apr 26, 2022
34510e1
More test coverage in _quadproblems_uniform
marvinpfoertner Apr 26, 2022
bd974b6
increase test coverage
fxbriol Apr 26, 2022
434a781
increase test coverage
fxbriol Apr 26, 2022
86a9ba3
Add some LaTeX math in docstrings
marvinpfoertner Apr 26, 2022
8c48032
Merge branch 'bq-test-problems' of https://github.com/fxbriol/probnum…
Sep 25, 2023
48bc9e2
Update to latest probnum version (#585)
Sep 27, 2023
f67b865
Add tests for integrands with Gaussian measure (#585)
Sep 28, 2023
fa22405
Fix example in uniform_to_gaussian_quadprob
Oct 11, 2023
a4675ea
Update docs/source/api/problems/zoo.quad.rst
katharina-ott Oct 11, 2023
6df2ac2
Merge branch 'main' into bq-test-problems
JonathanWenger Oct 18, 2023
f8a2be3
Merge branch 'main' into bq-test-problems
JonathanWenger Oct 21, 2023
342ea29
Update src/probnum/problems/zoo/quad/_quadproblems_gaussian.py
katharina-ott Oct 23, 2023
4e6fff0
Reduce runtime of MC sampling tests (#585)
Oct 23, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 3 additions & 4 deletions src/probnum/problems/zoo/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
"""Collection of test problems for probabilistic numerical methods.

Subpackage offering implementations of standard example problems or
convenient interfaces to benchmark problems for probabilistic numerical
methods. These test problems are meant for rapid experimentation and
prototyping.
Subpackage offering implementations of standard example problems or convenient
interfaces to benchmark problems for probabilistic numerical methods. These test
problems are meant for rapid experimentation and prototyping.
"""
22 changes: 21 additions & 1 deletion src/probnum/problems/zoo/quad/__init__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,26 @@
"""Test problems for numerical integration/ quadrature."""

from ._emukit_problems import circulargaussian2d, hennig1d, hennig2d, sombrero2d
from ._quadproblems_gaussian import *
from ._quadproblems_uniform import *

# Public classes and functions. Order is reflected in documentation.
__all__ = ["circulargaussian2d", "hennig1d", "hennig2d", "sombrero2d"]
__all__ = [
"circulargaussian2d",
"hennig1d",
"hennig2d",
"sombrero2d",
"uniform_to_gaussian_quadprob",
"sum_polynomials",
"genz_continuous",
"genz_cornerpeak",
"genz_discontinuous",
"genz_gaussian",
"genz_oscillatory",
"genz_productpeak",
"bratley1992",
"roos_arnold",
"gfunction",
"morokoff_caflisch_1",
"morokoff_caflisch_2",
]
232 changes: 232 additions & 0 deletions src/probnum/problems/zoo/quad/_quadproblems_gaussian.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
"""Test problems for integration against a Gaussian measure."""

from typing import Callable, Union

import numpy as np
from scipy import special
from scipy.stats import norm

from probnum.problems import QuadratureProblem
from probnum.quad.integration_measures import GaussianMeasure
from probnum.typing import FloatLike

__all__ = [
"uniform_to_gaussian_quadprob",
"sum_polynomials",
]


# Construct transformation of the integrand
def uniform_to_gaussian_integrand(
fun: Callable[[np.ndarray], np.ndarray],
mean: Union[float, np.floating, np.ndarray] = 0.0,
std: Union[float, np.floating, np.ndarray] = 1.0,
) -> Callable[[np.ndarray], np.ndarray]:
# mean and var should be either one-dimensional
if isinstance(mean, np.ndarray):
if len(mean.shape) != 1:
raise TypeError(
"The mean parameter should be a float or a d-dimensional array."
)

if isinstance(std, np.ndarray):
if len(std.shape) != 1:
raise TypeError(
"The std parameter should be a float or a d-dimensional array."
)

def new_func(x):
return fun(norm.cdf(x, loc=mean, scale=std))

return new_func


def uniform_to_gaussian_quadprob(
quadprob: QuadratureProblem,
mean: Union[float, np.floating, np.ndarray] = 0.0,
std: Union[float, np.floating, np.ndarray] = 1.0,
) -> QuadratureProblem:
r"""Creates a new QuadratureProblem for integration against a Gaussian on
:math:`\mathbb{R}^d` by using an existing QuadratureProblem whose integrand is
suitable for integration against the Lebesgue measure on :math:`[0,1]^d`.

The multivariate Gaussian is of the form :math:`\mathcal{N}(mean \cdot (1, \dotsc,
1)^\top, var^2 \cdot I_d)`.

Using the change of variable formula, we have that

.. math:: \int_{[0,1]^d} f(x) dx = \int_{\mathbb{R}^d} h(x) \phi(x) dx

where :math:`h(x)=f(\Phi((x-mean)/var))`, :math:`\phi(x)` is the Gaussian
probability density function and :math:`\Phi(x)` an elementwise application of the
Gaussian cumulative distribution function. See [1]_.

Parameters
----------
quadprob
A QuadratureProblem instance which includes an integrand defined on [0,1]^d
mean
Mean of the Gaussian distribution. If `float`, mean is set to the same value
across all dimensions. Else, specifies the mean as a d-dimensional array.
std
Diagonal element for the covariance matrix of the Gaussian distribution. If
`float`, the covariance matrix has the same diagonal value for all dimensions.
Else, specifies the covariance matrix via a d-dimensional array.

Returns
-------
problem
A new Quadrature Problem instance with a transformed integrand taking inputs in
:math:`\mathbb{R}^d`.

Raises
------
ValueError
If the original quadrature problem is over a domain other than [0, 1]^d or if it
does not have a scalar solution.

Example
-------
Convert the uniform continuous Genz problem to a Gaussian quadrature problem.

>>> import numpy as np
>>> from probnum.problems.zoo.quad import genz_continuous
>>> gaussian_quadprob = uniform_to_gaussian_quadprob(genz_continuous(1))
>>> gaussian_quadprob.fun(np.array([[0.]]))
array([[1.]])

References
----------
.. [1] Si, S., Oates, C. J., Duncan, A. B., Carin, L. & Briol. F-X. (2021). Scalable
control variates for Monte Carlo methods via stochastic optimization. Proceedings
of the 14th Monte Carlo and Quasi-Monte Carlo Methods (MCQMC) conference 2020.
arXiv:2006.07487.
"""
lower_bd, upper_bd = quadprob.measure.domain

# Check that the original quadrature problem was defined on [0,1]^d
if np.any(lower_bd != 0.0):
raise ValueError("quadprob is not an integration problem over [0,1]^d")
if np.any(upper_bd != 1.0):
raise ValueError("quadprob is not an integration problem over [0,1]^d")

# Check that the original quadrature problem has a scalar valued solution
if np.ndim(quadprob.solution) != 0:
raise ValueError("The solution of quadprob is not a scalar.")

Check warning on line 115 in src/probnum/problems/zoo/quad/_quadproblems_gaussian.py

View check run for this annotation

Codecov / codecov/patch

src/probnum/problems/zoo/quad/_quadproblems_gaussian.py#L115

Added line #L115 was not covered by tests

dim = lower_bd.shape[0]

cov = std**2
if isinstance(std, np.ndarray):
cov = np.eye(dim) * cov
gaussian_measure = GaussianMeasure(mean=mean, cov=cov, input_dim=dim)
return QuadratureProblem(
fun=uniform_to_gaussian_integrand(fun=quadprob.fun, mean=mean, std=std),
measure=gaussian_measure,
solution=quadprob.solution,
)


def sum_polynomials(
dim: int, a: np.ndarray = None, b: np.ndarray = None, var: FloatLike = 1.0
) -> QuadratureProblem:
r"""Quadrature problem with an integrand taking the form of a sum of polynomials
over :math:`\mathbb{R}^d`.

.. math:: f(x) = \sum_{j=0}^p \prod_{i=1}^dim a_{ji} x_i^{b_ji}

The integrand is integrated against a multivariate normal :math:`\mathcal{N}(0,var *
I_d)`. See [1]_.

Parameters
----------
dim
Dimension d of the integration domain
a
2d-array of size (p+1)xd giving coefficients of the polynomials.
b
2d-array of size (p+1)xd giving orders of the polynomials. All entries
should be natural numbers.
var
diagonal elements of the covariance function.

Returns
-------
f
array of size (n,1) giving integrand evaluations at points in 'x'.

Raises
------
ValueError
If the given parameters have the wrong shape or contain invalid values.

References
----------
.. [1] Si, S., Oates, C. J., Duncan, A. B., Carin, L. & Briol. F-X. (2021). Scalable
control variates for Monte Carlo methods via stochastic optimization. Proceedings
of the 14th Monte Carlo and Quasi-Monte Carlo Methods (MCQMC) conference 2020.
arXiv:2006.07487.
"""

# Specify default values of parameters a and u
if a is None:
a = np.broadcast_to(1.0, (1, dim))
if b is None:
b = np.broadcast_to(1, (1, dim))

if len(a.shape) != 2:
raise ValueError(
f"Invalid shape {a.shape} for parameter `a`. "
f"Expected parameters of shape (p+1)xdim"
)

if len(b.shape) != 2:
raise ValueError(
f"Invalid shape {b.shape} for parameter `b`. "
f"Expected parameters of shape (p+1)xdim"
)

# Check that the parameters have valid values and shape
if a.shape[1] != dim:
raise ValueError(
f"Invalid shape {a.shape} for parameter `a`. Expected {dim} columns."
)

if b.shape[1] != dim:
raise ValueError(
f"Invalid shape {b.shape} for parameter `b`. Expected {dim} columns."
)

if np.any(b < 0):
raise ValueError("The parameters `b` must be non-negative.")

def integrand(x: np.ndarray) -> np.ndarray:
n = x.shape[0]

# Compute function values
f = np.sum(
np.prod(
a[np.newaxis, :, :] * (x[:, np.newaxis, :] ** b[np.newaxis, :, :]),
axis=2,
),
axis=1,
)

# Return function values as a 2d array with one column.
return f.reshape((n, 1))

# Return function values as a 2d array with one column.
delta = (np.remainder(b, 2) - 1) ** 2
doublefact = special.factorial2(b - 1)
solution = np.sum(np.prod(a * delta * (var**b) * doublefact, axis=1))
if isinstance(var, float):
mean = 0.0
else:
mean = np.zeros(dim)

gaussian_measure = GaussianMeasure(mean=mean, cov=var, input_dim=dim)
return QuadratureProblem(
fun=integrand,
measure=gaussian_measure,
solution=solution,
)
Loading
Loading