import numpy as np
from random import random
class EABi:
def __init__(self, n_var, lb, ub, ff, wf, populations=50, iterations=2000, eps=1e-4,
cross_method='1', p_cross=0.1, mutation_method='1', p_mutation=0.05,
choose_method='1', cnt_saves=4):
self.n = n_var
self.fitness_function = ff
self.wrapper_function = wf
self.populations = populations
self.iterations = iterations
self.eps = eps
self.lb = lb
self.ub = ub
self.l = np.asarray(np.ceil(np.log2((self.ub - self.lb) / eps + 1)), dtype=np.int32)
self.end_of_var = np.concatenate((np.array([0], dtype=np.int32), np.cumsum(self.l)), axis=None)
self.len_individual = np.sum(self.l)
self.cross_method = cross_method
self.p_cross = p_cross
self.mutation_method = mutation_method
self.p_mutation = p_mutation
self.choose_method = choose_method
self.pow2 = 2 ** np.arange(np.max(self.l) + 2).reshape(-1, 1)
self.chrom, self.fitness = self.initRace()
self.new_chrom = None
self.save_freq = int(self.iterations / cnt_saves)
def decode(self, individual=None):
if individual is None:
res = np.zeros((self.populations, self.n))
for j in range(self.n):
res[:, j] = self.lb[j] + (self.ub[j] - self.lb[j]) / (self.pow2[self.l[j], 0] - 1) * \
np.dot(self.chrom[:, self.end_of_var[j]:self.end_of_var[j + 1]],
self.pow2[:self.l[j]]).reshape((-1,))
else:
individual = individual.reshape((-1, self.len_individual))
res = np.zeros((individual.shape[0], self.n))
for j in range(self.n):
res[:, j] = self.lb[j] + (self.ub[j] - self.lb[j]) / (self.pow2[self.l[j], 0] - 1) * \
np.dot(individual[:, self.end_of_var[j]:self.end_of_var[j + 1]],
self.pow2[:self.l[j]]).reshape((-1,))
return res
def initRace(self):
chrom = np.random.rand(self.populations, self.len_individual) > 0.5
fitness = self.getFitness(chrom)
return chrom, fitness
def cross(self):
if self.cross_method == '1':
for i in range(self.populations):
for j in range(i + 1, self.populations):
if random() < self.p_cross:
t = np.random.randint(0, self.len_individual)
tmp = self.new_chrom[i, t:]
self.new_chrom[i, t:] = self.new_chrom[j, t:]
self.new_chrom[j, t:] = tmp
else:
pass
def mutation(self):
if self.cross_method == '1':
rand = np.random.rand(*self.chrom.shape)
is_change = rand < self.p_mutation
self.new_chrom = self.new_chrom ^ is_change
else:
pass
def choose(self, keep_cnt=2):
self.new_chrom = np.vstack((self.new_chrom, self.chrom), )
fitness = self.getFitness()
tmp_id = np.argsort(-fitness)
self.new_chrom = self.new_chrom[tmp_id, :]
fitness = fitness[tmp_id]
self.chrom[0:keep_cnt, :] = self.new_chrom[0:keep_cnt, :]
self.fitness[0:keep_cnt] = fitness[0:keep_cnt]
if self.choose_method == '1':
fitness = fitness[keep_cnt:]
self.new_chrom = self.new_chrom[keep_cnt:, ]
p = fitness / np.sum(fitness)
sum_p = np.cumsum(p)
cnt = keep_cnt
while cnt < self.populations:
r = random()
j = 0
for i in range(p.shape[0]):
if r <= sum_p[i]:
j = i
break
self.chrom[cnt, :] = self.new_chrom[j, :]
self.fitness[cnt] = fitness[j]
cnt += 1
else:
pass
def getFitness(self, x=None):
if x is None:
de = self.decode(self.new_chrom)
fitness = np.array(
[self.wrapper_function(self.fitness_function(de[i, :])) for i in range(self.new_chrom.shape[0])])
else:
x = x.reshape((-1, self.len_individual))
de = self.decode(x)
fitness = np.array([self.wrapper_function(self.fitness_function(de[i, :])) for i in range(x.shape[0])])
return fitness
def main(self):
best_fit = [np.max(self.fitness)]
mean_fit = [np.mean(self.fitness)]
saved_idx = [0]
saved_chrom = [self.decode()]
for i in range(1, self.iterations):
self.new_chrom = self.chrom.copy()
self.cross()
self.mutation()
self.choose()
best_fit.append(np.max(self.fitness))
mean_fit.append(np.mean(self.fitness))
if i % self.save_freq == 0:
saved_idx.append(i)
saved_chrom.append(self.decode())
saved_idx.append(self.iterations)
saved_chrom.append(self.decode())
return np.array(mean_fit), np.array(best_fit), saved_idx, np.array(saved_chrom)
class EAReal:
def __init__(self, n_var, lb, ub, ff, wf, populations=50, iterations=2000, eps=1,
cross_method='1', p_cross=0.2, mutation_method='1', p_mutation=0.8,
choose_method='1', cnt_saves=4):
self.n = n_var
self.fitness_function = ff
self.wrapper_function = wf
self.populations = populations
self.iterations = iterations
self.eps = eps
self.len_individual = self.n
self.lb = lb.reshape((1, -1))
self.ub = ub.reshape((1, -1))
self.cross_method = cross_method
self.p_cross = p_cross
self.mutation_method = mutation_method
self.p_mutation = p_mutation
self.choose_method = choose_method
self.chrom, self.fitness = self.initRace()
self.new_chrom = None
self.save_freq = int(self.iterations / cnt_saves)
def decode(self):
return self.chrom.copy()
def initRace(self):
chrom = np.random.rand(self.populations, self.n)
chrom = chrom * (self.ub - self.lb) + self.lb
return chrom, self.getFitness(chrom)
def cross(self, lamb=0.7):
if self.cross_method == '1':
for i in range(self.populations):
for j in range(i + 1, self.populations):
if random() < self.p_cross:
self.new_chrom[i, :] = lamb * self.chrom[i, :] + (1 - lamb) * self.chrom[j, :]
self.new_chrom[j, :] = lamb * self.chrom[j, :] + (1 - lamb) * self.chrom[i, :]
else:
pass
def mutation(self):
if self.cross_method == '1':
rand = np.random.rand(*self.chrom.shape)
is_change = rand < self.p_mutation
rand = np.random.rand(*self.chrom.shape)
is_neg = np.ones_like(is_change, dtype=int)
is_neg[rand < 0.5] = -1
self.new_chrom = self.new_chrom + is_change * is_neg * self.eps
else:
pass
def choose(self, keep_cnt=2):
assert np.all(self.new_chrom <= self.ub) and np.all(self.new_chrom >= self.lb)
self.new_chrom = np.vstack((self.new_chrom, self.chrom), )
fitness = self.getFitness()
tmp_id = np.argsort(-fitness)
self.new_chrom = self.new_chrom[tmp_id, :]
fitness = fitness[tmp_id]
self.chrom[0:keep_cnt, :] = self.new_chrom[0:keep_cnt, :]
self.fitness[0:keep_cnt] = fitness[0:keep_cnt]
if self.choose_method == '1':
fitness = fitness[keep_cnt:]
self.new_chrom = self.new_chrom[keep_cnt:, ]
p = fitness / np.sum(fitness)
sum_p = np.cumsum(p)
cnt = keep_cnt
while cnt < self.populations:
r = random()
j = 0
for i in range(p.shape[0]):
if r <= sum_p[i]:
j = i
break
self.chrom[cnt, :] = self.new_chrom[j, :]
self.fitness[cnt] = fitness[j]
cnt += 1
else:
pass
def getFitness(self, x=None):
if x is None:
fitness = np.array([self.wrapper_function(self.fitness_function(self.new_chrom[i, :])) for i in
range(self.new_chrom.shape[0])])
else:
x = x.reshape((-1, self.n))
fitness = np.array([self.wrapper_function(self.fitness_function(x[i, :])) for i in range(x.shape[0])])
return fitness
def main(self):
best_fit = [np.max(self.fitness)]
mean_fit = [np.mean(self.fitness)]
saved_idx = [0]
saved_chrom = [self.decode()]
for i in range(1, self.iterations):
if i % 50 == 0:
self.ub = np.max(self.chrom, axis=0, keepdims=True)
self.lb = np.min(self.chrom, axis=0, keepdims=True)
if i == 100:
self.eps /= 2
elif i == 500:
self.eps /= 2
self.new_chrom = self.chrom.copy()
self.cross()
self.mutation()
self.new_chrom = np.maximum(np.minimum(self.new_chrom, self.ub), self.lb)
self.choose()
best_fit.append(np.max(self.fitness))
mean_fit.append(np.mean(self.fitness))
if i % self.save_freq == 0:
saved_idx.append(i)
saved_chrom.append(self.decode())
saved_idx.append(self.iterations)
saved_chrom.append(self.decode())
return np.array(mean_fit), np.array(best_fit), saved_idx, np.array(saved_chrom)
def f(x):
return np.dot(x, x)
def test_real():
n_var = 3
ea = EAReal(n_var, np.ones(n_var) * (-10), np.ones(n_var) * 10, f)
ea.main()
print(ea.chrom)
def test_bin():
n_var = 3
ea = EABi(n_var, np.ones(n_var) * (-10), np.ones(n_var) * 10, f)
ea.main()
print(ea.decode())
if __name__ == '__main__':
test_real()
from ea import *
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def Ball(x):
return x[0] * x[0] + x[1] * x[1]
def DeJong(x):
return 100 * (x[1] - x[0] ** 2) ** 2 + (x[0] - 1) * (x[0] - 1)
def HimmelBaut(x):
x, y = x[0], x[1]
return (x * x + y - 11) * (x * x + y - 11) + (x + y * y - 7) * (x + y * y - 7)
def SixHumpCamelBack(x):
x, y = x[0], x[1]
return 4 * x * x - 2.1 * x ** 4 + 1 / 3 * x ** 6 + x * y - 4 * y * y + 4 * y ** 4
def Shubert(x):
x, y = x[0], x[1]
return (sum([i * np.cos((i + 1) * x + i) for i in range(1, 6)])) * (
sum([i * np.cos((i + 1) * y + i) for i in range(1, 6)]))
def draw(fun, lb, ub, idx, chrom, title, fig):
for i in range(5):
if 'Real' in title:
ax = fig.add_subplot(6, 5, i + 16)
else:
ax = fig.add_subplot(6, 5, i + 21)
eps = (ub - lb) / 50
x = np.arange(lb - eps * 5, ub + eps * 5, eps)
y = np.arange(lb - eps * 5, ub + eps * 5, eps)
xx, yy = np.meshgrid(x, y)
zz = fun(np.array([xx, yy]))
ax.contourf(xx, yy, zz, cmap='rainbow', levels=100)
x = chrom[i, :, 0]
y = chrom[i, :, 1]
ax.scatter(x, y, s=2, marker='x', c='black')
ax.set_title(title + ' in ' + str(idx[i]), fontsize=8)
ax.tick_params(labelsize=6)
def wrapper(x):
return 1 / (1 + x)
def main():
fun = Ball
n_var = 2
lb = np.ones(n_var) * (-5.12)
ub = np.ones(n_var) * (5.12)
ea = EAReal(n_var=n_var, lb=lb, ub=ub, ff=fun, wf=wrapper)
real_mean, real_best, real_id, real_chrom = ea.main()
real_res = 'EAReal: ' + str(ea.decode()[0]) + ' ' + str(real_best[-1])
print(real_res)
ea = EABi(n_var=n_var, lb=lb, ub=ub, ff=fun, wf=wrapper)
bi_mean, bi_best, bi_id, bi_chrom = ea.main()
bi_res = 'EABi: ' + str(ea.decode()[0]) + ' ' + str(bi_best[-1])
print(bi_res)
fig = plt.figure(1, figsize=(10, 12))
ax = fig.add_subplot(2, 1, 1, projection='3d')
eps = (ub[0] - lb[0]) / 100
x = np.arange(lb[0] - eps * 10, ub[0] + eps * 10, eps)
y = np.arange(lb[0] - eps * 10, ub[0] + eps * 10, eps)
xx, yy = np.meshgrid(x, y)
zz = fun(np.array([xx, yy]))
ax.plot_surface(xx, yy, zz, cmap='rainbow')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('g(x, y)')
ax.set_title('3D plot')
draw(fun, lb[0], ub[0], real_id, real_chrom, 'EAReal', fig)
draw(fun, lb[0], ub[0], bi_id, bi_chrom, 'EABi', fig)
ax1 = fig.add_subplot(616)
idx = np.arange(0, 2000, 10, dtype=int)
plt1 = ax1.plot(idx, real_mean[idx], 'r', label='EAReal-mean')
plt2 = ax1.plot(idx, bi_mean[idx], 'g', label='EABi-mean')
ax2 = ax1.twinx()
plt3 = ax2.plot(real_best, '--', color='orange', label='EAReal-best')
plt4 = ax2.plot(bi_best, '--', color='b', label='EABi-best')
line = plt1 + plt3 + plt2 + plt4
ax1.set_xlabel('iterations')
ax1.set_ylabel('mean fitness')
ax2.set_ylabel('best fitness')
plt.legend(line, [l.get_label() for l in line], fontsize=7)
plt.subplots_adjust(left=None, bottom=None, right=None, top=None,
wspace=0.5, hspace=0.4)
plt.text(0, -1, real_res + '\n' + bi_res, size=12, transform=ax1.transAxes)
plt.savefig('2' + str(fun.__name__) + '.pdf', bbox_inches='tight')
if __name__ == '__main__':
main()
from ea import *
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
def Ball(x):
return np.sum(x * x, axis=0)
def Step(x):
return np.sum(np.floor(x + 0.5) ** 2, axis=0)
def Rastrigin(x):
A = 10
return np.sum(A + x * x - A * np.cos(2 * np.pi * x), axis=0)
def RosenBrock(x):
x0 = x[:-1]
x1 = x[1:]
return np.sum((1 - x0) ** 2 + 100 * (x1 - x0 ** 2) ** 2, axis=0)
def Ackley(x):
s1 = np.sum(x * x, axis=0)
s2 = np.sum(np.cos(2 * np.pi * x), axis=0)
n = x.shape[0]
return -20 * np.exp(-0.2 * np.sqrt(s1 / n)) - np.exp(s2 / n) + 20 + np.e
def draw(fun, lb, ub, idx, chrom, title, fig):
for i in range(5):
if 'Real' in title:
ax = fig.add_subplot(6, 5, i + 16)
else:
ax = fig.add_subplot(6, 5, i + 21)
eps = (ub - lb) / 100
x = np.arange(lb - eps * 10, ub + eps * 10, eps)
y = np.arange(lb - eps * 10, ub + eps * 10, eps)
xx, yy = np.meshgrid(x, y)
zz = fun(np.array([xx, yy]))
ax.contourf(xx, yy, zz, cmap='rainbow', levels=100)
x = chrom[i, :, 0]
y = chrom[i, :, 1]
ax.scatter(x, y, s=2, marker='x', c='black')
ax.set_title(title + ' in ' + str(idx[i]), fontsize=8)
ax.tick_params(labelsize=6)
def wrapper(x):
return 1 / (1 + x)
def main():
fun = Ball
n_var = 10
lb = np.ones(n_var) * (-100)
ub = np.ones(n_var) * (100)
ea = EAReal(n_var=n_var, lb=lb, ub=ub, ff=fun, wf=wrapper)
real_mean, real_best, real_id, real_chrom = ea.main()
real_res = 'EAReal: ' + str(ea.decode()[0]) + ' ' + str(real_best[-1])
print(real_res)
ea = EABi(n_var=n_var, lb=lb, ub=ub, ff=fun, wf=wrapper)
bi_mean, bi_best, bi_id, bi_chrom = ea.main()
bi_res = 'EABi: ' + str(ea.decode()[0]) + ' ' + str(bi_best[-1])
print(bi_res)
fig = plt.figure(1, figsize=(10, 12))
ax = fig.add_subplot(2, 1, 1, projection='3d')
eps = (ub[0] - lb[0]) / 200
x = np.arange(lb[0] - eps * 10, ub[0] + eps * 10, eps)
y = np.arange(lb[0] - eps * 10, ub[0] + eps * 10, eps)
xx, yy = np.meshgrid(x, y)
zz = fun(np.array([xx, yy]))
ax.plot_surface(xx, yy, zz, cmap='rainbow')
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_zlabel('g(x, y)')
ax.set_title('3D plot')
draw(fun, lb[0], ub[0], real_id, real_chrom, 'EAReal', fig)
draw(fun, lb[0], ub[0], bi_id, bi_chrom, 'EABi', fig)
ax1 = fig.add_subplot(616)
idx = np.arange(0, 2000, 10, dtype=int)
plt1 = ax1.plot(idx, real_mean[idx], 'r', label='EAReal-mean')
plt2 = ax1.plot(idx, bi_mean[idx], 'g', label='EABi-mean')
ax2 = ax1.twinx()
plt3 = ax2.plot(real_best, '--', color='orange', label='EAReal-best')
plt4 = ax2.plot(bi_best, '--', color='b', label='EABi-best')
line = plt1 + plt3 + plt2 + plt4
ax1.set_xlabel('iterations')
ax1.set_ylabel('mean fitness')
ax2.set_ylabel('best fitness')
plt.legend(line, [l.get_label() for l in line], fontsize=7)
plt.subplots_adjust(left=None, bottom=None, right=None, top=None,
wspace=0.5, hspace=0.4)
plt.text(0, -1, real_res + '\n' + bi_res, size=12, transform=ax1.transAxes)
plt.savefig('n' + str(fun.__name__) + '.pdf', bbox_inches='tight')
if __name__ == '__main__':
main()