Repository: damar-wicaksono/uqtestfuns (language: python)

Issue:
Add the one-dimensional test function from Higdon (2002)
The test function reads:

$$
\mathcal{M}(x) = \sin{\left(2 \pi \frac{x}{10} \right)} + 0.2 \sin{\left(2 \pi \frac{x}{2.5} \right)},
$$

where $x$ is uniformly distributed in $[1, 10]$.

The function was introduced in [^Higdon2002] as a test function for a multi-resolution spatial modeling technique.
The first term in the equation above gives large scale variation that slowly varies while the second term gives small scale variation (five times smaller) but varies faster (four times faster). In the paper, an i.i.d noise of $\mathcal{N}(0, 1)$ is added to the response.

I would propose the name of `HigdonSine`.

[^Higdon2002]: D. Higdon, “Space and Space-Time Modeling using Process Convolutions,” in *Quantitative Methods for Current Environmental Issues*, C. W. Anderson, V. Barnett, P. C. Chatwin, and A. H. El-Shaarawi, Eds., London: Springer London, 2002, pp. 37–56. doi: [10.1007/978-1-4471-0657-9\_2](https://doi.org/10.1007/978-1-4471-0657-9_2).

[^location]: See Section 4.1 in [^Higdon2002].


Discussion / hints:

Fix patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index bf71e5a..5994478 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -9,7 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
 
 ### Added
 
-- The One-dimensional sine function from Holsclaw et al. (2013) for
+- The one-dimensional sine function from Higdon (2002) featuring behaviors
+  that are different in two scales; for metamodeling (multi-resolution)
+  exercises.
+- The one-dimensional sine function from Holsclaw et al. (2013) for
   metamodeling exercises.
 - The M-dimensional discontinuous function from Genz (1984) for integration and
   sensitivity analysis exercises; one parameter set from the literature
diff --git a/docs/_toc.yml b/docs/_toc.yml
index a685320..3140359 100644
--- a/docs/_toc.yml
+++ b/docs/_toc.yml
@@ -63,7 +63,7 @@ parts:
           - file: test-functions/convex-fail-domain
             title: Convex Failure Domain
           - file: test-functions/currin-sine
-            title: Currin Sine
+            title: Currin et al. (1988) Sine
           - file: test-functions/damped-cosine
             title: Damped Cosine
           - file: test-functions/damped-oscillator
@@ -108,8 +108,10 @@ parts:
             title: Genz (Product Peak)
           - file: test-functions/gramacy-1d-sine
             title: Gramacy (2007) 1D Sine
+          - file: test-functions/higdon-sine
+            title: Higdon (2002) Sine
           - file: test-functions/holsclaw-sine
-            title: Holsclaw Sine
+            title: Holsclaw et al. (2013) Sine
           - file: test-functions/hyper-sphere
             title: Hyper-sphere Bound
           - file: test-functions/ishigami
diff --git a/docs/fundamentals/metamodeling.md b/docs/fundamentals/metamodeling.md
index 5d53fcf..fb3710e 100644
--- a/docs/fundamentals/metamodeling.md
+++ b/docs/fundamentals/metamodeling.md
@@ -41,6 +41,7 @@ in the comparison of metamodeling approaches.
 |          {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()`       |
diff --git a/docs/references.bib b/docs/references.bib
index cc4a60e..9fd1f3a 100644
--- a/docs/references.bib
+++ b/docs/references.bib
@@ -1020,4 +1020,16 @@ @Article{Holsclaw2013
   doi     = {10.1080/00401706.2012.723918},
 }
 
+@InBook{Higdon2002,
+  author    = {Higdon, Dave},
+  chapter   = {Space and space-time modeling using process convolutions},
+  editor    = {C. W. Anderson, V. Barnett, P. C. Chatwin and El-Shaarawi, A. H.},
+  pages     = {37--56},
+  publisher = {Springer London},
+  title     = {Quantitative methods for current environmental issues},
+  year      = {2002},
+  isbn      = {9781447106579},
+  doi       = {10.1007/978-1-4471-0657-9_2},
+}
+
 @Comment{jabref-meta: databaseType:bibtex;}


Test patch:
diff --git a/docs/test-functions/available.md b/docs/test-functions/available.md
index 80a3148..4104209 100644
--- a/docs/test-functions/available.md
+++ b/docs/test-functions/available.md
@@ -57,6 +57,7 @@ regardless of their typical applications.
 |             {ref}`Genz (Oscillatory) <test-functions:genz-oscillatory>`             |        M        |       `GenzOscillatory()`       |
 |            {ref}`Genz (Product Peak) <test-functions:genz-product-peak>`            |        M        |       `GenzProductPeak()`       |
 |           {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}`Hyper-sphere Bound <test-functions:hyper-sphere>`               |        2        |         `HyperSphere()`         |
 |                      {ref}`Ishigami <test-functions:ishigami>`                      |        3        |          `Ishigami()`           |
diff --git a/docs/test-functions/higdon-sine.md b/docs/test-functions/higdon-sine.md
new file mode 100644
index 0000000..791c0d1
--- /dev/null
+++ b/docs/test-functions/higdon-sine.md
@@ -0,0 +1,126 @@
+---
+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:higdon-sine)=
+# Sine Function from Higdon (2002)
+
+```{code-cell} ipython3
+import numpy as np
+import matplotlib.pyplot as plt
+import uqtestfuns as uqtf
+```
+
+The function is a simple one-dimensional, scalar-valued test function.
+It was featured in {cite}`Higdon2002` as an example for illustrating
+a multi-resolution spatial modeling technique.
+
+A plot of the function is shown below..
+
+```{code-cell} ipython3
+:tags: [remove-input]
+
+rng = np.random.default_rng(93025)
+my_testfun = uqtf.HigdonSine()
+
+xx = np.linspace(1.0, 10.0, 100)[:, np.newaxis]
+yy = my_testfun(xx)
+
+xx_train = np.linspace(1, 10, 30)[:, np.newaxis]
+yy_train = my_testfun(xx_train) + rng.normal(0, 0.1, size=(30, 1))
+
+# --- Create the plot
+plt.plot(xx, yy, color="#8da0cb")
+plt.scatter(xx_train, yy_train, color="#8da0cb")
+plt.grid()
+plt.xlabel("$x$")
+plt.ylabel("$\mathcal{M}(x)$")
+plt.gcf().tight_layout(pad=3.0)
+plt.gcf().set_dpi(150);
+```
+
+```{note}
+In the original paper, the function was evaluated at 30 equispaced points
+in $[1.0, 10.0]$ with added i.i.d noise from $\mathcal{N} \sim (0, 0.1)$;
+these points are shown in the above plot.
+```
+
+## Test function instance
+
+To create a default instance of the test function:
+
+```{code-cell} ipython3
+my_testfun = uqtf.HigdonSine()
+```
+
+Check if it has been correctly instantiated:
+
+```{code-cell} ipython3
+print(my_testfun)
+```
+
+## Description
+
+The test function is analytically defined as follows[^location]:
+
+$$
+\mathcal{M}(x) = \sin{\left(2 \pi \frac{x}{10} \right)} + 0.2 \, \sin{\left(2 \pi \frac{x}{2.5} \right)},
+$$
+
+where $x$ is further defined below.
+
+Notice that the second term of the equation gives variation 5 times smaller
+but 4 times faster.
+
+## 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 Section 4.1 in {cite}`Higdon2002`.
diff --git a/src/uqtestfuns/test_functions/__init__.py b/src/uqtestfuns/test_functions/__init__.py
index 4e4c966..c7165ff 100644
--- a/src/uqtestfuns/test_functions/__init__.py
+++ b/src/uqtestfuns/test_functions/__init__.py
@@ -29,6 +29,7 @@
     GenzProductPeak,
 )
 from .gramacy2007 import Gramacy1DSine
+from .higdon_sine import HigdonSine
 from .holsclaw_sine import HolsclawSine
 from .hyper_sphere import HyperSphere
 from .ishigami import Ishigami
@@ -93,6 +94,7 @@
     "GenzOscillatory",
     "GenzProductPeak",
     "Gramacy1DSine",
+    "HigdonSine",
     "HolsclawSine",
     "HyperSphere",
     "Ishigami",
diff --git a/src/uqtestfuns/test_functions/higdon_sine.py b/src/uqtestfuns/test_functions/higdon_sine.py
new file mode 100644
index 0000000..efcb438
--- /dev/null
+++ b/src/uqtestfuns/test_functions/higdon_sine.py
@@ -0,0 +1,73 @@
+"""
+Module with an implementation of the Sine function from Higdon (2002).
+
+The one-dimensional, scalar-valued function was featured in [1] as an example
+for a multi-resolution spatial modeling technique.
+
+References
+----------
+
+1. D. Higdon, “Space and Space-Time Modeling using Process Convolutions,”
+   in Quantitative Methods for Current Environmental Issues, C. W. Anderson,
+   V. Barnett, P. C. Chatwin, and A. H. El-Shaarawi, Eds.,
+   London: Springer London, 2002, pp. 37–56.
+   DOI: 10.1007/978-1-4471-0657-9_2.
+
+"""
+
+import numpy as np
+
+from uqtestfuns.core.custom_typing import ProbInputSpecs
+from uqtestfuns.core.uqtestfun_abc import UQTestFunFixDimABC
+
+__all__ = ["HigdonSine"]
+
+
+AVAILABLE_INPUTS: ProbInputSpecs = {
+    "Higdon2002": {
+        "function_id": "HigdonSine",
+        "description": (
+            "Input model for the sine function from Higdon (2002)"
+        ),
+        "marginals": [
+            {
+                "name": "x",
+                "distribution": "uniform",
+                "parameters": [1.0, 10.0],
+                "description": None,
+            },
+        ],
+        "copulas": None,
+    },
+}
+
+
+def evaluate(xx: np.ndarray) -> np.ndarray:
+    """Evaluate the Higdon sine function on a set of input values.
+
+    Parameters
+    ----------
+    xx : np.ndarray
+        1-Dimensional input values given by an N-by-1 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.sin(2 * np.pi * xx / 10) + 0.2 * np.sin(2 * np.pi * xx / 2.5)
+
+    return yy
+
+
+class HigdonSine(UQTestFunFixDimABC):
+    """A concrete implementation of the Higdon sine function."""
+
+    _tags = ["metamodeling"]
+    _description = "Sine function from Higdon (2002)"
+    _available_inputs = AVAILABLE_INPUTS
+    _available_parameters = None
+
+    evaluate = staticmethod(evaluate)  # type: ignore