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 plotter (#9)
Browse files Browse the repository at this point in the history
* docs(function.py): update docstrings

* refactor(check_vector): add n_min and n_max parameters

* feat: add create_coordinates2d

* docs: show only visualization module in API

* refactor: rename Config to VizConfig

* refactor: import structure and visualization separately

* feat: add create_line_plot

* test: rename ax to actual

* style: remove bracket

* docs(create_coordinates3d): change type

* feat: add create_discrete_cmap

* feat: add FunctionPlotter

* style: change VizConfig docstring

* refactor: remove config.py

* refactor: fBench-functions.ipynb

* feat: example.ipynb

* refactor: rename visualization module to viz

* style: use capital letter

BREAKING CHANGE: New function signature for check_vector and rename visualization module to viz
  • Loading branch information
estripling committed May 15, 2023
1 parent 6461d1f commit 4c4aa5e
Show file tree
Hide file tree
Showing 16 changed files with 1,342 additions and 451 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ A collection of benchmark functions:

- [Documentation](https://fbench.readthedocs.io/en/stable/index.html)
- [Overview of fBench functions](https://fbench.readthedocs.io/en/stable/fBench-functions.html)
- [Example usage](https://fbench.readthedocs.io/en/stable/example.html)
- [API Reference](https://fbench.readthedocs.io/en/stable/autoapi/fbench/index.html)

## Installation
Expand Down
9 changes: 9 additions & 0 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,15 @@ def skip_util_classes(app, what, name, obj, skip, options):
# https://sphinx-autoapi.readthedocs.io/en/latest/reference/config.html#event-autoapi-skip-member
if what == "module":
skip = True

modules_to_show = ["viz"]
if what == "module" and any(n in name for n in modules_to_show):
skip = False

if what in ("attribute", "method") and name.split(".")[-1].startswith("_"):
# skip private attributes and methods
skip = True

return skip


Expand Down
401 changes: 401 additions & 0 deletions docs/source/example.ipynb

Large diffs are not rendered by default.

111 changes: 76 additions & 35 deletions docs/source/fBench-functions.ipynb

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/source/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
:hidden:
fBench-functions.ipynb
example.ipynb
changelog.md
contributing.md
developers.md
Expand Down
5 changes: 1 addition & 4 deletions src/fbench/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,12 @@

__version__ = metadata.version("fbench")

from .config import *
from . import structure, viz
from .function import *
from .validation import *
from .visualization import *

del (
metadata,
config,
function,
validation,
visualization,
)
45 changes: 0 additions & 45 deletions src/fbench/config.py

This file was deleted.

10 changes: 0 additions & 10 deletions src/fbench/exception.py

This file was deleted.

46 changes: 29 additions & 17 deletions src/fbench/function.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import numpy as np

from fbench import validation
import fbench

__all__ = (
"ackley",
Expand All @@ -13,25 +13,28 @@
def ackley(x, /):
"""Ackley function.
A function :math:`f\\colon \\mathbb{R}^{n} \\rightarrow \\mathbb{R}`
that takes an :math:`n`-vector as input and returns a scalar value.
.. math::
f(\\mathbf{x}) =
-20 \\exp \\left(
-0.2 \\sqrt{ \\frac{1}{n} \\sum_{i=1}^n x_i^2 }
-0.2 \\sqrt{ \\frac{1}{n} \\sum_{i=1}^{n} x_i^2 }
\\right)
- \\exp \\left( \\frac{1}{n} \\sum_{i=1}^n \\cos(2 \\pi x_i) \\right)
- \\exp \\left( \\frac{1}{n} \\sum_{i=1}^{n} \\cos(2 \\pi x_i) \\right)
+ 20
+ e
Parameters
----------
x : array_like
An :math:`n`-dimensional real vector.
The :math:`n`-vector.
Returns
-------
float
Function value at x.
Function value at :math:`\\mathbf{x}`.
References
----------
Expand All @@ -50,7 +53,7 @@ def ackley(x, /):
>>> round(fbench.ackley([1, 2, 3]), 4)
7.0165
"""
x = validation.check_vector(x, min_elements=1)
x = fbench.check_vector(x)
return float(
-20 * np.exp(-0.2 * np.sqrt((x**2).mean()))
- np.exp((np.cos(2 * np.pi * x)).sum() / len(x))
Expand All @@ -62,20 +65,23 @@ def ackley(x, /):
def rastrigin(x, /):
"""Rastrigin function.
A function :math:`f\\colon \\mathbb{R}^{n} \\rightarrow \\mathbb{R}`
that takes an :math:`n`-vector as input and returns a scalar value.
.. math::
f(\\mathbf{x}) =
10n + \\sum_{i=1}^n \\left( x_i^2 - 10 \\cos(2 \\pi x_i) \\right)
10n + \\sum_{i=1}^{n} \\left( x_i^2 - 10 \\cos(2 \\pi x_i) \\right)
Parameters
----------
x : array_like
An :math:`n`-dimensional real vector.
The :math:`n`-vector.
Returns
-------
float
Function value at x.
Function value at :math:`\\mathbf{x}`.
References
----------
Expand All @@ -97,13 +103,16 @@ def rastrigin(x, /):
>>> round(fbench.rastrigin([1, 2, 3]), 4)
14.0
"""
x = validation.check_vector(x, min_elements=1)
x = fbench.check_vector(x)
return float(10 * len(x) + (x**2 - 10 * np.cos(2 * np.pi * x)).sum())


def rosenbrock(x, /):
"""Rosenbrock function.
A function :math:`f\\colon \\mathbb{R}^{n} \\rightarrow \\mathbb{R}`
that takes an :math:`n`-vector as input and returns a scalar value.
.. math::
f(\\mathbf{x}) =
Expand All @@ -114,12 +123,12 @@ def rosenbrock(x, /):
Parameters
----------
x : array_like
An :math:`n`-dimensional real vector.
The :math:`n`-vector.
Returns
-------
float
Function value at x.
Function value at :math:`\\mathbf{x}`.
References
----------
Expand All @@ -144,26 +153,29 @@ def rosenbrock(x, /):
>>> round(fbench.rosenbrock([3, 3]), 4)
3604.0
"""
x = validation.check_vector(x, min_elements=2)
x = fbench.check_vector(x, n_min=2)
return float((100 * (x[1:] - x[:-1] ** 2) ** 2 + (1 - x[:-1]) ** 2).sum())


def sphere(x, /):
"""Sphere function.
A function :math:`f\\colon \\mathbb{R}^{n} \\rightarrow \\mathbb{R}`
that takes an :math:`n`-vector as input and returns a scalar value.
.. math::
f(\\mathbf{x}) = \\sum_{i=1}^n x_i^2
f(\\mathbf{x}) = \\sum_{i=1}^{n} x_i^2
Parameters
----------
x : array_like
An :math:`n`-dimensional real vector.
The :math:`n`-vector.
Returns
-------
float
Function value at x.
Function value at :math:`\\mathbf{x}`.
References
----------
Expand All @@ -182,5 +194,5 @@ def sphere(x, /):
>>> fbench.sphere([1, 2, 3])
14.0
"""
x = validation.check_vector(x, min_elements=1)
x = fbench.check_vector(x)
return float((x**2).sum())
18 changes: 9 additions & 9 deletions src/fbench/structure.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
from typing import Callable, NamedTuple, Optional, Tuple
from typing import NamedTuple

import numpy as np

__all__ = ("CoordinateMatrices",)
__all__ = (
"CoordinateMatrices",
"CoordinatePairs",
)


class CoordinateMatrices(NamedTuple):
Expand All @@ -13,11 +16,8 @@ class CoordinateMatrices(NamedTuple):
z: np.ndarray


class FunctionConfig(NamedTuple):
"""An immutable data structure for a function configuration."""
class CoordinatePairs(NamedTuple):
"""An immutable data structure for (x, y) pairs."""

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]
x: np.ndarray
y: np.ndarray
44 changes: 22 additions & 22 deletions src/fbench/validation.py
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
import numpy as np

from fbench import exception

__all__ = ("check_vector",)


def check_vector(x, /, *, min_elements):
"""Validate an n-dimensional vector.
def check_vector(x, /, *, n_min=1, n_max=np.inf):
"""Validate :math:`n`-vector.
Parameters
----------
x : array_like
Input data with :math:`n` elements that can be converted to an array.
min_elements : int
Specify the minimum number of elements ``x`` must have.
The input object to be validated to represent an :math:`n`-vector.
n_min : int, default=1
Specify the minimum number of :math:`n`.
n_max : int, default=inf
Specify the maximum number of :math:`n`.
Returns
-------
np.ndarray
The :math:`n`-dimensional vector.
The :math:`n`-vector.
Raises
------
NotAVectorError
If ``x`` is not vector-like.
IncorrectNumberOfElements
If ``x`` does not satisfy the ``min_elements`` condition.
TypeError
- If ``x`` is not vector-like.
- If ``n`` is not between ``n_min`` and ``n_max``.
Examples
--------
>>> import fbench
>>> fbench.check_vector([0, 0])
array([0, 0])
"""
x = np.asarray(x)
x = np.atleast_1d(x)

if len(x.shape) != 1:
raise exception.NotAVectorError(
f"input must be vector-like object - it has shape={x.shape}"
)

if not len(x) >= min_elements:
raise exception.IncorrectNumberOfElements(
f"number of elements must be at least {min_elements} "
f"- it has {x.shape[0]}"
)
raise TypeError(f"input must be a vector-like object - it has shape={x.shape}")

if not (n_min <= len(x) <= n_max):
raise TypeError(f"n={len(x)} is not between n_min={n_min} and n_max={n_max}")

return x

0 comments on commit 4c4aa5e

Please sign in to comment.