"""For the online documentation of these base functions, please refer to:
https://pypop.readthedocs.io/en/latest/benchmarks.html#base-functions
Here all of below base functions are ordered only in *name*. However,
in the above online documentation, all of base functions are
classified mainly according to *uni-modality* or *multi-modality*
(dichotomy).
"""
import numpy as np
# helper function
def squeeze_and_check(x, size_gt_1=False):
"""Squeeze the input vector `x` into 1-d `numpy.ndarray` and check
whether or not its number of dimensions == 1. If not, raise a
`TypeError`. Optionally, check whether or not its size should
> 1. If not, raise a `TypeError`.
Parameters
----------
x : ndarray-like
An input vector.
size_gt_1 : bool
Checking whether or not its size should > 1
(default: `False`).
Returns
-------
x : ndarray
An input vector.
"""
x = np.squeeze(x)
if (x.ndim == 0) and (x.size == 1): # distinguish `ndim` and `size`
x = np.array([x])
if x.ndim != 1:
s = f'PyPop7: ndim should == 1 (not {x.ndim}) after np.squeeze().'
raise TypeError(s)
if size_gt_1 and not (x.size > 1): # distinguish `ndim` and `size`
s = f'PyPop7: size should > 1 (not {x.size}) after np.squeeze().'
raise TypeError(s)
if x.size == 0:
raise TypeError(f'PyPop7: size should != 0.')
return x
# a list of 22 *scalable* base functions:
[docs]def ackley(x):
"""**Ackley** test function.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x)
y = 20.0 + np.exp(1.0)
y -= 20.0 * np.exp(-0.2 * np.sqrt(np.sum(np.square(x)) / len(x)))
y -= np.exp(np.sum(np.cos(2.0 * np.pi * x)) / len(x))
return y
[docs]def cigar(x):
"""**Cigar** test function.
.. note:: Its dimensionality should `> 1`.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x, True)
x = np.square(x)
y = x[0] + (10.0 ** 6) * np.sum(x[1:])
return y
[docs]def cigar_discus(x):
"""**Cigar-Discus** test function.
.. note:: Its dimensionality should `> 1`.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x, True)
x = np.square(x)
if x.size == 2:
y = x[0] + (10.0 ** 4) * np.sum(x) + (10.0 ** 6) * x[-1]
else:
y = x[0] + (10.0 ** 4) * np.sum(x[1:-1]) + (10.0 ** 6) * x[-1]
return y
[docs]def different_powers(x):
"""**Different-Powers** test function.
.. note:: Its dimensionality should `> 1`.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x, True)
w = 2.0 + 4.0 * np.linspace(0.0, 1.0, len(x))
y = np.sum(np.power(np.abs(x), w))
return y
[docs]def discus(x):
"""**Discus** (also called **Tablet**) test function.
.. note:: Its dimensionality should `> 1`.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x, True)
x = np.square(x)
y = (10.0 ** 6) * x[0] + np.sum(x[1:])
return y
[docs]def ellipsoid(x):
"""**Ellipsoid** test function.
.. note:: Its dimensionality should `> 1`.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x, True)
w = 6.0 * np.linspace(0.0, 1.0, len(x))
y = np.dot(np.power(10.0, w), np.square(x))
return y
[docs]def exponential(x):
"""**Exponential** test function.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x)
y = -np.exp(-0.5 * np.sum(np.square(x)))
return y
[docs]def griewank(x):
"""**Griewank** test function.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x)
y = 1.0 + np.sum(np.square(x)) / 4000.0
w = np.sqrt(np.arange(len(x)) + 1)
y -= np.prod(np.cos(x / w))
return y
[docs]def levy_montalvo(x):
"""**Levy-Montalvo** test function.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x)
x = 1.0 + 0.25 * (x + 1.0)
y = 0.0
for i in range(len(x) - 1):
yy = 1.0 + 10.0 * np.square(np.sin(np.pi * x[i + 1]))
y += np.square(x[i] - 1.0) * yy
yy = np.square(np.sin(np.pi * x[0]))
y += 10.0 * yy + np.square(x[-1] - 1.0)
y *= (np.pi / len(x))
return y
[docs]def michalewicz(x):
"""**Michalewicz** test function.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x)
y = 0.0
for i in range(len(x)):
yy = np.sin((i + 1) * np.square(x[i]) / np.pi)
y -= np.sin(x[i]) * np.power(yy, 20.0)
return y
[docs]def rastrigin(x):
"""**Rastrigin** test function.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x)
y = np.square(x) - 10.0 * np.cos(2.0 * np.pi * x)
y = 10.0 * len(x) + np.sum(y)
return y
[docs]def rosenbrock(x):
"""**Rosenbrock** test function.
.. note:: Its dimensionality should `> 1`.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x, True)
y = np.square(x[1:] - np.square(x[:-1]))
y = 100.0 * np.sum(y) + np.sum(np.square(x[:-1] - 1.0))
return y
[docs]def salomon(x):
"""**Salomon** test function.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x)
x = np.linalg.vector_norm(x)
y = 1.0 - np.cos(2.0 * np.pi * x) + 0.1 * x
return y
[docs]def scaled_rastrigin(x):
"""**Scaled-Rastrigin** test function.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x)
w = np.power(10.0, np.linspace(0.0, 1.0, len(x)))
y = rastrigin(x * w)
return y
[docs]def schaffer(x):
"""**Schaffer** test function.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x)
y = 0.0
for i in range(len(x) - 1):
xx = np.square(x[i]) + np.square(x[i + 1])
yy = np.square(np.sin(50.0 * np.power(xx, 0.1))) + 1.0
y += np.power(xx, 0.25) * yy
return y
[docs]def schwefel12(x):
"""**Schwefel12** test function.
.. note:: Its dimensionality should `> 1`.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x, True)
x = [np.sum(x[:i + 1]) for i in range(len(x))]
y = np.sum(np.square(x))
return y
[docs]def schwefel221(x):
"""**Schwefel221** test function.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x)
y = np.max(np.abs(x))
return y
[docs]def schwefel222(x):
"""**Schwefel222** test function.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x)
x = np.abs(x)
y = np.sum(x) + np.prod(x)
return y
[docs]def shubert(x):
"""**Shubert** test function.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x)
y = 1.0
for i in range(len(x)):
yy = 0.0
for j in range(1, 6):
yy += j * np.cos((j + 1) * x[i] + j)
y *= yy
return y
[docs]def skew_rastrigin(x):
"""**Skew-Rastrigin** test function.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x)
for i in range(len(x)):
if x[i] > 0.0:
x[i] *= 10.0
y = rastrigin(x)
return y
def sphere(x):
"""**Sphere** test function.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x)
y = np.sum(np.square(x))
return y
[docs]def step(x):
"""**Step** test function.
Parameters
----------
x : ndarray
An input vector.
Returns
-------
y : float
A scalar fitness.
"""
x = squeeze_and_check(x)
y = np.sum(np.square(np.floor(x + 0.5)))
return y