Skip to content

Commit

Permalink
Merge pull request #425 from damar-wicaksono/dev-331
Browse files Browse the repository at this point in the history
Add exponential function from Dette & Pepelyshev (2010)
  • Loading branch information
damar-wicaksono authored Nov 28, 2024
2 parents 015f860 + 9e87b20 commit 7a990d2
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 43 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

### Added

- The tree-dimensional exponential function from Dette and Pepelyshev (2010)
for metamodeling exercises.
- The one-dimensional sine function from Higdon (2002) featuring behaviors
that are different in two scales; for metamodeling (multi-resolution)
exercises.
Expand Down
2 changes: 2 additions & 0 deletions docs/_toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ parts:
title: Damped Oscillator
- file: test-functions/damped-oscillator-reliability
title: Damped Oscillator Reliability
- file: test-functions/dette-exp
title: Dette & Pepelyshev (2010) Exponential
- file: test-functions/flood
title: Flood
- file: test-functions/forrester
Expand Down
85 changes: 43 additions & 42 deletions docs/fundamentals/metamodeling.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,48 +18,49 @@ kernelspec:
The table below listed the available test functions typically used
in the comparison of metamodeling approaches.

| Name | Input Dimension | Constructor |
|:----------------------------------------------------------------------:|:---------------:|:----------------------:|
| {ref}`Ackley <test-functions:ackley>` | M | `Ackley()` |
| {ref}`Alemazkoor & Meidani (2018) 2D <test-functions:alemazkoor-2d>` | 2 | `Alemazkoor2D()` |
| {ref}`Alemazkoor & Meidani (2018) 20D <test-functions:alemazkoor-20d>` | 20 | `Alemazkoor20D()` |
| {ref}`Borehole <test-functions:borehole>` | 8 | `Borehole()` |
| {ref}`Cheng and Sandu (2010) 2D <test-functions:cheng2d>` | 2 | `Cheng2D` |
| {ref}`Coffee Cup Model <test-functions:coffee-cup>` | 2 | `CoffeeCup()` |
| {ref}`Currin et al. (1988) Sine <test-functions:currin-sine>` | 1 | `CurrinSine()` |
| {ref}`Damped Cosine <test-functions:damped-cosine>` | 1 | `DampedCosine()` |
| {ref}`Damped Oscillator <test-functions:damped-oscillator>` | 7 | `DampedOscillator()` |
| {ref}`Flood <test-functions:flood>` | 8 | `Flood()` |
| {ref}`Forrester et al. (2008) <test-functions:forrester>` | 1 | `Forrester2008()` |
| {ref}`(1st) Franke <test-functions:franke-1>` | 2 | `Franke1()` |
| {ref}`(2nd) Franke <test-functions:franke-2>` | 2 | `Franke2()` |
| {ref}`(3rd) Franke <test-functions:franke-3>` | 2 | `Franke3()` |
| {ref}`(4th) Franke <test-functions:franke-4>` | 2 | `Franke4()` |
| {ref}`(5th) Franke <test-functions:franke-5>` | 2 | `Franke5()` |
| {ref}`(6th) Franke <test-functions:franke-6>` | 2 | `Franke6()` |
| {ref}`Friedman (6D) <test-functions:friedman-6d>` | 6 | `Friedman6D()` |
| {ref}`Friedman (10D) <test-functions:friedman-10d>` | 10 | `Friedman10D()` |
| {ref}`Genz (Corner Peak) <test-functions:genz-corner-peak>` | M | `GenzCornerPeak()` |
| {ref}`Gramacy (2007) 1D Sine <test-functions:gramacy-1d-sine>` | 1 | `Gramacy1DSine()` |
| {ref}`Higdon (2002) Sine <test-functions:higdon-sine>` | 1 | `HigdonSine()` |
| {ref}`Holsclaw et al. (2013) Sine <test-functions:holsclaw-sine>` | 1 | `HolsclawSine()` |
| {ref}`Lim et al. (2002) Non-Polynomial <test-functions:lim-non-poly>` | 2 | `LimNonPoly()` |
| {ref}`Lim et al. (2002) Polynomial <test-functions:lim-poly>` | 2 | `LimPoly()` |
| {ref}`McLain S1 <test-functions:mclain-s1>` | 2 | `McLainS1()` |
| {ref}`McLain S2 <test-functions:mclain-s2>` | 2 | `McLainS2()` |
| {ref}`McLain S3 <test-functions:mclain-s3>` | 2 | `McLainS3()` |
| {ref}`McLain S4 <test-functions:mclain-s4>` | 2 | `McLainS4()` |
| {ref}`McLain S5 <test-functions:mclain-s5>` | 2 | `McLainS5()` |
| {ref}`Oakley & O'Hagan (2002) 1D <test-functions:oakley-1d>` | 1 | `Oakley1D()` |
| {ref}`OTL Circuit <test-functions:otl-circuit>` | 6 / 20 | `OTLCircuit()` |
| {ref}`Piston Simulation <test-functions:piston>` | 7 / 20 | `Piston()` |
| {ref}`Robot Arm <test-functions:robot-arm>` | 8 | `RobotArm()` |
| {ref}`Solar Cell Model <test-functions:solar-cell>` | 5 | `SolarCell()` |
| {ref}`Sulfur <test-functions:sulfur>` | 9 | `Sulfur()` |
| {ref}`Undamped Oscillator <test-functions:undamped-oscillator>` | 6 | `UndampedOscillator()` |
| {ref}`Webster et al. (1996) 2D <test-functions:webster-2d>` | 2 | `Webster2D()` |
| {ref}`Welch et al. (1992) <test-functions:welch1992>` | 20 | `Welch1992()` |
| {ref}`Wing Weight <test-functions:wing-weight>` | 10 | `WingWeight()` |
| Name | Input Dimension | Constructor |
|:------------------------------------------------------------------------:|:---------------:|:----------------------:|
| {ref}`Ackley <test-functions:ackley>` | M | `Ackley()` |
| {ref}`Alemazkoor & Meidani (2018) 2D <test-functions:alemazkoor-2d>` | 2 | `Alemazkoor2D()` |
| {ref}`Alemazkoor & Meidani (2018) 20D <test-functions:alemazkoor-20d>` | 20 | `Alemazkoor20D()` |
| {ref}`Borehole <test-functions:borehole>` | 8 | `Borehole()` |
| {ref}`Cheng and Sandu (2010) 2D <test-functions:cheng2d>` | 2 | `Cheng2D` |
| {ref}`Coffee Cup Model <test-functions:coffee-cup>` | 2 | `CoffeeCup()` |
| {ref}`Currin et al. (1988) Sine <test-functions:currin-sine>` | 1 | `CurrinSine()` |
| {ref}`Damped Cosine <test-functions:damped-cosine>` | 1 | `DampedCosine()` |
| {ref}`Damped Oscillator <test-functions:damped-oscillator>` | 7 | `DampedOscillator()` |
| {ref}`Dette & Pepelyshev (2010) Exponential <test-functions:dette-exp>` | 3 | `DetteExp()` |
| {ref}`Flood <test-functions:flood>` | 8 | `Flood()` |
| {ref}`Forrester et al. (2008) <test-functions:forrester>` | 1 | `Forrester2008()` |
| {ref}`(1st) Franke <test-functions:franke-1>` | 2 | `Franke1()` |
| {ref}`(2nd) Franke <test-functions:franke-2>` | 2 | `Franke2()` |
| {ref}`(3rd) Franke <test-functions:franke-3>` | 2 | `Franke3()` |
| {ref}`(4th) Franke <test-functions:franke-4>` | 2 | `Franke4()` |
| {ref}`(5th) Franke <test-functions:franke-5>` | 2 | `Franke5()` |
| {ref}`(6th) Franke <test-functions:franke-6>` | 2 | `Franke6()` |
| {ref}`Friedman (6D) <test-functions:friedman-6d>` | 6 | `Friedman6D()` |
| {ref}`Friedman (10D) <test-functions:friedman-10d>` | 10 | `Friedman10D()` |
| {ref}`Genz (Corner Peak) <test-functions:genz-corner-peak>` | M | `GenzCornerPeak()` |
| {ref}`Gramacy (2007) 1D Sine <test-functions:gramacy-1d-sine>` | 1 | `Gramacy1DSine()` |
| {ref}`Higdon (2002) Sine <test-functions:higdon-sine>` | 1 | `HigdonSine()` |
| {ref}`Holsclaw et al. (2013) Sine <test-functions:holsclaw-sine>` | 1 | `HolsclawSine()` |
| {ref}`Lim et al. (2002) Non-Polynomial <test-functions:lim-non-poly>` | 2 | `LimNonPoly()` |
| {ref}`Lim et al. (2002) Polynomial <test-functions:lim-poly>` | 2 | `LimPoly()` |
| {ref}`McLain S1 <test-functions:mclain-s1>` | 2 | `McLainS1()` |
| {ref}`McLain S2 <test-functions:mclain-s2>` | 2 | `McLainS2()` |
| {ref}`McLain S3 <test-functions:mclain-s3>` | 2 | `McLainS3()` |
| {ref}`McLain S4 <test-functions:mclain-s4>` | 2 | `McLainS4()` |
| {ref}`McLain S5 <test-functions:mclain-s5>` | 2 | `McLainS5()` |
| {ref}`Oakley & O'Hagan (2002) 1D <test-functions:oakley-1d>` | 1 | `Oakley1D()` |
| {ref}`OTL Circuit <test-functions:otl-circuit>` | 6 / 20 | `OTLCircuit()` |
| {ref}`Piston Simulation <test-functions:piston>` | 7 / 20 | `Piston()` |
| {ref}`Robot Arm <test-functions:robot-arm>` | 8 | `RobotArm()` |
| {ref}`Solar Cell Model <test-functions:solar-cell>` | 5 | `SolarCell()` |
| {ref}`Sulfur <test-functions:sulfur>` | 9 | `Sulfur()` |
| {ref}`Undamped Oscillator <test-functions:undamped-oscillator>` | 6 | `UndampedOscillator()` |
| {ref}`Webster et al. (1996) 2D <test-functions:webster-2d>` | 2 | `Webster2D()` |
| {ref}`Welch et al. (1992) <test-functions:welch1992>` | 20 | `Welch1992()` |
| {ref}`Wing Weight <test-functions:wing-weight>` | 10 | `WingWeight()` |

