-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathdifferential_evolution.py
More file actions
76 lines (59 loc) · 2.91 KB
/
Copy pathdifferential_evolution.py
File metadata and controls
76 lines (59 loc) · 2.91 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
import numpy as np
class DifferentialEvolution:
def __init__(self, fobj, bounds, mutation_coefficient=0.8, crossover_coefficient=0.7, population_size=20):
self.fobj = fobj
self.bounds = bounds
self.mutation_coefficient = mutation_coefficient
self.crossover_coefficient = crossover_coefficient
self.population_size = population_size
self.dimensions = len(self.bounds)
self.a = None
self.b = None
self.c = None
self.mutant = None
self.population = None
self.idxs = None
self.fitness = []
self.min_bound = None
self.max_bound = None
self.diff = None
self.population_denorm = None
self.best_idx = None
self.best = None
self.cross_points = None
def _init_population(self):
self.population = np.random.rand(self.population_size, self.dimensions)
self.min_bound, self.max_bound = self.bounds.T
self.diff = np.fabs(self.min_bound - self.max_bound)
self.population_denorm = self.min_bound + self.population * self.diff
self.fitness = np.asarray([self.fobj(ind) for ind in self.population_denorm])
self.best_idx = np.argmin(self.fitness)
self.best = self.population_denorm[self.best_idx]
def _mutation(self):
self.a, self.b, self.c = self.population[np.random.choice(self.idxs, 3, replace = False)]
self.mutant = np.clip(self.a + self.mutation_coefficient * (self.b - self.c), 0, 1)
return self.mutant
def _crossover(self):
cross_points = np.random.rand(self.dimensions) < self.crossover_coefficient
if not np.any(cross_points):
cross_points[np.random.randint(0, self.dimensions)] = True
return cross_points
def _recombination(self, population_index):
trial = np.where(self.cross_points, self.mutant, self.population[population_index])
trial_denorm = self.min_bound + trial * self.diff
return trial, trial_denorm
def _evaluate(self, result_of_evolution, population_index):
if result_of_evolution < self.fitness[population_index]:
self.fitness[population_index] = result_of_evolution
self.population[population_index] = self.trial
if result_of_evolution < self.fitness[self.best_idx]:
self.best_idx = population_index
self.best = self.trial_denorm
def iterate(self):
for population_index in range(self.population_size):
self.idxs = [idx for idx in range(self.population_size) if idx != population_index]
self.mutant = self._mutation()
self.cross_points = self._crossover()
self.trial, self.trial_denorm = self._recombination(population_index)
result_of_evolution = self.fobj(self.trial_denorm)
self._evaluate(result_of_evolution, population_index)