Skip to content

Commit 4eaab73

Browse files
authored
Merge pull request #95 from Anselmoo/add-2d-optimization-functions
feat: Add 2D optimization functions
2 parents d4e3a2f + 95a98f7 commit 4eaab73

File tree

3 files changed

+169
-0
lines changed

3 files changed

+169
-0
lines changed

README.md

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,40 @@ res.save_as_image()
4949

5050
![_](https://github.com/Anselmoo/useful-math-functions/blob/main/docs/extra/images/DeJongN5Function.png?raw=true)
5151

52+
To use the newly added functions:
53+
54+
```python
55+
from umf.functions.optimization.special import HimmelblauFunction
56+
import numpy as np
57+
58+
x = np.linspace(-5, 5, 100)
59+
y = np.linspace(-5, 5, 100)
60+
X, Y = np.meshgrid(x, y)
61+
Z = HimmelblauFunction(X, Y).__eval__
62+
63+
import matplotlib.pyplot as plt
64+
fig = plt.figure()
65+
ax = fig.add_subplot(111, projection="3d")
66+
ax.plot_surface(X, Y, Z, cmap="viridis")
67+
plt.savefig("HimmelblauFunction.png", dpi=300, transparent=True)
68+
```
69+
70+
```python
71+
from umf.functions.optimization.valley_shaped import Rosenbrock2DFunction
72+
import numpy as np
73+
74+
x = np.linspace(-2, 2, 100)
75+
y = np.linspace(-1, 3, 100)
76+
X, Y = np.meshgrid(x, y)
77+
Z = Rosenbrock2DFunction(X, Y).__eval__
78+
79+
import matplotlib.pyplot as plt
80+
fig = plt.figure()
81+
ax = fig.add_subplot(111, projection="3d")
82+
ax.plot_surface(X, Y, Z, cmap="viridis")
83+
plt.savefig("Rosenbrock2DFunction.png", dpi=300, transparent=True)
84+
```
85+
5286
## Documentation
5387

5488
The documentation can be found

umf/functions/optimization/special.py

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
"BraninFunction",
2222
"GoldsteinPriceFunction",
2323
"GoldsteinPriceLogFunction",
24+
"HimmelblauFunction",
2425
"StyblinskiTangFunction",
2526
]
2627