In a Python terminal, you can list all the available functions relevant
for metamodeling applications using ``list_functions()``
Expand Down
11 changes: 11 additions & 0 deletions docs/references.bib
Original file line number Diff line number Diff line change
Expand Up @@ -1032,4 +1032,15 @@ @InBook{Higdon2002
doi = {10.1007/978-1-4471-0657-9_2},
}

@Article{Dette2010,
author = {Dette, Holger and Pepelyshev, Andrey},
journal = {Technometrics},
title = {Generalized latin hypercube design for computer experiments},
year = {2010},
number = {4},
pages = {421--429},
volume = {52},
doi = {10.1198/tech.2010.09157},
}

@Comment{jabref-meta: databaseType:bibtex;}
1 change: 1 addition & 0 deletions docs/test-functions/available.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ regardless of their typical applications.
| {ref}`Damped Cosine <test-functions:damped-cosine>` | 1 | `DampedCosine()` |
| {ref}`Damped Oscillator <test-functions:damped-oscillator>` | 7 | `DampedOscillator()` |
| {ref}`Damped Oscillator Reliability <test-functions:damped-oscillator-reliability>` | 8 | `DampedOscillatorReliability()` |
| {ref}`Dette & Pepelyshev (2010) Exponential <test-functions:dette-exp>` | 3 | `DetteExp()` |
| {ref}`Flood <test-functions:flood>` | 8 | `Flood()` |
| {ref}`Forrester et al. (2008) <test-functions:forrester>` | 1 | `Forrester2008()` |
| {ref}`Four-branch <test-functions:four-branch>` | 2 | `FourBranch()` |
Expand Down
98 changes: 98 additions & 0 deletions docs/test-functions/dette-exp.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
---
jupytext:
formats: ipynb,md:myst
text_representation:
extension: .md
format_name: myst
format_version: 0.13
jupytext_version: 1.14.1
kernelspec:
display_name: Python 3 (ipykernel)
language: python
name: python3
---

