added schaffer2 function
added output for improvement of fitness added CMAES algorithm, that requires further testing
This commit is contained in:
16
functions.py
16
functions.py
@@ -17,17 +17,29 @@ class Function:
|
|||||||
X, Y = np.meshgrid(x, y)
|
X, Y = np.meshgrid(x, y)
|
||||||
return x, y, self.eval(X, Y)
|
return x, y, self.eval(X, Y)
|
||||||
|
|
||||||
|
|
||||||
class Rastrigin(Function):
|
class Rastrigin(Function):
|
||||||
def __init__(self, A: int = 10):
|
def __init__(self, A: int = 10):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
xlim=(-5.12, 5.12),
|
xlim=(-6.12, 6.12),
|
||||||
ylim=(-5.12, 5.12),
|
ylim=(-6.12, 6.12),
|
||||||
minimum=(0, 0),
|
minimum=(0, 0),
|
||||||
eval=lambda x, y: self.A * 2 + \
|
eval=lambda x, y: self.A * 2 + \
|
||||||
(x**2 - self.A * np.cos(2 * np.pi * x)) + \
|
(x**2 - self.A * np.cos(2 * np.pi * x)) + \
|
||||||
(y**2 - self.A * np.cos(2 * np.pi * y)))
|
(y**2 - self.A * np.cos(2 * np.pi * y)))
|
||||||
self.A = A
|
self.A = A
|
||||||
|
|
||||||
|
|
||||||
|
class Schaffer2(Function):
|
||||||
|
def __init__(self):
|
||||||
|
super().__init__(
|
||||||
|
xlim=(-50, 50),
|
||||||
|
ylim=(-50, 50),
|
||||||
|
minimum=(0, 0),
|
||||||
|
eval=lambda x, y: 0.5 + \
|
||||||
|
(np.sin(x**2 - y**2)**2 - 0.5) / \
|
||||||
|
((1 + 0.001 * (x**2 + y**2))**2))
|
||||||
|
|
||||||
class Sphere(Function):
|
class Sphere(Function):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
super().__init__(
|
super().__init__(
|
||||||
|
|||||||
43
main.py
Normal file
43
main.py
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
import functions
|
||||||
|
import numpy as np
|
||||||
|
import solvers
|
||||||
|
|
||||||
|
from matplotlib import pyplot as plt
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
plot_rest = True
|
||||||
|
f = functions.Rastrigin()
|
||||||
|
# f = functions.Sphere()
|
||||||
|
# s = solvers.SimpleEvolutionStrategy(f, np.array([2, 2]))
|
||||||
|
s = solvers.CMAEvolutionStrategy(f, np.array([2.0, 2.0]), np.array([[2.0, 0.0], [0.0, 2.0]]))
|
||||||
|
old_fitness = 100
|
||||||
|
fitness = old_fitness * 0.9
|
||||||
|
old = None
|
||||||
|
plt.set_cmap('Spectral')
|
||||||
|
|
||||||
|
while abs(old_fitness - fitness) > 0.001:
|
||||||
|
old_fitness = fitness
|
||||||
|
samples = s.sample(2000)
|
||||||
|
elite, fitness = s.rank(samples, 150)
|
||||||
|
s.update(elite)
|
||||||
|
|
||||||
|
if plot_rest:
|
||||||
|
rest = np.setdiff1d(samples, elite, assume_unique=True)
|
||||||
|
rest = rest.reshape((int(rest.shape[0]/2), 2))
|
||||||
|
plt.pcolormesh(*f.grid())
|
||||||
|
if plot_rest:
|
||||||
|
plt.scatter(*rest.transpose(), color="dimgrey")
|
||||||
|
if old is not None:
|
||||||
|
plt.scatter(*old.transpose(), color="orange")
|
||||||
|
plt.scatter(*elite.transpose(), color="yellow")
|
||||||
|
# plt.scatter(*elite[0].transpose(), color="green")
|
||||||
|
print('old fitness: {}\nnew fitness: {}\nimprovement: {}\n'.format(old_fitness, fitness,
|
||||||
|
old_fitness - fitness))
|
||||||
|
plt.show()
|
||||||
|
old = elite
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
|
|
||||||
43
solvers.py
43
solvers.py
@@ -10,7 +10,7 @@ class Solver(ABC):
|
|||||||
self.function = function
|
self.function = function
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def rank(self, samples: Iterable[Iterable[float]], elite_size: int) -> (Iterable[Tuple], Iterable[Tuple], float):
|
def rank(self, samples: Iterable[Iterable[float]], elite_size: int) -> (Iterable[Iterable[float]], float):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
@@ -18,7 +18,7 @@ class Solver(ABC):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def update(elite: Iterable[Tuple]):
|
def update(elite: Iterable[Iterable[float]]):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
@@ -33,7 +33,7 @@ class SimpleEvolutionStrategy(Solver):
|
|||||||
else:
|
else:
|
||||||
self.sigma = [1] * len(mu)
|
self.sigma = [1] * len(mu)
|
||||||
|
|
||||||
def rank(self, samples: Iterable[Iterable[float]], elite_size: int) -> (Iterable[Tuple], Iterable[float]):
|
def rank(self, samples: Iterable[Iterable[float]], elite_size: int) -> (Iterable[Iterable[float]], Iterable[float]):
|
||||||
fitness = self.function.eval(*samples.transpose())
|
fitness = self.function.eval(*samples.transpose())
|
||||||
samples = samples[np.argsort(fitness)]
|
samples = samples[np.argsort(fitness)]
|
||||||
fitness = np.sort(fitness)
|
fitness = np.sort(fitness)
|
||||||
@@ -43,6 +43,41 @@ class SimpleEvolutionStrategy(Solver):
|
|||||||
def sample(self, n: int) -> Iterable[Iterable[float]]:
|
def sample(self, n: int) -> Iterable[Iterable[float]]:
|
||||||
return np.array([np.random.multivariate_normal(self.mu, np.diag(self.sigma)) for _ in range(n)])
|
return np.array([np.random.multivariate_normal(self.mu, np.diag(self.sigma)) for _ in range(n)])
|
||||||
|
|
||||||
def update(self, elite: Iterable[Tuple]):
|
def update(self, elite: Iterable[Iterable[float]]):
|
||||||
self.mu = elite[0]
|
self.mu = elite[0]
|
||||||
|
|
||||||
|
|
||||||
|
class CMAEvolutionStrategy(Solver):
|
||||||
|
def __init__(self, function: Function, mu: Iterable[float], covariances: Iterable[float] = None):
|
||||||
|
if covariances is not None and len(mu) != covariances.shape[0] and len(mu) != covariances.shape[1]:
|
||||||
|
raise Exception('Length of mu and covariance matrix must match')
|
||||||
|
super().__init__(function)
|
||||||
|
self.mu = mu
|
||||||
|
if covariances is not None:
|
||||||
|
self.covariances = covariances
|
||||||
|
else:
|
||||||
|
self.covariances = np.array([[1.0, 0.0], [0.0, 1.0]])
|
||||||
|
|
||||||
|
def rank(self, samples: Iterable[Iterable[float]], elite_size: int) -> (Iterable[Iterable[float]], Iterable[float]):
|
||||||
|
fitness = self.function.eval(*samples.transpose())
|
||||||
|
samples = samples[np.argsort(fitness)]
|
||||||
|
fitness = np.sort(fitness)
|
||||||
|
elite = samples[0:elite_size]
|
||||||
|
return elite, fitness[0]
|
||||||
|
|
||||||
|
def sample(self, n: int) -> Iterable[Iterable[float]]:
|
||||||
|
return np.array([np.random.multivariate_normal(self.mu, self.covariances) for _ in range(n)])
|
||||||
|
|
||||||
|
def update(self, elite: Iterable[Iterable[float]]):
|
||||||
|
mu = self.mu
|
||||||
|
x = elite.transpose()[0]
|
||||||
|
y = elite.transpose()[1]
|
||||||
|
self.mu[0] = np.average(x)
|
||||||
|
self.mu[1] = np.average(y)
|
||||||
|
|
||||||
|
# TODO fix covariance matrix calculation using the tutorial by Nikolaus Hansen
|
||||||
|
self.covariances[0][0] = np.average((x - mu[0])**2)
|
||||||
|
self.covariances[1][1] = np.average((y - mu[1])**2)
|
||||||
|
self.covariances[0][1] = np.average((x - mu[0]) * (y - mu[1]))
|
||||||
|
# self.covariances = np.cov(elite.transpose())
|
||||||
|
|
||||||
|
|||||||
35
test.py
35
test.py
@@ -1,35 +0,0 @@
|
|||||||
import functions
|
|
||||||
import numpy as np
|
|
||||||
import solvers
|
|
||||||
|
|
||||||
from matplotlib import pyplot as plt
|
|
||||||
|
|
||||||
|
|
||||||
plot_rest = True
|
|
||||||
f = functions.Rastrigin()
|
|
||||||
# f = functions.Sphere()
|
|
||||||
s = solvers.SimpleEvolutionStrategy(f, np.array([2, 2]))
|
|
||||||
old_fitness = 100
|
|
||||||
fitness = old_fitness * 0.9
|
|
||||||
old = None
|
|
||||||
plt.plasma()
|
|
||||||
|
|
||||||
while abs(old_fitness - fitness) > 0.001:
|
|
||||||
old_fitness = fitness
|
|
||||||
samples = s.sample(100)
|
|
||||||
elite, fitness = s.rank(samples, 10)
|
|
||||||
s.update(elite)
|
|
||||||
|
|
||||||
if plot_rest:
|
|
||||||
rest = np.setdiff1d(samples, elite, assume_unique=True)
|
|
||||||
rest = rest.reshape((int(rest.shape[0]/2), 2))
|
|
||||||
plt.pcolormesh(*f.grid())
|
|
||||||
if plot_rest:
|
|
||||||
plt.scatter(*rest.transpose(), color="dimgrey")
|
|
||||||
if old is not None:
|
|
||||||
plt.scatter(*old.transpose(), color="lightgrey")
|
|
||||||
plt.scatter(*elite.transpose(), color="yellow")
|
|
||||||
plt.scatter(*elite[0].transpose(), color="green")
|
|
||||||
plt.show()
|
|
||||||
old = elite
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user