From d06eb58fdfd94b9ad4202b0cf7fa67764d7b477e Mon Sep 17 00:00:00 2001 From: Damar Wicaksono Date: Fri, 6 Dec 2024 14:23:21 +0100 Subject: [PATCH] Add the sine function from Linkletter et al. (2006) This commit introduces the ten-dimensional sine function from Linkletter et al. (2006). The function features only two active variables and was used in the context of sensitivity (screening) analysis. The documentation has been updated accordingly. This commit should resolve Issue #329. --- CHANGELOG.md | 3 + docs/_toc.yml | 2 + docs/fundamentals/metamodeling.md | 95 +++++----- docs/fundamentals/sensitivity.md | 57 +++--- docs/test-functions/available.md | 1 + docs/test-functions/linkletter-dec-coeffs.md | 7 +- docs/test-functions/linkletter-linear.md | 7 +- docs/test-functions/linkletter-sine.md | 182 +++++++++++++++++++ src/uqtestfuns/test_functions/__init__.py | 3 +- src/uqtestfuns/test_functions/linkletter.py | 101 +++++++--- 10 files changed, 354 insertions(+), 104 deletions(-) create mode 100644 docs/test-functions/linkletter-sine.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 0441445..667ea49 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added +- The ten-dimensional sine function from Linkletter et al. (2006) featuring + only two active input variables out of ten; the function was used in the + context of metamodeling and sensitivity analysis. - The ten-dimensional linear function with decreasing coefficients from Linkletter et al. (2006) featuring only eight active input variables out of ten; the function was used in the context of metamodeling and sensitivity diff --git a/docs/_toc.yml b/docs/_toc.yml index 5cc6b44..0c18199 100644 --- a/docs/_toc.yml +++ b/docs/_toc.yml @@ -130,6 +130,8 @@ parts: title: Linkletter et al. (2006) Dec. Coeffs. - file: test-functions/linkletter-linear title: Linkletter et al. (2006) Linear + - file: test-functions/linkletter-sine + title: Linkletter et al. (2006) Sine - file: test-functions/mclain-s1 title: McLain S1 - file: test-functions/mclain-s2 diff --git a/docs/fundamentals/metamodeling.md b/docs/fundamentals/metamodeling.md index f45f21c..0cb48e6 100644 --- a/docs/fundamentals/metamodeling.md +++ b/docs/fundamentals/metamodeling.md @@ -18,53 +18,54 @@ kernelspec: The table below listed the available test functions typically used in the comparison of metamodeling approaches. -| Name | Input Dimension | Constructor | -|:-----------------------------------------------------------------------------------------------:|:---------------:|:-----------------------:| -| {ref}`Ackley ` | M | `Ackley()` | -| {ref}`Alemazkoor & Meidani (2018) 2D ` | 2 | `Alemazkoor2D()` | -| {ref}`Alemazkoor & Meidani (2018) 20D ` | 20 | `Alemazkoor20D()` | -| {ref}`Borehole ` | 8 | `Borehole()` | -| {ref}`Cheng and Sandu (2010) 2D ` | 2 | `Cheng2D` | -| {ref}`Coffee Cup Model ` | 2 | `CoffeeCup()` | -| {ref}`Currin et al. (1988) Sine ` | 1 | `CurrinSine()` | -| {ref}`Damped Cosine ` | 1 | `DampedCosine()` | -| {ref}`Damped Oscillator ` | 7 | `DampedOscillator()` | -| {ref}`Dette & Pepelyshev (2010) 8D ` | 3 | `Dette8D()` | -| {ref}`Dette & Pepelyshev (2010) Curved ` | 3 | `DetteCurved()` | -| {ref}`Dette & Pepelyshev (2010) Exponential ` | 3 | `DetteExp()` | -| {ref}`Flood ` | 8 | `Flood()` | -| {ref}`Forrester et al. (2008) ` | 1 | `Forrester2008()` | -| {ref}`(1st) Franke ` | 2 | `Franke1()` | -| {ref}`(2nd) Franke ` | 2 | `Franke2()` | -| {ref}`(3rd) Franke ` | 2 | `Franke3()` | -| {ref}`(4th) Franke ` | 2 | `Franke4()` | -| {ref}`(5th) Franke ` | 2 | `Franke5()` | -| {ref}`(6th) Franke ` | 2 | `Franke6()` | -| {ref}`Friedman (6D) ` | 6 | `Friedman6D()` | -| {ref}`Friedman (10D) ` | 10 | `Friedman10D()` | -| {ref}`Genz (Corner Peak) ` | M | `GenzCornerPeak()` | -| {ref}`Gramacy (2007) 1D Sine ` | 1 | `Gramacy1DSine()` | -| {ref}`Higdon (2002) Sine ` | 1 | `HigdonSine()` | -| {ref}`Holsclaw et al. (2013) Sine ` | 1 | `HolsclawSine()` | -| {ref}`Lim et al. (2002) Non-Polynomial ` | 2 | `LimNonPoly()` | -| {ref}`Lim et al. (2002) Polynomial ` | 2 | `LimPoly()` | -| {ref}`Linkletter et al. (2006) Decreasing Coefficients ` | 10 | `LinkletterDecCoeffs()` | -| {ref}`Linkletter et al. (2006) Linear ` | 10 | `LinkletterLinear()` | -| {ref}`McLain S1 ` | 2 | `McLainS1()` | -| {ref}`McLain S2 ` | 2 | `McLainS2()` | -| {ref}`McLain S3 ` | 2 | `McLainS3()` | -| {ref}`McLain S4 ` | 2 | `McLainS4()` | -| {ref}`McLain S5 ` | 2 | `McLainS5()` | -| {ref}`Oakley & O'Hagan (2002) 1D ` | 1 | `Oakley1D()` | -| {ref}`OTL Circuit ` | 6 / 20 | `OTLCircuit()` | -| {ref}`Piston Simulation ` | 7 / 20 | `Piston()` | -| {ref}`Robot Arm ` | 8 | `RobotArm()` | -| {ref}`Solar Cell Model ` | 5 | `SolarCell()` | -| {ref}`Sulfur ` | 9 | `Sulfur()` | -| {ref}`Undamped Oscillator ` | 6 | `UndampedOscillator()` | -| {ref}`Webster et al. (1996) 2D ` | 2 | `Webster2D()` | -| {ref}`Welch et al. (1992) ` | 20 | `Welch1992()` | -| {ref}`Wing Weight ` | 10 | `WingWeight()` | +| Name | Input Dimension | Constructor | +|:----------------------------------------------------------------------------------------------:|:---------------:|:-----------------------:| +| {ref}`Ackley ` | M | `Ackley()` | +| {ref}`Alemazkoor & Meidani (2018) 2D ` | 2 | `Alemazkoor2D()` | +| {ref}`Alemazkoor & Meidani (2018) 20D ` | 20 | `Alemazkoor20D()` | +| {ref}`Borehole ` | 8 | `Borehole()` | +| {ref}`Cheng and Sandu (2010) 2D ` | 2 | `Cheng2D` | +| {ref}`Coffee Cup Model ` | 2 | `CoffeeCup()` | +| {ref}`Currin et al. (1988) Sine ` | 1 | `CurrinSine()` | +| {ref}`Damped Cosine ` | 1 | `DampedCosine()` | +| {ref}`Damped Oscillator ` | 7 | `DampedOscillator()` | +| {ref}`Dette & Pepelyshev (2010) 8D ` | 3 | `Dette8D()` | +| {ref}`Dette & Pepelyshev (2010) Curved ` | 3 | `DetteCurved()` | +| {ref}`Dette & Pepelyshev (2010) Exponential ` | 3 | `DetteExp()` | +| {ref}`Flood ` | 8 | `Flood()` | +| {ref}`Forrester et al. (2008) ` | 1 | `Forrester2008()` | +| {ref}`(1st) Franke ` | 2 | `Franke1()` | +| {ref}`(2nd) Franke ` | 2 | `Franke2()` | +| {ref}`(3rd) Franke ` | 2 | `Franke3()` | +| {ref}`(4th) Franke ` | 2 | `Franke4()` | +| {ref}`(5th) Franke ` | 2 | `Franke5()` | +| {ref}`(6th) Franke ` | 2 | `Franke6()` | +| {ref}`Friedman (6D) ` | 6 | `Friedman6D()` | +| {ref}`Friedman (10D) ` | 10 | `Friedman10D()` | +| {ref}`Genz (Corner Peak) ` | M | `GenzCornerPeak()` | +| {ref}`Gramacy (2007) 1D Sine ` | 1 | `Gramacy1DSine()` | +| {ref}`Higdon (2002) Sine ` | 1 | `HigdonSine()` | +| {ref}`Holsclaw et al. (2013) Sine ` | 1 | `HolsclawSine()` | +| {ref}`Lim et al. (2002) Non-Polynomial ` | 2 | `LimNonPoly()` | +| {ref}`Lim et al. (2002) Polynomial ` | 2 | `LimPoly()` | +| {ref}`Linkletter et al. (2006) Decreasing Coefficients ` | 10 | `LinkletterDecCoeffs()` | +| {ref}`Linkletter et al. (2006) Linear ` | 10 | `LinkletterLinear()` | +| {ref}`Linkletter et al. (2006) Sine ` | 10 | `LinkletterSine()` | +| {ref}`McLain S1 ` | 2 | `McLainS1()` | +| {ref}`McLain S2 ` | 2 | `McLainS2()` | +| {ref}`McLain S3 ` | 2 | `McLainS3()` | +| {ref}`McLain S4 ` | 2 | `McLainS4()` | +| {ref}`McLain S5 ` | 2 | `McLainS5()` | +| {ref}`Oakley & O'Hagan (2002) 1D ` | 1 | `Oakley1D()` | +| {ref}`OTL Circuit ` | 6 / 20 | `OTLCircuit()` | +| {ref}`Piston Simulation ` | 7 / 20 | `Piston()` | +| {ref}`Robot Arm ` | 8 | `RobotArm()` | +| {ref}`Solar Cell Model ` | 5 | `SolarCell()` | +| {ref}`Sulfur ` | 9 | `Sulfur()` | +| {ref}`Undamped Oscillator ` | 6 | `UndampedOscillator()` | +| {ref}`Webster et al. (1996) 2D ` | 2 | `Webster2D()` | +| {ref}`Welch et al. (1992) ` | 20 | `Welch1992()` | +| {ref}`Wing Weight ` | 10 | `WingWeight()` | In a Python terminal, you can list all the available functions relevant for metamodeling applications using ``list_functions()`` diff --git a/docs/fundamentals/sensitivity.md b/docs/fundamentals/sensitivity.md index 20df329..a686761 100644 --- a/docs/fundamentals/sensitivity.md +++ b/docs/fundamentals/sensitivity.md @@ -18,34 +18,35 @@ kernelspec: The table below listed the available test functions typically used in the comparison of sensitivity analysis methods. -| Name | Input Dimension | Constructor | -|:-----------------------------------------------------------------------------------------------:|:---------------:|:------------------------:| -| {ref}`Borehole ` | 8 | `Borehole()` | -| {ref}`Bratley et al. (1992) A ` | M | `Bratley1992a()` | -| {ref}`Bratley et al. (1992) B ` | M | `Bratley1992b()` | -| {ref}`Bratley et al. (1992) C ` | M | `Bratley1992c()` | -| {ref}`Bratley et al. (1992) D ` | M | `Bratley1992d()` | -| {ref}`Damped Oscillator ` | 7 | `DampedOscillator()` | -| {ref}`Flood ` | 8 | `Flood()` | -| {ref}`Friedman (6D) ` | 6 | `Friedman6D()` | -| {ref}`Genz (Corner Peak) ` | M | `GenzCornerPeak()` | -| {ref}`Genz (Discontinuous) ` | M | `GenzDiscontinuous()` | -| {ref}`Ishigami ` | 3 | `Ishigami()` | -| {ref}`Linkletter et al. (2006) Decreasing Coefficients ` | 10 | `LinkletterDecCoeffs()` | -| {ref}`Linkletter et al. (2006) Linear ` | 10 | `LinkletterLinear()` | -| {ref}`Moon (2010) 3D ` | 3 | `Moon3D()` | -| {ref}`Morris et al. (2006) ` | M | `Morris2006()` | -| {ref}`OTL Circuit ` | 6 / 20 | `OTLCircuit()` | -| {ref}`Piston Simulation ` | 7 / 20 | `Piston()` | -| {ref}`Simple Portfolio Model ` | 3 | `Portfolio3D()` | -| {ref}`SaltelliLinear ` | M | `SaltelliLinear()` | -| {ref}`Sobol'-G ` | M | `SobolG()` | -| {ref}`Sobol'-G* ` | M | `SobolGStar()` | -| {ref}`Sobol'-Levitan ` | M | `SobolLevitan()` | -| {ref}`Solar Cell Model ` | 5 | `SolarCell()` | -| {ref}`Sulfur ` | 9 | `Sulfur()` | -| {ref}`Welch et al. (1992) ` | 20 | `Welch1992()` | -| {ref}`Wing Weight ` | 10 | `WingWeight()` | +| Name | Input Dimension | Constructor | +|:----------------------------------------------------------------------------------------------:|:---------------:|:-----------------------:| +| {ref}`Borehole ` | 8 | `Borehole()` | +| {ref}`Bratley et al. (1992) A ` | M | `Bratley1992a()` | +| {ref}`Bratley et al. (1992) B ` | M | `Bratley1992b()` | +| {ref}`Bratley et al. (1992) C ` | M | `Bratley1992c()` | +| {ref}`Bratley et al. (1992) D ` | M | `Bratley1992d()` | +| {ref}`Damped Oscillator ` | 7 | `DampedOscillator()` | +| {ref}`Flood ` | 8 | `Flood()` | +| {ref}`Friedman (6D) ` | 6 | `Friedman6D()` | +| {ref}`Genz (Corner Peak) ` | M | `GenzCornerPeak()` | +| {ref}`Genz (Discontinuous) ` | M | `GenzDiscontinuous()` | +| {ref}`Ishigami ` | 3 | `Ishigami()` | +| {ref}`Linkletter et al. (2006) Decreasing Coefficients ` | 10 | `LinkletterDecCoeffs()` | +| {ref}`Linkletter et al. (2006) Linear ` | 10 | `LinkletterLinear()` | +| {ref}`Linkletter et al. (2006) Sine ` | 10 | `LinkletterSine()` | +| {ref}`Moon (2010) 3D ` | 3 | `Moon3D()` | +| {ref}`Morris et al. (2006) ` | M | `Morris2006()` | +| {ref}`OTL Circuit ` | 6 / 20 | `OTLCircuit()` | +| {ref}`Piston Simulation ` | 7 / 20 | `Piston()` | +| {ref}`Simple Portfolio Model ` | 3 | `Portfolio3D()` | +| {ref}`SaltelliLinear ` | M | `SaltelliLinear()` | +| {ref}`Sobol'-G ` | M | `SobolG()` | +| {ref}`Sobol'-G* ` | M | `SobolGStar()` | +| {ref}`Sobol'-Levitan ` | M | `SobolLevitan()` | +| {ref}`Solar Cell Model ` | 5 | `SolarCell()` | +| {ref}`Sulfur ` | 9 | `Sulfur()` | +| {ref}`Welch et al. (1992) ` | 20 | `Welch1992()` | +| {ref}`Wing Weight ` | 10 | `WingWeight()` | In a Python terminal, you can list all the available functions relevant for metamodeling applications using ``list_functions()`` diff --git a/docs/test-functions/available.md b/docs/test-functions/available.md index c9eee7d..38938fc 100644 --- a/docs/test-functions/available.md +++ b/docs/test-functions/available.md @@ -68,6 +68,7 @@ regardless of their typical applications. | {ref}`Lim et al. (2002) Polynomial ` | 2 | `LimPoly()` | | {ref}`Linkletter et al. (2006) Decreasing Coefficients ` | 10 | `LinkletterDecCoeffs()` | | {ref}`Linkletter et al. (2006) Linear ` | 10 | `LinkletterLinear()` | +| {ref}`Linkletter et al. (2006) Sine ` | 10 | `LinkletterSine()` | | {ref}`McLain S1 ` | 2 | `McLainS1()` | | {ref}`McLain S2 ` | 2 | `McLainS2()` | | {ref}`McLain S3 ` | 2 | `McLainS3()` | diff --git a/docs/test-functions/linkletter-dec-coeffs.md b/docs/test-functions/linkletter-dec-coeffs.md index 0224783..d970149 100644 --- a/docs/test-functions/linkletter-dec-coeffs.md +++ b/docs/test-functions/linkletter-dec-coeffs.md @@ -21,12 +21,12 @@ import matplotlib.pyplot as plt import uqtestfuns as uqtf ``` -The linear function is a ten-dimensional, scalar-valued function whose +The function is a ten-dimensional, scalar-valued function whose coefficients are decreasing. Only the first eight input variables are active, while the rest is inert. The function was used in {cite}`Linkletter2006` to demonstrate a variable selection method (i.e., sensitivity analysis) -in the context of Gaussian process metamodeling: +in the context of Gaussian process metamodeling. ```{note} Linkletter et al. {cite}`Linkletter2006` introduced four ten-dimensional @@ -39,6 +39,9 @@ in the context of Gaussian process metamodeling: - {ref}`Linear with decreasing coefficients ` function features a slightly more complex linear function with eight active input variables (out of 10). (_this function_) +- {ref}`Sine ` function features only two + active input variables (out of 10); the effect of the two inputs on + the output, however, is very different. ``` diff --git a/docs/test-functions/linkletter-linear.md b/docs/test-functions/linkletter-linear.md index addae96..638a637 100644 --- a/docs/test-functions/linkletter-linear.md +++ b/docs/test-functions/linkletter-linear.md @@ -21,11 +21,11 @@ import matplotlib.pyplot as plt import uqtestfuns as uqtf ``` -The linear function is a ten-dimensional, scalar-valued function. +The function is a ten-dimensional, scalar-valued function. Only the first four input variables are active, while the rest is inert. The function was used in {cite}`Linkletter2006` to demonstrate a variable selection method (i.e., sensitivity analysis) -in the context of Gaussian process metamodeling: +in the context of Gaussian process metamodeling. ```{note} Linkletter et al. {cite}`Linkletter2006` introduced four ten-dimensional @@ -39,6 +39,9 @@ in the context of Gaussian process metamodeling: - {ref}`Linear with decreasing coefficients ` function features a slightly more complex linear function with eight active input variables (out of 10). +- {ref}`Sine ` function features only two + active input variables (out of 10); the effect of the two inputs on + the output, however, is very different. ``` diff --git a/docs/test-functions/linkletter-sine.md b/docs/test-functions/linkletter-sine.md new file mode 100644 index 0000000..ae31ac5 --- /dev/null +++ b/docs/test-functions/linkletter-sine.md @@ -0,0 +1,182 @@ +--- +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:linkletter-sine)= +# Sine Function from Linkletter et al. (2006) + +```{code-cell} ipython3 +import numpy as np +import matplotlib.pyplot as plt +import uqtestfuns as uqtf +``` + +The function is a ten-dimensional, scalar-valued function. +Only the first two input variables are active, while the rest is inert. +The function was used in {cite}`Linkletter2006` to demonstrate a variable +selection method (i.e., sensitivity analysis) +in the context of Gaussian process metamodeling. + +```{note} +Linkletter et al. {cite}`Linkletter2006` introduced four ten-dimensional +analytical test functions with some of the input variables inert. +They are used to demonstrate a variable selection method (i.e., screening) +in the context of Gaussian process metamodeling: + +- {ref}`Linear ` function features + a simple function with four active input variables (out of 10). +- {ref}`Linear with decreasing coefficients ` + function features a slightly more complex linear function with eight active + input variables (out of 10). +- {ref}`Sine ` function features only two + active input variables (out of 10); the effect of the two inputs on + the output, however, is very different. (_this function_). +``` + +Because the function is effectively two dimensional, the surface and contour +plots are shown below. + +```{code-cell} ipython3 +:tags: [remove-input] + +from mpl_toolkits.axes_grid1 import make_axes_locatable + +my_fun = uqtf.LinkletterSine() + +# --- Create 2D data +xx_1d = np.linspace(0.0, 1.0, 1000)[:, np.newaxis] +mesh_2d = np.meshgrid(xx_1d, xx_1d) +xx_2d = np.array(mesh_2d).T.reshape(-1, 2) +xx = my_fun.prob_input.get_sample(len(xx_2d)) +xx[:,:2] = xx_2d +yy_2d = my_fun(xx) + +# --- Create two-dimensional plots +fig = plt.figure(figsize=(10, 5)) + +# Surface +axs_1 = plt.subplot(121, projection='3d') +axs_1.plot_surface( + mesh_2d[0], + mesh_2d[1], + yy_2d.reshape(1000,1000).T, + linewidth=0, + cmap="plasma", + antialiased=False, + alpha=0.5 +) +axs_1.set_xlabel("$x_1$", fontsize=14) +axs_1.set_ylabel("$x_2$", fontsize=14) +axs_1.set_zlabel("$\mathcal{M}(x_1, x_2)$", fontsize=14) +axs_1.set_title("Surface plot of LinkletterSine", fontsize=14) + +# Contour +axs_2 = plt.subplot(122) +cf = axs_2.contourf( + mesh_2d[0], mesh_2d[1], yy_2d.reshape(1000, 1000).T, cmap="plasma", levels=10, +) +axs_2.set_xlabel("$x_1$", fontsize=14) +axs_2.set_ylabel("$x_2$", fontsize=14) +axs_2.set_title("Contour plot of LinkletterSine", fontsize=14) +divider = make_axes_locatable(axs_2) +cax = divider.append_axes('right', size='5%', pad=0.05) +fig.colorbar(cf, cax=cax, orientation='vertical') +axs_2.axis('scaled') + +fig.tight_layout(pad=4.0) +plt.gcf().set_dpi(75); +``` + + +## Test function instance + +To create a default instance of the test function: + +```{code-cell} ipython3 +my_testfun = uqtf.LinkletterSine() +``` + +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}) = \sin{(x_1)} + \sin{(5 x_2)}, +$$ + +where $\boldsymbol{x} = \left( x_1, \ldots x_{10} \right)$ +is the ten-dimensional vector of input variables further defined below. +Notice that only two out of ten input variables are active. + +```{note} +In the original paper, the function was added with an independent identically +distributed (i.i.d) noise from $\mathcal{N}(0, \sigma)$ +with a standard deviation $\sigma = 0.05$. + +Furthermore, also in the original paper, a batch of data is generated from +the function and then standardized to have mean $0.0$ and standard deviation +$1.0$. + +The implementation of UQTestFuns does not include any error addition +or standardization. However, these processes can be done manually +after the data is generated. +``` + +## 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. (7), Example 3, in {cite}`Linkletter2006`. diff --git a/src/uqtestfuns/test_functions/__init__.py b/src/uqtestfuns/test_functions/__init__.py index bc2cec8..a139579 100644 --- a/src/uqtestfuns/test_functions/__init__.py +++ b/src/uqtestfuns/test_functions/__init__.py @@ -35,7 +35,7 @@ from .hyper_sphere import HyperSphere from .ishigami import Ishigami from .lim import LimPoly, LimNonPoly -from .linkletter import LinkletterLinear, LinkletterDecCoeffs +from .linkletter import LinkletterLinear, LinkletterDecCoeffs, LinkletterSine from .oakley2002 import Oakley1D from .otl_circuit import OTLCircuit from .mclain import McLainS1, McLainS2, McLainS3, McLainS4, McLainS5 @@ -107,6 +107,7 @@ "LimPoly", "LinkletterDecCoeffs", "LinkletterLinear", + "LinkletterSine", "Oakley1D", "OTLCircuit", "McLainS1", diff --git a/src/uqtestfuns/test_functions/linkletter.py b/src/uqtestfuns/test_functions/linkletter.py index d1aa41e..140e0b8 100644 --- a/src/uqtestfuns/test_functions/linkletter.py +++ b/src/uqtestfuns/test_functions/linkletter.py @@ -8,8 +8,9 @@ Available functions are: -- Linear function with four active input variables.. +- Linear function with four active input variables. - Linear function with decreasing coefficients, eight active input variables. +- Sine function with two active input variables. References ---------- @@ -22,10 +23,21 @@ import numpy as np -from uqtestfuns.core.custom_typing import ProbInputSpecs +from uqtestfuns.core.custom_typing import MarginalSpecs, ProbInputSpecs from uqtestfuns.core.uqtestfun_abc import UQTestFunFixDimABC -__all__ = ["LinkletterLinear", "LinkletterDecCoeffs"] + +MARGINALS_LINKLETTER2006: MarginalSpecs = [ + { + "name": f"x_{i + 1}", + "distribution": "uniform", + "parameters": [0, 1], + "description": None, + } + for i in range(10) +] + +__all__ = ["LinkletterLinear", "LinkletterDecCoeffs", "LinkletterSine"] def evaluate_linear(xx: np.ndarray) -> np.ndarray: @@ -42,6 +54,10 @@ def evaluate_linear(xx: np.ndarray) -> np.ndarray: np.ndarray The output of the test function evaluated on the input values. The output is a 1-dimensional array of length N. + + Notes + ----- + - Only the first four input variables are active; the rest is inactive. """ yy = 0.2 * np.sum(xx[:, :4], axis=1) @@ -62,6 +78,10 @@ def evaluate_dec_coeffs(xx: np.ndarray) -> np.ndarray: np.ndarray The output of the test function evaluated on the input values. The output is a 1-dimensional array of length N. + + Notes + ----- + - Only the first eight input variables are active; the rest is inactive. """ exps = np.arange(8) # 8 input variables are active coeffs = 0.2 / 2**exps @@ -71,11 +91,37 @@ def evaluate_dec_coeffs(xx: np.ndarray) -> np.ndarray: return yy +def evaluate_sine(xx: np.ndarray) -> np.ndarray: + """Evaluate the sine function from Linkletter et al. (2006). + + Parameters + ---------- + xx : np.ndarray + M-Dimensional input values given by an N-by-10 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. + + Notes + ----- + - Only the first two input variables are active; the rest is inactive. + """ + yy = np.sin(xx[:, 0]) + np.sin(5 * xx[:, 1]) + + return yy + + class LinkletterLinear(UQTestFunFixDimABC): """A concrete implementation of the linear function.""" _tags = ["metamodeling", "sensitivity"] - _description = "Linear function from Linkletter et al. (2006)" + _description = ( + "Linear function with 4 active inputs from Linkletter et al. (2006)" + ) _available_inputs: ProbInputSpecs = { "Linkletter2006": { "function_id": "LinkletterLinear", @@ -83,15 +129,7 @@ class LinkletterLinear(UQTestFunFixDimABC): "Input specification for the linear test function Eq. (5)" "from Linkletter et al. (2006)" ), - "marginals": [ - { - "name": f"x_{i + 1}", - "distribution": "uniform", - "parameters": [0, 1], - "description": None, - } - for i in range(10) - ], + "marginals": MARGINALS_LINKLETTER2006, "copulas": None, }, } @@ -105,8 +143,8 @@ class LinkletterDecCoeffs(UQTestFunFixDimABC): _tags = ["metamodeling", "sensitivity"] _description = ( - "Linear function with decreasing coefficients from Linkletter et al. " - "(2006)" + "Linear function with decreasing coefficients (8 active inputs) " + "from Linkletter et al. (2006)" ) _available_inputs: ProbInputSpecs = { "Linkletter2006": { @@ -115,18 +153,33 @@ class LinkletterDecCoeffs(UQTestFunFixDimABC): "Input specification for the linear test function with " "decreasing coefficients Eq. (6) from Linkletter et al. (2006)" ), - "marginals": [ - { - "name": f"x_{i + 1}", - "distribution": "uniform", - "parameters": [0, 1], - "description": None, - } - for i in range(10) - ], + "marginals": MARGINALS_LINKLETTER2006, "copulas": None, }, } _available_parameters = None evaluate = staticmethod(evaluate_dec_coeffs) # type: ignore + + +class LinkletterSine(UQTestFunFixDimABC): + """A concrete implementation of the sine function.""" + + _tags = ["metamodeling", "sensitivity"] + _description = ( + "Sine function with 2 active inputs from Linkletter et al. (2006)" + ) + _available_inputs: ProbInputSpecs = { + "Linkletter2006": { + "function_id": "LinkletterSine", + "description": ( + "Input specification for the sine test function with Eq. (7)" + "from Linkletter et al. (2006)" + ), + "marginals": MARGINALS_LINKLETTER2006, + "copulas": None, + }, + } + _available_parameters = None + + evaluate = staticmethod(evaluate_sine) # type: ignore