(test-functions:dette-exp)=
# Exponential Function from Dette and Pepelyshev (2010)

```{code-cell} ipython3
import numpy as np
import matplotlib.pyplot as plt
import uqtestfuns as uqtf
```

The function is a three-dimensional, scalar-valued function that exhibits
asymptotic behavior where the function value approaches zero near the origin
and increases toward a value as the input moves farther away from the origin
in any direction.

The function appeared in {cite}`Dette2010` as a test function for comparing
different experimental designs in the construction of metamodels.

## Test function instance

To create a default instance of the test function:

```{code-cell} ipython3
my_testfun = uqtf.DetteExp()
```

Check if it has been correctly instantiated:

```{code-cell} ipython3
print(my_testfun)
```

## Description

The test function is defined as[^location]:

$$
\mathcal{M}(\boldsymbol{x}) = 100 \left[ \exp{\left( -\frac{2}{x_1^{1.75}} \right)} + \exp{\left( -\frac{2}{x_2^{1.5}} \right)} + \exp{\left( -\frac{2}{x_3^{1.25}} \right)} \right],
$$

where $\boldsymbol{x} = \left( x_1, x_2, x_3 \right)$ is the three-dimensional
vector of input variables further defined below.

## Probabilistic input

The probabilistic input model for the test function is shown below.

