-
Notifications
You must be signed in to change notification settings - Fork 408
/
Copy pathnsga2_custom.py
113 lines (79 loc) · 3.23 KB
/
nsga2_custom.py
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
import string
import numpy as np
from pymoo.algorithms.moo.nsga2 import NSGA2
from pymoo.core.crossover import Crossover
from pymoo.core.duplicate import ElementwiseDuplicateElimination
from pymoo.core.mutation import Mutation
from pymoo.core.problem import ElementwiseProblem
from pymoo.core.sampling import Sampling
from pymoo.optimize import minimize
from pymoo.visualization.scatter import Scatter
class MyProblem(ElementwiseProblem):
def __init__(self, n_characters=10):
super().__init__(n_var=1, n_obj=2, n_ieq_constr=0)
self.n_characters = n_characters
self.ALPHABET = [c for c in string.ascii_lowercase]
def _evaluate(self, x, out, *args, **kwargs):
n_a, n_b = 0, 0
for c in x[0]:
if c == 'a':
n_a += 1
elif c == 'b':
n_b += 1
out["F"] = np.array([- n_a, - n_b], dtype=float)
class MySampling(Sampling):
def _do(self, problem, n_samples, **kwargs):
X = np.full((n_samples, 1), None, dtype=object)
for i in range(n_samples):
X[i, 0] = "".join([np.random.choice(problem.ALPHABET) for _ in range(problem.n_characters)])
return X
class MyCrossover(Crossover):
def __init__(self):
# define the crossover: number of parents and number of offsprings
super().__init__(2, 2)
def _do(self, problem, X, **kwargs):
# The input of has the following shape (n_parents, n_matings, n_var)
_, n_matings, n_var = X.shape
# The output owith the shape (n_offsprings, n_matings, n_var)
# Because there the number of parents and offsprings are equal it keeps the shape of X
Y = np.full_like(X, None, dtype=object)
# for each mating provided
for k in range(n_matings):
# get the first and the second parent
a, b = X[0, k, 0], X[1, k, 0]
# prepare the offsprings
off_a = ["_"] * problem.n_characters
off_b = ["_"] * problem.n_characters
for i in range(problem.n_characters):
if np.random.random() < 0.5:
off_a[i] = a[i]
off_b[i] = b[i]
else:
off_a[i] = b[i]
off_b[i] = a[i]
# join the character list and set the output
Y[0, k, 0], Y[1, k, 0] = "".join(off_a), "".join(off_b)
return Y
class MyMutation(Mutation):
def __init__(self):
super().__init__()
def _do(self, problem, X, **kwargs):
for i in range(len(X)):
if np.random.random() < 0.5:
X[i, 0] = "".join(np.array([e for e in X[i, 0]])[np.random.permutation(problem.n_characters)])
return X
class MyDuplicateElimination(ElementwiseDuplicateElimination):
def is_equal(self, a, b):
return a.X[0] == b.X[0]
algorithm = NSGA2(pop_size=20,
sampling=MySampling(),
crossover=MyCrossover(),
mutation=MyMutation(),
eliminate_duplicates=MyDuplicateElimination()
)
res = minimize(MyProblem(),
algorithm,
seed=1,
verbose=True)
Scatter().add(res.F).show()
print(res.X[np.argsort(res.F[:, 0])])