Skip to content
This repository has been archived by the owner on Dec 21, 2023. It is now read-only.

Commit

Permalink
feat: add function configurations (#8)
Browse files Browse the repository at this point in the history
* refactor: set positional-only and keyword-only

* feat: add function configurations
  • Loading branch information
estripling committed Apr 30, 2023
1 parent 31809ba commit 4610d34
Show file tree
Hide file tree
Showing 6 changed files with 181 additions and 51 deletions.
145 changes: 110 additions & 35 deletions docs/source/fBench-functions.ipynb

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/fbench/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@

__version__ = metadata.version("fbench")

from .config import *
from .function import *
from .validation import *
from .visualization import *

del (
metadata,
config,
function,
validation,
visualization,
Expand Down
45 changes: 45 additions & 0 deletions src/fbench/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import numpy as np
import toolz

from fbench import function, structure

__all__ = ("FUNCTION_CONFIGURATIONS",)


FUNCTION_CONFIGURATIONS = {
"Ackley": structure.FunctionConfig(
func=function.ackley,
x_bounds=(-5, 5),
y_bounds=(-5, 5),
global_minimum_x=(0, 0),
global_minimum_fx=0,
),
"Rastrigin": structure.FunctionConfig(
func=function.rastrigin,
x_bounds=(-5.12, 5.12),
y_bounds=(-5.12, 5.12),
global_minimum_x=(0, 0),
global_minimum_fx=0,
),
"Rosenbrock": structure.FunctionConfig(
func=function.rosenbrock,
x_bounds=(-2, 2),
y_bounds=(-2, 2),
global_minimum_x=(1, 1),
global_minimum_fx=0,
),
"Rosenbrock_log1p": structure.FunctionConfig(
func=toolz.compose_left(function.rosenbrock, np.log1p),
x_bounds=(-2, 2),
y_bounds=(-2, 2),
global_minimum_x=(1, 1),
global_minimum_fx=0,
),
"Sphere": structure.FunctionConfig(
func=function.sphere,
x_bounds=(-2, 2),
y_bounds=(-2, 2),
global_minimum_x=(0, 0),
global_minimum_fx=0,
),
}
12 changes: 11 additions & 1 deletion src/fbench/structure.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import NamedTuple
from typing import Callable, NamedTuple, Optional, Tuple

import numpy as np

Expand All @@ -11,3 +11,13 @@ class CoordinateMatrices(NamedTuple):
x: np.ndarray
y: np.ndarray
z: np.ndarray


class FunctionConfig(NamedTuple):
"""An immutable data structure for a function configuration."""

func: Callable[[np.ndarray], float]
x_bounds: Tuple[float, float]
y_bounds: Tuple[float, float]
global_minimum_x: Optional[np.ndarray]
global_minimum_fx: Optional[float]
25 changes: 12 additions & 13 deletions src/fbench/visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ def get_kws_surface__base(cls):
antialiased=True,
linewidth=0.1,
alpha=0.61803,
zorder=0,
)

@classmethod
Expand All @@ -91,7 +92,7 @@ def get_kws_surface__YlOrBr_r(cls):


@toolz.curry
def create_contour_plot(coord, kws_contourf=None, kws_contour=None, ax=None):
def create_contour_plot(coord, /, *, kws_contourf=None, kws_contour=None, ax=None):
"""Create a contour plot from X, Y, Z coordinate matrices.
Parameters
Expand Down Expand Up @@ -178,14 +179,16 @@ def create_coordinates3d(func, x_coord, y_coord=None, /):
[2., 1., 2.]]))
"""
x_coord = validation.check_vector(x_coord, min_elements=2)
y_coord = validation.check_vector(y_coord, min_elements=2) if y_coord else x_coord
y_coord = (
x_coord if y_coord is None else validation.check_vector(y_coord, min_elements=2)
)
x, y = np.meshgrid(x_coord, y_coord)
z = np.apply_along_axis(func1d=func, axis=1, arr=np.c_[x.ravel(), y.ravel()])
return structure.CoordinateMatrices(x, y, z.reshape(x.shape))


@toolz.curry
def create_surface_plot(coord, kws_surface=None, kws_contourf=None, fig=None):
def create_surface_plot(coord, /, *, kws_surface=None, kws_contourf=None, ax=None):
"""Create a surface plot from X, Y, Z coordinate matrices.
Parameters
Expand All @@ -200,26 +203,22 @@ def create_surface_plot(coord, kws_surface=None, kws_contourf=None, fig=None):
The kwargs are passed to ``mpl_toolkits.mplot3d.axes3d.Axes3D.contourf``.
By default, using configuration: ``PlotConfig.get_kws_contourf__YlOrBr_r()``.
Optionally specify a dict of keyword arguments to update configurations.
fig: matplotlib.figure.Figure, default=None
Optionally supply a ``Figure`` object.
If None, the current ``Figure`` object is retrieved.
ax: mpl_toolkits.mplot3d.axes3d.Axes3D, default=None
Optionally supply an ``Axes3D`` object.
If None, the current ``Axes3D`` object is retrieved.
Returns
-------
fig : matplotlib.figure.Figure
The ``Figure`` object.
ax : mpl_toolkits.mplot3d.axes3d.Axes3D
The ``Axes3D`` object.
The ``Axes3D`` object of the surface.
Notes
-----
- Function is curried.
- Examples are shown in the
`Overview of fBench functions <https://fbench.readthedocs.io/en/stable/fBench-functions.html)>`_.
""" # noqa: E501
fig = fig or plt.gcf()
ax = fig.add_subplot(projection="3d")
ax = ax or plt.gcf().add_subplot(projection="3d")

# Make background and axis panes transparent
ax.patch.set_alpha(0.0)
Expand All @@ -237,4 +236,4 @@ def create_surface_plot(coord, kws_surface=None, kws_contourf=None, fig=None):
settings_contourf["offset"] = settings_contourf.get("offset", 0) + coord.z.min()
ax.contourf(coord.x, coord.y, coord.z, **settings_contourf)

return fig, ax
return ax
3 changes: 1 addition & 2 deletions tests/test_visualization.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,10 @@ def test_create_coordinates3d():


def test_create_surface_plot():
fig, ax = toolz.pipe(
ax = toolz.pipe(
[-1, 0, 1],
fbench.create_coordinates3d(fbench.sphere),
fbench.create_surface_plot(),
)
plt.close()
assert isinstance(fig, matplotlib.figure.Figure)
assert isinstance(ax, mpl_toolkits.mplot3d.Axes3D)

0 comments on commit 4610d34

Please sign in to comment.