```{code-cell} ipython3
:tags: [hide-input]
print(my_testfun.prob_input)
```

## Reference results

This section provides several reference results of typical UQ analyses involving
the test function.

### Sample histogram

Shown below is the histogram of the output based on $100'000$ random points:

```{code-cell} ipython3
:tags: [hide-input]
my_testfun.prob_input.reset_rng(42)
xx_test = my_testfun.prob_input.get_sample(100000)
yy_test = my_testfun(xx_test)
plt.hist(yy_test, bins="auto", color="#8da0cb");
plt.grid();
plt.ylabel("Counts [-]");
plt.xlabel("$\mathcal{M}(X)$");
plt.gcf().tight_layout(pad=3.0)
plt.gcf().set_dpi(150);
```

## References

```{bibliography}
:style: unsrtalpha
:filter: docname in docnames
```

[^location]: see Eq. (4), Section 3.1, p. 424, in {cite}`Dette2010`.
2 changes: 2 additions & 0 deletions src/uqtestfuns/test_functions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from .currin_sine import CurrinSine
from .damped_cosine import DampedCosine
from .damped_oscillator import DampedOscillator, DampedOscillatorReliability
from .dette import DetteExp
from .flood import Flood
from .forrester import Forrester2008
from .four_branch import FourBranch
Expand Down Expand Up @@ -75,6 +76,7 @@
"DampedCosine",
"DampedOscillator",
"DampedOscillatorReliability",
"DetteExp",
"Flood",
"Forrester2008",
"FourBranch",
Expand Down
70 changes: 70 additions & 0 deletions src/uqtestfuns/test_functions/dette.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
"""
Module with an implementation of the functions from Dette and Pepelyshev (2010)
The paper by Dette and Pepelyshev [1] contains several analytical test
functions used to compare different experimental designs for metamodeling
applications.
References
----------
1. H. Dette and A. Pepelyshev, “Generalized Latin Hypercube Design for Computer
Experiments,” Technometrics, vol. 52, no. 4, pp. 421–429, 2010.
DOI: 10.1198/TECH.2010.09157.
"""

import numpy as np

from uqtestfuns.core.custom_typing import ProbInputSpecs
from uqtestfuns.core.uqtestfun_abc import UQTestFunFixDimABC

__all__ = ["DetteExp"]


def evaluate_exp(xx: np.ndarray) -> np.ndarray:
"""Evaluate the exponential function from Dette and Pepelyshev (2010).
Parameters
----------
xx : np.ndarray
M-Dimensional input values given by an N-by-3 array where
N is the number of input values.
Returns
-------
np.ndarray
The output of the test function evaluated on the input values.
The output is a 1-dimensional array of length N.
"""
yy = np.sum(np.exp(-2 / xx ** ([1.75, 1.5, 1.25])), axis=1)

return 100 * yy


class DetteExp(UQTestFunFixDimABC):
"""A concrete implementation of the exponential function."""

_tags = ["metamodeling"]
_description = "Exponential function from Dette and Pepelyshev (2010)"
_available_inputs: ProbInputSpecs = {
"Dette2010": {
"function_id": "DetteExp",
"description": (
"Input specification for the exponential test function "
"from Dette and Pepelyshev et al. (2010)"
),
"marginals": [
{
"name": f"x_{i + 1}",
"distribution": "uniform",
"parameters": [0, 1],
"description": None,
}
for i in range(3)
],
"copulas": None,
},
}
_available_parameters = None

evaluate = staticmethod(evaluate_exp) # type: ignore
2 changes: 1 addition & 1 deletion tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ def create_random_marginals(length: int) -> List[Marginal]:
parameters = np.sort(1 + 2 * np.random.rand(3))
parameters[[0, 1]] = parameters[[1, 0]]
# Insert sigma/beta as the second parameter
parameters = np.insert(parameters, 1, np.random.rand(1))
parameters = np.insert(parameters, 1, 0.5 + np.random.rand(1))
elif distribution == "lognormal":
# Limit the size of the parameters
parameters = 1 + np.random.rand(2)
Expand Down

0 comments on commit 7a990d2

Please sign in to comment.