Skip to content

Commit b0f438f

Browse files
author
Julian Blank
committed
Revmoed Templated Individual
1 parent ae5a191 commit b0f438f

File tree

17 files changed

+322
-202
lines changed

17 files changed

+322
-202
lines changed

benchmark/benchmark_nsga2.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@
9191
prefix = "runs"
9292

9393
# name of the experiment
94-
name = "pynsga2-0.4.0"
94+
name = "pynsga2-0.4.2"
9595

9696
# number of runs to execute
9797
n_runs = 100

benchmark/benchmark_nsga3.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ def get_setup(n_obj):
203203
prefix = "runs"
204204

205205
# name of the experiment
206-
name = "pynsga3-0.4.0"
206+
name = "pynsga3-0.4.2"
207207

208208
# number of runs to execute
209209
n_runs = 50

pymoo/algorithms/ctaea.py

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -105,8 +105,6 @@ def __init__(self,
105105
self.ref_dirs = ref_dirs
106106
pop_size = len(ref_dirs)
107107

108-
kwargs['individual'] = Individual(rank=np.inf, niche=-1, FV=-1)
109-
110108
if 'survival' in kwargs:
111109
survival = kwargs['survival']
112110
del kwargs['survival']
@@ -129,7 +127,7 @@ def __init__(self,
129127

130128
def _initialize(self):
131129
# Prepare diversity archives
132-
da = Population(0, individual=self.individual)
130+
da = Population()
133131

134132
# create the initial population
135133
pop = self.initialization.do(self.problem, self.pop_size, algorithm=self)

pymoo/algorithms/genetic_algorithm.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
from pymoo.model.algorithm import Algorithm
22
from pymoo.model.duplicate import DefaultDuplicateElimination, NoDuplicateElimination
3-
from pymoo.model.individual import Individual
43
from pymoo.model.initialization import Initialization
54
from pymoo.model.mating import Mating
65
from pymoo.model.population import Population
@@ -20,7 +19,6 @@ def __init__(self,
2019
eliminate_duplicates=DefaultDuplicateElimination(),
2120
repair=None,
2221
mating=None,
23-
individual=Individual(),
2422
min_infeas_pop_size=0,
2523
**kwargs
2624
):
@@ -43,9 +41,6 @@ def __init__(self,
4341
if self.n_offsprings is None:
4442
self.n_offsprings = pop_size
4543

46-
# the object to be used to represent an individual - either individual or derived class
47-
self.individual = individual
48-
4944
# set the duplicate detection class - a boolean value chooses the default duplicate detection
5045
if isinstance(eliminate_duplicates, bool):
5146
if eliminate_duplicates:
@@ -59,7 +54,6 @@ def __init__(self,
5954
self.repair = repair if repair is not None else NoRepair()
6055

6156
self.initialization = Initialization(sampling,
62-
individual=individual,
6357
repair=self.repair,
6458
eliminate_duplicates=self.eliminate_duplicates)
6559

pymoo/algorithms/moead.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,10 @@
22
from scipy.spatial.distance import cdist
33

44
from pymoo.algorithms.genetic_algorithm import GeneticAlgorithm
5+
from pymoo.algorithms.nsga2 import NSGA2
56
from pymoo.factory import get_decomposition
7+
from pymoo.model.individual import Individual
8+
from pymoo.model.population import Population
69
from pymoo.operators.crossover.simulated_binary_crossover import SimulatedBinaryCrossover
710
from pymoo.operators.mutation.polynomial_mutation import PolynomialMutation
811
from pymoo.operators.sampling.random_sampling import FloatRandomSampling

pymoo/algorithms/nsga2.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def binary_tournament(pop, P, algorithm, **kwargs):
4646
S[i] = b
4747

4848
elif tournament_type == 'comp_by_rank_and_crowding':
49-
S[i] = compare(a, pop[a].rank, b, pop[b].rank,
49+
S[i] = compare(a, pop[a].get("rank"), b, pop[b].get("rank"),
5050
method='smaller_is_better')
5151

5252
else:
@@ -91,7 +91,6 @@ def __init__(self,
9191
9292
"""
9393

94-
kwargs['individual'] = Individual(rank=np.inf, crowding=-1)
9594
super().__init__(pop_size=pop_size,
9695
sampling=sampling,
9796
selection=selection,

pymoo/algorithms/nsga3.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,8 +82,6 @@ def __init__(self,
8282
"This might cause unwanted behavior of the algorithm. \nPlease make sure pop_size is equal or larger "
8383
"than the number of reference directions. ")
8484

85-
kwargs['individual'] = Individual(rank=np.inf, niche=-1, dist_to_niche=np.inf)
86-
8785
if 'survival' in kwargs:
8886
survival = kwargs['survival']
8987
del kwargs['survival']

pymoo/model/crossover.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,6 @@ def do(self, problem, pop, parents, **kwargs):
6161
X = X.reshape(-1, X.shape[-1])
6262

6363
# create a population object
64-
off = pop.new("X", X)
64+
off = Population.new("X", X)
6565

6666
return off

pymoo/model/individual.py

Lines changed: 103 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,118 @@
11
import copy
22

3-
from pymoo.util.dynamic_dict import DynamicDict
43

4+
class Individual:
55

6-
class Individual(DynamicDict):
6+
def __init__(self, X=None, F=None, CV=None, G=None, feasible=None, **kwargs) -> None:
7+
self.X = X
8+
self.F = F
9+
self.CV = CV
10+
self.G = G
11+
self.feasible = feasible
12+
self.data = kwargs
13+
self.attr = set(self.__dict__.keys())
714

815
def has(self, key):
9-
return key in self
16+
return key in self.attr or key in self.data
1017

11-
def set(self, key, val):
12-
self[key] = val
18+
def set(self, key, value):
19+
if key in self.attr:
20+
self.__dict__[key] = value
21+
else:
22+
self.data[key] = value
23+
return self
1324

1425
def copy(self, deep=False):
15-
if not deep:
16-
d = dict(**self.__dict__)
26+
ind = copy.copy(self)
27+
ind.data = copy.copy(self.data) if not deep else copy.deepcopy(self.data)
28+
return ind
29+
30+
def get(self, *keys):
31+
32+
def _get(key):
33+
if key in self.data:
34+
return self.data[key]
35+
elif key in self.attr:
36+
return self.__dict__[key]
37+
else:
38+
return None
39+
40+
ret = []
41+
42+
for key in keys:
43+
ret.append(_get(key))
44+
45+
if len(ret) == 1:
46+
return ret[0]
1747
else:
18-
d = copy.deepcopy(**self.__dict__)
48+
return tuple(ret)
1949

20-
ind = Individual(**d)
21-
return ind
50+
51+
class eIndividual:
52+
53+
def __init__(self, **kwargs) -> None:
54+
kwargs = {**kwargs, **dict(X=None, F=None, CV=None, G=None, feasible=None)}
55+
for k, v in kwargs.items():
56+
self.__dict__[k] = v
57+
58+
def has(self, key):
59+
return key in self.__dict__
60+
61+
def set(self, key, val):
62+
self.__dict__[key] = val
2263

2364
def get(self, *keys):
2465
if len(keys) == 1:
25-
key, = keys
26-
return super().get(key)
66+
return self.__dict__.get(keys[0])
67+
else:
68+
return tuple([self.__dict__.get(key) for key in keys])
69+
70+
def copy(self, deep=False):
71+
ind = copy.copy(self)
72+
ind.data = copy.copy(self.__dict__) if not deep else copy.deepcopy(self.__dict__)
73+
return ind
74+
75+
76+
if not deep:
77+
d = dict(self.__dict__)
2778
else:
28-
return tuple([super().get(key) for key in keys])
79+
d = copy.deepcopy(self.__dict__)
80+
ind = Individual(**d)
81+
return ind
82+
83+
# @property
84+
# def F(self):
85+
# attr = "F"
86+
# if attr in self.__dict__:
87+
# return self.__dict__[attr]
88+
# else:
89+
# return None
90+
91+
# Gets called when the item is not found via __getattribute__
92+
# def __getattr__(self, item):
93+
# return super(Individual, self).__setattr__(item, 'orphan')
94+
95+
def __getattr__(self, val):
96+
return self.__dict__.get(val)
97+
98+
# def __setitem__(self, key, value):
99+
# self.__dict__[key] = value
100+
#
101+
# def __getitem__(self, key):
102+
# return self.__dict__.get(key)
103+
104+
# def __getattr__(self, attr):
105+
#
106+
# if attr == "F":
107+
# if attr in self.__dict__:
108+
# return self.__dict__[attr]
109+
# else:
110+
# return None
111+
#
112+
# if attr in self.__dict__:
113+
# return self.__dict__[attr]
114+
#
115+
#
116+
#
117+
def __setattr__(self, key, value):
118+
self.__dict__[key] = value

pymoo/model/initialization.py

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
import numpy as np
22

33
from pymoo.model.duplicate import NoDuplicateElimination
4-
from pymoo.model.individual import Individual
54
from pymoo.model.population import Population
65
from pymoo.model.repair import NoRepair
76

@@ -10,13 +9,11 @@ class Initialization:
109

1110
def __init__(self,
1211
sampling,
13-
individual=Individual(),
1412
repair=None,
1513
eliminate_duplicates=None) -> None:
1614

1715
super().__init__()
1816
self.sampling = sampling
19-
self.individual = individual
2017
self.eliminate_duplicates = eliminate_duplicates if eliminate_duplicates is not None else NoDuplicateElimination()
2118
self.repair = repair if repair is not None else NoRepair()
2219

@@ -27,11 +24,10 @@ def do(self, problem, n_samples, **kwargs):
2724
pop = self.sampling
2825

2926
else:
30-
pop = Population(0, individual=self.individual)
3127
if isinstance(self.sampling, np.ndarray):
32-
pop = pop.new("X", self.sampling)
28+
pop = Population.new(X=self.sampling)
3329
else:
34-
pop = self.sampling.do(problem, n_samples, pop=pop, **kwargs)
30+
pop = self.sampling.do(problem, n_samples, **kwargs)
3531

3632
# repair all solutions that are not already evaluated
3733
not_eval_yet = [k for k in range(len(pop)) if pop[k].F is None]

0 commit comments

Comments
 (0)