DEAP doesn't have built-in support for multimodal optimization. However, it can be used to solve such problems, simply by specifying the right fitness function.
import numpy as np
import random
import math
import matplotlib.pyplot as plt
from scipy.spatial import distance_matrix
from deap import base, tools, creator, algorithms
npop = 1000
sigma = 0.3
alpha = 2
# Here is a function with many local maxima
def objective(x, y):
return np.exp(-9*abs(x*y)) * np.sin(3*math.pi*x)**2 * np.sin(3*math.pi*y)**2
def fitness(individual):
return objective(individual[0], individual[1]),
xrange = np.arange(0., 1., 0.01)
X, Y = np.meshgrid(xrange, xrange)
zs = np.array(objective(np.ravel(X), np.ravel(Y)))
Z = zs.reshape(X.shape)
# Setup the DEAP toolbox
toolbox = base.Toolbox()
creator.create("FitnessMax", base.Fitness, weights=(1.0,))
creator.create("Individual", list, fitness=creator.FitnessMax)
toolbox.register("individual", tools.initRepeat, creator.Individual, random.random, n=2)
toolbox.register("population", tools.initRepeat, list, toolbox.individual)
toolbox.register('mutate', tools.mutPolynomialBounded, eta=.6, low=[0,0], up=[1,1], indpb=0.1)
toolbox.register('mate', tools.cxUniform, indpb=0.5)
toolbox.register('select', tools.selBest)
# Register a shared fitness function
def sharing(distance, sigma, alpha):
res = 0
if distance<sigma:
res += 1 - (distance/sigma)**alpha
return res
def shared_fitness(individual, population, sigma, alpha):
num = fitness(individual)[0]
dists = distance_matrix([individual], population)[0]
tmp = [sharing(d, sigma, alpha) for d in dists]
den = sum(tmp)
return num/den,
pop = toolbox.population(n=npop)
toolbox.register('evaluate', shared_fitness, population=pop, sigma=sigma, alpha=alpha)
# Run the optimization algorithm
mu = int(len(pop)*0.5)
lambda_ = int(len(pop)*0.5)
cxpb = 0.4
mutpb = 0.5
ngen = 10
pop, logbook = algorithms.eaMuPlusLambda(pop, toolbox, mu, lambda_, cxpb, mutpb, ngen)
fig = plt.figure()
ax = fig.add_subplot(111)
sc = ax.scatter(X, Y, c=Z)
plt.colorbar(sc)
ax.scatter(*zip(*pop), color='red')
With this, the population gets distributed within niches, and each local maxima can be identified.