@@ -431,3 +432,75 @@ def __minima__(self) -> MinimaAPI:
431432
MinimaAPI: Minima of the Goldstein-Price function in logarithmic form.
432433
"""
433434
return MinimaAPI(f_x=3, x=tuple(np.array([0, -1])))
435+
436+
437+
class HimmelblauFunction(OptFunction):
438+
r"""Himmelblau function.
439+
440+
The Himmelblau function is a two-dimensional function with four global minima.
441+
442+
Examples:
443+
>>> import matplotlib.pyplot as plt
444+
>>> import numpy as np
445+
>>> from umf.functions.optimization.special import HimmelblauFunction
446+
>>> x = np.linspace(-5, 5, 100)
447+
>>> y = np.linspace(-5, 5, 100)
448+
>>> X, Y = np.meshgrid(x, y)
449+
>>> Z = HimmelblauFunction(X, Y).__eval__
450+
>>> fig = plt.figure()
451+
>>> ax = fig.add_subplot(111, projection="3d")
452+
>>> _ = ax.plot_surface(X, Y, Z, cmap="viridis")
453+
>>> plt.savefig("HimmelblauFunction.png", dpi=300, transparent=True)
454+
455+
Notes:
456+
The Himmelblau function is defined as:
457+
458+
$$
459+
f(x, y) = (x^2 + y - 11)^2 + (x + y^2 - 7)^2
460+
$$
461+
462+
> Reference: Original implementation can be found
463+
> [here](https://www.sfu.ca/~ssurjano/himmel.html).
464+
465+
Args:
466+
*x (UniversalArray): Input data, which has to be two dimensional.
467+
468+
Raises:
469+
OutOfDimensionError: If the dimension of the input data is not 2.
470+
"""
471+
472+
def __init__(self, *x: UniversalArray) -> None:
473+
"""Initialize the function."""
474+
if len(x) != __2d__:
475+
raise OutOfDimensionError(
476+
function_name="Himmelblau",
477+
dimension=__2d__,
478+
)
479+
super().__init__(*x)
480+
481+
@property
482+
def __eval__(self) -> UniversalArray:
483+
"""Evaluate Himmelblau function at x.
484+
485+
Returns:
486+
UniversalArray: Evaluated function value.
487+
"""
488+
x, y = self._x[0], self._x[1]
489+
return (x**2 + y - 11) ** 2 + (x + y**2 - 7) ** 2
490+
491+
@property
492+
def __minima__(self) -> MinimaAPI:
493+
"""Return the minima of the Himmelblau function.
494+
495+
Returns:
496+
MinimaAPI: Minima of the Himmelblau function.
497+
"""
498+
return MinimaAPI(
499+
f_x=0.0,
500+
x=tuple(
501+
np.array([3.0, 2.0]),
502+
np.array([-2.805118, 3.131312]),
503+
np.array([-3.779310, -3.283186]),
504+
np.array([3.584428, -1.848126]),
505+
),
506+
)

umf/functions/optimization/valley_shaped.py

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
__all__: list[str] = [
2121
"DixonPriceFunction",
22+
"Rosenbrock2DFunction",
2223
"RosenbrockFunction",
2324
"SixHumpCamelFunction",
2425
"ThreeHumpCamelFunction",
@@ -280,3 +281,64 @@ def __minima__(self) -> MinimaAPI:
280281
f_x=0.0,
281282
x=tuple(np.array([1.0 for _ in range(len(self._x))])),
282283
)
284+
285+
286+
class Rosenbrock2DFunction(OptFunction):
287+
r"""2D Rosenbrock function.
288+
289+
The 2D Rosenbrock function is a two-dimensional function with a single
290+
global minimum.
291+
292+
Examples:
293+
>>> import matplotlib.pyplot as plt
294+
>>> import numpy as np
295+
>>> from umf.functions.optimization.valley_shaped import Rosenbrock2DFunction
296+
>>> x = np.linspace(-2, 2, 100)
297+
>>> y = np.linspace(-1, 3, 100)
298+
>>> X, Y = np.meshgrid(x, y)
299+
>>> Z = Rosenbrock2DFunction(X, Y).__eval__
300+
>>> fig = plt.figure()
301+
>>> ax = fig.add_subplot(111, projection="3d")
302+
>>> _ = ax.plot_surface(X, Y, Z, cmap="viridis")
303+
>>> plt.savefig("Rosenbrock2DFunction.png", dpi=300, transparent=True)
304+
305+
Notes:
306+
The 2D Rosenbrock function is defined as:
307+
308+
$$
309+
f(x) = 100(x_2 - x_1^2)^2 + (1 - x_1)^2
310+
$$
311+
312+
> Reference: Original implementation can be found
313+
> [here](https://www.sfu.ca/~ssurjano/rosen.html).
314+
315+
Args:
316+
*x (UniversalArray): Input data, which has to be two-dimensional.
317+
318+
Raises:
319+
OutOfDimensionError: If the dimension of the input data is not 2.
320+
"""
321+
322+
def __init__(self, *x: UniversalArray) -> None:
323+
"""Initialize the 2D Rosenbrock function."""
324+
if len(x) != __2d__:
325+
raise OutOfDimensionError(
326+
function_name="Rosenbrock2D",
327+
dimension=__2d__,
328+
)
329+
super().__init__(*x)
330+
331+
@property
332+
def __eval__(self) -> UniversalArray:
333+
"""Evaluate 2D Rosenbrock function at x."""
334+
x_1 = self._x[0]
335+
x_2 = self._x[1]
336+
return 100 * (x_2 - x_1**2) ** 2 + (1 - x_1) ** 2
337+
338+
@property
339+
def __minima__(self) -> MinimaAPI:
340+
"""Return the zero function."""
341+
return MinimaAPI(
342+
f_x=0.0,
343+
x=(1.0, 1.0),
344+
)

0 commit comments

Comments
 (0)