Spaces:
Sleeping
Sleeping
import numpy as np | |
""" | |
Interface to a subset of the test functions listed at | |
https://en.wikipedia.org/wiki/Test_functions_for_optimization | |
""" | |
def rastrigin(x, y): | |
args = (x, y) | |
A = 10 | |
return A * len(x) + sum([(xi**2 - A * np.cos(2 * np.pi * xi)) for xi in args]) | |
def ackley(x, y): | |
return -20 * np.exp(-0.2 * np.sqrt(0.5 * (x**2 + y**2))) - \ | |
np.exp(0.5 * (np.cos(2 * np.pi * x) + np.cos(2 * np.pi * y))) + np.e + 20 | |
def sphere(x, y): | |
return x**2 + y**2 | |
def rosenbrock(x, y): | |
return 100 * (y - x**2)**2 + (1 - x)**2 | |
def beale(x, y): | |
return (1.5 - x + x * y)**2 + (2.25 - x + x * y**2)**2 + (2.625 - x + x * y**3)**2 | |
def goldstein_price(x, y): | |
return (1 + (x + y + 1)**2 * (19 - 14 * x + 3 * x**2 - 14 * y + 6 * x * y + 3 * y**2)) * \ | |
(30 + (2 * x - 3 * y)**2 * (18 - 32 * x + 12 * x**2 + 48 * y - 36 * x * y + 27 * y**2)) | |
def booth(x, y): | |
return (x + 2 * y - 7)**2 + (2 * x + y - 5)**2 | |
def bukin(x, y): | |
return 100 * np.sqrt(abs(y - 0.01 * x**2)) + 0.01 * abs(x + 10) | |
def matyas(x, y): | |
return 0.26 * (x**2 + y**2) - 0.48 * x * y | |
def levi(x, y): | |
return np.sin(3 * np.pi * x)**2 + (x - 1)**2 * (1 + np.sin(3 * np.pi * y)**2) + \ | |
(y - 1)**2 * (1 + np.sin(2 * np.pi * y)**2) | |
def himmelblau(x, y): | |
return (x**2 + y - 11)**2 + (x + y**2 - 7)**2 | |
def three_hump_camel(x, y): | |
return 2 * x**2 - 1.05 * x**4 + x**6 / 6 + x * y + y**2 | |
def easom(x, y): | |
return -np.cos(x) * np.cos(y) * np.exp(-((x - np.pi)**2 + (y - np.pi)**2)) | |
def cross_in_tray(x, y): | |
return -0.0001 * (abs(np.sin(x) * np.sin(y) * np.exp(abs(100 - np.sqrt(x**2 + y**2) / np.pi))) + 1)**0.1 | |
def eggholder(x, y): | |
return -(y + 47) * np.sin(np.sqrt(abs(x / 2 + (y + 47)))) - x * np.sin(np.sqrt(abs(x - (y + 47)))) | |
def holder_table(x, y): | |
return -abs(np.sin(x) * np.cos(y) * np.exp(abs(1 - np.sqrt(x**2 + y**2) / np.pi))) | |
def mccormick(x, y): | |
return np.sin(x + y) + (x - y)**2 - 1.5 * x + 2.5 * y + 1 | |
def schaffer2(x, y): | |
return 0.5 + (np.sin(x**2 - y**2)**2 - 0.5) / (1 + 0.001 * (x**2 + y**2))**2 | |
def schaffer4(x, y): | |
return 0.5 + (np.cos(np.sin(abs(x**2 - y**2)))**2 - 0.5) / (1 + 0.001 * (x**2 + y**2))**2 | |
def styblinski_tang(x, y): | |
args = (x, y) | |
return sum([xi**4 - 16 * xi**2 + 5 * xi for xi in args]) / 2 | |
functions = [ | |
rastrigin, | |
ackley, | |
sphere, | |
rosenbrock, | |
beale, | |
goldstein_price, | |
booth, | |
bukin, | |
matyas, | |
levi, | |
himmelblau, | |
three_hump_camel, | |
easom, | |
cross_in_tray, | |
eggholder, | |
holder_table, | |
mccormick, | |
schaffer2, | |
schaffer4, | |
styblinski_tang | |
] | |
function_names = [ | |
'rastrigin', | |
'ackley', | |
'sphere', | |
'rosenbrock', | |
'beale', | |
'goldstein_price', | |
'booth', | |
'bukin', | |
'matyas', | |
'levi', | |
'himmelblau', | |
'three_hump_camel', | |
'easom', | |
'cross_in_tray', | |
'eggholder', | |
'holder_table', | |
'mccormick', | |
'schaffer2', | |
'schaffer4', | |
'styblinski_tang' | |
] | |
domains = { | |
'rastrigin': (-5.12, 5.12), | |
'ackley': (-5, 5), | |
'sphere': (-1, 1), | |
'rosenbrock': {'x': (-2, 2), 'y': (-10, 10)}, | |
'beale': (-4.5, 4.5), | |
'goldstein_price': (-2, 2), | |
'booth': (-10, 10), | |
'bukin': {'x': (-15, -5), 'y': (-3, 3)}, | |
'matyas': (-10, 10), | |
'levi': (-10, 10), | |
'himmelblau': (-5, 5), | |
'three_hump_camel': (-5, 5), | |
'easom': (-100, 100), | |
'cross_in_tray': (-10, 10), | |
'eggholder': (-512, 512), | |
'holder_table': (-10, 10), | |
'mccormick': {'x': (-1.5, 4), 'y': (-3, 4)}, | |
'schaffer2': (-100, 100), | |
'schaffer4': (-100, 100), | |
'styblinski_tang': (-5, 5) | |
} | |
def scale_input(x, domain): | |
min_d, max_d = domain | |
return min_d + (max_d - min_d) * x | |
def get_test_function(X, Y, fun_idx): | |
""" | |
Evaluates a function on inputs (X, Y). | |
Args: | |
X (float or array-like): The X input values to be scaled and used in the function. | |
Y (float or array-like): The Y input values to be scaled and used in the function. | |
Ignored if the function takes only one argument. | |
fun_idx (int): The index of the function to be retrieved from a predefined list 'functions'. | |
Returns: | |
(float or array-like), values of the function on the grid | |
""" | |
func = functions[fun_idx] | |
domain = domains[func.__name__] | |
if isinstance(domain, dict): | |
x_scaled = scale_input(X, domain['x']) | |
y_scaled = scale_input(Y, domain['y']) | |
else: | |
x_scaled = scale_input(X, domain) | |
y_scaled = scale_input(Y, domain) | |
try: | |
output = func(X, Y) | |
except TypeError: | |
output = func(X) | |
return output | |