Skip to content

Commit b2855f3

Browse files
committed
Update: further test functions
1 parent eaf4c9b commit b2855f3

2 files changed

Lines changed: 213 additions & 21 deletions

File tree

test/retrieve/oe/test_oe_jax.py

Lines changed: 107 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,132 @@
22
# License: MIT
33

44
import unittest
5+
from typing import Literal
56

67
import numpy as np
78

8-
from uncertaintyx.f.jax import ToF
9+
from uncertaintyx.f.jax import Cigar
10+
from uncertaintyx.f.jax import DifferentPowers
11+
from uncertaintyx.f.jax import Ellipsoid
12+
from uncertaintyx.f.jax import Rosenbrock
13+
from uncertaintyx.f.jax import Sphere
14+
from uncertaintyx.f.jax import Tablet
915
from uncertaintyx.retrieve.oe.jax import OE
1016

1117

12-
class Parabola(ToF):
13-
"""The parabolic test function."""
18+
class OptimalEstimationTest(unittest.TestCase):
19+
"""
20+
Tests optimal estimation.
21+
"""
1422

15-
def __init__(self):
16-
def f(x):
17-
"""The test function."""
18-
return x * x
23+
def setUp(self):
24+
self.rng = np.random.default_rng(5489)
25+
self.M = 50
26+
self.m = 10
1927

20-
super().__init__(f)
28+
def test_sphere(self):
29+
"""The sphere function has a unique minimum at zero."""
30+
f = Sphere()
2131

32+
x = np.square(self.fuzzy(1.0, "x"))
33+
y = np.square(self.fuzzy(0.0, "y"))
34+
result = OE().retrieve(f, x, y)
2235

23-
class OptimalEstimationTest(unittest.TestCase):
24-
"""
25-
Tests EIV regression.
26-
"""
36+
self.assertTrue(np.all(result.info == 0))
37+
self.assertTrue(np.allclose(f.eval(result.xopt), y))
38+
self.assertTrue(np.all(np.isfinite(result.xcov)))
39+
self.assertTrue(np.all(np.isfinite(result.xunc)))
40+
self.assertTrue(np.allclose(result.zvar, 0.0))
41+
self.assertTrue(np.allclose(result.cost, 0.0))
42+
43+
def test_ellipsoid(self):
44+
"""The ellipsoid function has a unique minimum at zero."""
45+
f = Ellipsoid()
2746

28-
def test_parabola(self):
47+
x = self.fuzzy(1.0, "x")
48+
y = self.sharp(0.0, "y")
49+
result = OE().retrieve(f, x, y)
50+
51+
self.assertTrue(np.all(result.info == 0))
52+
self.assertTrue(np.allclose(result.xopt, 0.0))
53+
self.assertTrue(np.all(np.isfinite(result.xcov)))
54+
self.assertTrue(np.all(np.isfinite(result.xunc)))
55+
self.assertTrue(np.allclose(result.zvar, 0.0))
56+
self.assertTrue(np.allclose(result.cost, 0.0))
57+
58+
def test_cigar(self):
59+
"""The cigar function has a unique minimum at zero."""
60+
f = Cigar()
61+
62+
x = self.fuzzy(1.0, "x")
63+
y = self.sharp(0.0, "y")
64+
result = OE().retrieve(f, x, y)
65+
66+
self.assertTrue(np.all(result.info == 0))
67+
self.assertTrue(np.allclose(result.xopt, 0.0))
68+
self.assertTrue(np.all(np.isfinite(result.xcov)))
69+
self.assertTrue(np.all(np.isfinite(result.xunc)))
70+
self.assertTrue(np.allclose(result.zvar, 0.0))
71+
self.assertTrue(np.allclose(result.cost, 0.0))
72+
73+
def test_tablet(self):
74+
"""The tablet function has a unique minimum at zero."""
75+
f = Tablet()
76+
77+
x = self.fuzzy(1.0, "x")
78+
y = self.sharp(0.0, "y")
79+
result = OE().retrieve(f, x, y)
80+
81+
self.assertTrue(np.all(result.info == 0))
82+
self.assertTrue(np.allclose(result.xopt, 0.0))
83+
self.assertTrue(np.all(np.isfinite(result.xcov)))
84+
self.assertTrue(np.all(np.isfinite(result.xunc)))
85+
self.assertTrue(np.allclose(result.zvar, 0.0))
86+
self.assertTrue(np.allclose(result.cost, 0.0))
87+
88+
def test_rosenbrock(self):
2989
"""
30-
Tests the EIV retrieval with a simple parabolic test function.
90+
The Rosenbrock function has a global and a local minimum. The
91+
minimization uses initial values biased toward the global minimum
92+
to establish an unambiguous test condition.
3193
"""
32-
n = 100
94+
f = Rosenbrock()
3395

