-
Notifications
You must be signed in to change notification settings - Fork 0
/
zdt1.py
84 lines (66 loc) · 2.5 KB
/
zdt1.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
import math
import random
import numpy as np
from matplotlib import pyplot as plt
from nsga2 import NSGA2Solution, NSGA2
from nsga2.solutions import MonoRepresentationSolution
from operators import linear_crossover, gaussian_mutation, dominance_operator
class ZDT1Solution(NSGA2Solution, MonoRepresentationSolution):
""" Solution for ZDT1 problem, solved using NSGA-II """
n_variables: int = 10 # default value
@classmethod
def set_num_variables(cls, n):
cls.n_variables = n
@classmethod
def calculate_fitness(cls, phenotype: np.ndarray) -> np.ndarray:
f_1 = phenotype[0]
g = 1.0 + 9 * sum(phenotype[1:]) / (cls.n_variables - 1)
h = 1.0 - math.sqrt(f_1 / g)
f_2 = g * h
return np.array([f_1, f_2])
@classmethod
def crossover(cls, parent1, parent2):
gene1 = parent1.genotype
gene2 = parent2.genotype
new1, new2 = linear_crossover(gene1, gene2, 0.0, 1.0)
return cls.from_genotype(new1), cls.from_genotype(new2)
@classmethod
def mutate(cls, parent):
new = gaussian_mutation(parent.genotype, 0.5, 0.0, 1.0)
return cls.from_genotype(new)
@classmethod
def random_init(cls):
random_gene = np.random.uniform(0, 1, size=(cls.n_variables,))
return cls.from_genotype(random_gene)
def dominate(self, another: NSGA2Solution):
return dominance_operator(self.fitness, another.fitness, larger_better=False)
@property
def fitness(self):
return np.array(super(ZDT1Solution, self)._fitness)
if __name__ == '__main__':
random.seed(42)
np.random.seed(42)
ZDT1Solution.set_num_variables(5)
nsga_ii = NSGA2(
solution_type=ZDT1Solution,
population_size=30,
n_generations=100,
crossover_rate=0.30,
mutation_rate=0.05
)
pareto_set = nsga_ii.search()
randomized = [ZDT1Solution.random_init() for _ in range(200)]
f1_rand = [s.fitness[0] for s in randomized]
f2_rand = [s.fitness[1] for s in randomized]
f1 = [solution.fitness[0] for solution in pareto_set]
f2 = [solution.fitness[1] for solution in pareto_set]
x = np.linspace(0, 1, 100)
y = 1 - np.sqrt(x)
plt.plot(x, y, c='red', label='true front')
plt.scatter(f1, f2, c='blue', label='nsga_ii front')
plt.scatter(f1_rand, f2_rand, c='green', label='random')
plt.legend()
plt.xlabel('f_1')
plt.ylabel('f_2')
plt.title('ZDT1 Objective Functions (no. variables = %d)' % ZDT1Solution.n_variables)
plt.show()