thursday/thursday/external/evolopy/DE.py

125 lines
3.4 KiB
Python

import random
import numpy
import time
from .solution import solution
# Differential Evolution (DE)
# mutation factor = [0.5, 2]
# crossover_ratio = [0,1]
def DE(objf, lb, ub, dim, PopSize, iters):
mutation_factor = 0.5
crossover_ratio = 0.7
stopping_func = None
# convert lb, ub to array
if not isinstance(lb, list):
lb = [lb for _ in range(dim)]
ub = [ub for _ in range(dim)]
# solution
s = solution()
s.best = float("inf")
# initialize population
population = []
population_fitness = numpy.array([float("inf") for _ in range(PopSize)])
for p in range(PopSize):
sol = []
for d in range(dim):
d_val = random.uniform(lb[d], ub[d])
sol.append(d_val)
population.append(sol)
population = numpy.array(population)
# calculate fitness for all the population
for i in range(PopSize):
fitness = objf(population[i, :])
population_fitness[p] = fitness
# s.func_evals += 1
# is leader ?
if fitness < s.best:
s.best = fitness
s.leader_solution = population[i, :]
convergence_curve = numpy.zeros(iters)
# start work
print('DE is optimizing "' + objf.__name__ + '"')
timerStart = time.time()
s.startTime = time.strftime("%Y-%m-%d-%H-%M-%S")
t = 0
while t < iters:
# should i stop
if stopping_func is not None and stopping_func(s.best, s.leader_solution, t):
break
# loop through population
for i in range(PopSize):
# 1. Mutation
# select 3 random solution except current solution
ids_except_current = [_ for _ in range(PopSize) if _ != i]
id_1, id_2, id_3 = random.sample(ids_except_current, 3)
mutant_sol = []
for d in range(dim):
d_val = population[id_1, d] + mutation_factor * (
population[id_2, d] - population[id_3, d]
)
# 2. Recombination
rn = random.uniform(0, 1)
if rn > crossover_ratio:
d_val = population[i, d]
# add dimension value to the mutant solution
mutant_sol.append(d_val)
# 3. Replacement / Evaluation
# clip new solution (mutant)
mutant_sol = numpy.clip(mutant_sol, lb, ub)
# calc fitness
mutant_fitness = objf(mutant_sol)
# s.func_evals += 1
# replace if mutant_fitness is better
if mutant_fitness < population_fitness[i]:
population[i, :] = mutant_sol
population_fitness[i] = mutant_fitness
# update leader
if mutant_fitness < s.best:
s.best = mutant_fitness
s.leader_solution = mutant_sol
convergence_curve[t] = s.best
if t % 1 == 0:
print(
["At iteration " + str(t + 1) + " the best fitness is " + str(s.best)]
)
# increase iterations
t = t + 1
timerEnd = time.time()
s.endTime = time.strftime("%Y-%m-%d-%H-%M-%S")
s.executionTime = timerEnd - timerStart
s.convergence = convergence_curve
s.optimizer = "DE"
s.bestIndividual = s.leader_solution
s.objfname = objf.__name__
# return solution
return s