34-
x = np.ones((n, 1))
35-
y = np.zeros((n, 1))
36-
result = OE().retrieve(Parabola(), x, y)
96+
x = self.fuzzy(3.0, "x")
97+
y = self.sharp(0.0, "y")
98+
result = OE().retrieve(f, x, y)
3799

38100
self.assertTrue(np.all(result.info == 0))
39-
self.assertTrue(np.allclose(result.xopt, 0.0))
40-
self.assertTrue(np.allclose(result.xcov, 0.0))
41-
self.assertTrue(np.allclose(result.xunc, 0.0))
101+
self.assertTrue(np.allclose(result.xopt, 1.0))
102+
self.assertTrue(np.all(np.isfinite(result.xcov)))
103+
self.assertTrue(np.all(np.isfinite(result.xunc)))
42104
self.assertTrue(np.allclose(result.zvar, 0.0))
43105
self.assertTrue(np.allclose(result.cost, 0.0))
44106

107+
def test_different_powers(self):
108+
"""
109+
The different power function has a unique minimum at zero.
110+
Only the value of the cost function is tested, since the
111+
problem is badly scaled.
112+
"""
113+
f = DifferentPowers()
114+
115+
x = self.fuzzy(1.0, "x")
116+
y = self.sharp(0.0, "y")
117+
result = OE().retrieve(f, x, y)
118+
119+
self.assertTrue(np.allclose(result.cost, 0.0))
120+
121+
def fuzzy(self, val, role: Literal["x", "y"]) -> np.ndarray:
122+
"""Returns an array filled with fuzzy values."""
123+
return self.rng.normal(
124+
val, 1.0, (self.M, self.m) if role == "x" else (self.M,)
125+
)
126+
127+
def sharp(self, val, role: Literal["x", "y"]) -> np.ndarray:
128+
"""Returns an array filled with sharp values."""
129+
return np.full((self.M, self.m) if role == "x" else (self.M,), val)
130+
45131

46132
if __name__ == "__main__":
47133
unittest.main()

uncertaintyx/f/jax.py

Lines changed: 106 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,3 +168,109 @@ def lpu(
168168
@property
169169
def f(self) -> Callable[[Array], Array]:
170170
return self._f
171+
172+
173+
class Sphere(ToF):
174+
"""
175+
A test function.
176+
177+
The test function has a global minimum at zero.
178+
"""
179+
180+
def __init__(self):
181+
def f(x):
182+
"""The test function."""
183+
return jnp.sum(jnp.square(x))
184+
185+
super().__init__(f)
186+
187+
188+
class Ellipsoid(ToF):
189+
"""
190+
A test function.
191+
192+
The test function has a global minimum at zero.
193+
All axes are scaled differently.
194+
"""
195+
196+
def __init__(self):
197+
def f(x):
198+
"""The test function."""
199+
m = x.size
200+
p = jnp.pow(1.0e06, jnp.arange(0, m) / (m - 1))
201+
return jnp.sum(p * jnp.square(x))
202+
203+
super().__init__(f)
204+
205+
206+
class Cigar(ToF):
207+
"""
208+
A test function.
209+
210+
The test function has a global minimum at zero.
211+
All but one axes are scaled extremely.
212+
"""
213+
214+
def __init__(self):
215+
def f(x):
216+
"""The test function."""
217+
a = jnp.sum(jnp.square(x[:1]))
218+
b = jnp.sum(jnp.square(x[1:]))
219+
return a + 1.0e06 * b
220+
221+
super().__init__(f)
222+
223+
224+
class Tablet(ToF):
225+
"""
226+
A test function.
227+
228+
The test function has a global minimum at zero.
229+
One axis is scaled extremely.
230+
"""
231+
232+
def __init__(self):
233+
def f(x):
234+
"""The test function."""
235+
a = jnp.sum(jnp.square(x[:1]))
236+
b = jnp.sum(jnp.square(x[1:]))
237+
return 1.0e06 * a + b
238+
239+
super().__init__(f)
240+
241+
242+
class Rosenbrock(ToF):
243+
"""
244+
The Rosenbrock test function.
245+
246+
The Rosenbrock function has a global and a local minimum.
247+
"""
248+
249+
def __init__(self):
250+
def f(x):
251+
"""The Rosenbrock test function."""
252+
a = jnp.square(x[1:] - jnp.square(x[:-1]))
253+
b = jnp.square(1.0 - x[:-1])
254+
return jnp.sum(100.0 * a + b)
255+
256+
super().__init__(f)
257+
258+
259+
class DifferentPowers(ToF):
260+
"""
261+
A test function.
262+
263+
The test function has a global minimum at zero.
264+
Axes are badly scaled.
265+
"""
266+
267+
def __init__(self):
268+
def f(x):
269+
"""The test function."""
270+
m = x.size
271+
p = jnp.pow(
272+
jnp.square(x), 1.0 + (5.0 * jnp.arange(0, m)) / (m - 1)
273+
)
274+
return jnp.sum(p)
275+
276+
super().__init__(f)

0 commit comments

Comments
 (0)