@@ -53,16 +53,6 @@ def __init__(self, M):
53
53
self .position = np .zeros (M )
54
54
self ._potentialMembers = {}
55
55
56
- @staticmethod
57
- def generateRecursive (rps , pt , numObjs , left , total , element ):
58
- if element == numObjs - 1 :
59
- pt .position [element ] = left * 1.0 / total
60
- rps .append (pt )
61
- else :
62
- for i in range (left + 1 ):
63
- pt .position [element ] = i * 1.0 / total
64
- NsgaIII .ReferencePoint .generateRecursive (rps , pt , numObjs , left - i , total , element + 1 )
65
-
66
56
def addMember (self ):
67
57
self .memberSize += 1
68
58
@@ -94,12 +84,21 @@ def removePotentialMember(self, memberInd):
94
84
95
85
@staticmethod
96
86
def generateReferencePoints (rps , M , p ):
87
+ def generateRecursive (rps , pt , numObjs , left , total , element ):
88
+ if element == numObjs - 1 :
89
+ pt .position [element ] = left / total
90
+ rps .append (pt )
91
+ else :
92
+ for i in range (left + 1 ):
93
+ pt .position [element ] = i / total
94
+ generateRecursive (rps , pt , numObjs , left - i , total , element + 1 )
95
+
97
96
pt = NsgaIII .ReferencePoint (M )
98
- NsgaIII . ReferencePoint . generateRecursive (rps , pt , M , p [0 ], p [0 ], 0 )
97
+ generateRecursive (rps , pt , M , p [0 ], p [0 ], 0 )
99
98
100
99
if len (p ) > 1 : # two layers of reference points (Check Fig. 4 in NSGA-III paper)
101
100
insideRps = []
102
- NsgaIII . ReferencePoint . generateRecursive (insideRps , pt , M , p [1 ], p [1 ], 0 )
101
+ generateRecursive (insideRps , pt , M , p [1 ], p [1 ], 0 )
103
102
104
103
center = 1.0 / M
105
104
for insideRp in insideRps :
@@ -111,18 +110,13 @@ def generateReferencePoints(rps, M, p):
111
110
112
111
113
112
def perpendicularDistance (self , direction , point ):
114
- numerator , denominator = 0 , 0
115
- for i , dir in enumerate (direction ):
116
- numerator += dir * point [i ]
117
- denominator += dir ** 2
113
+ numerator , denominator = np .sum (direction * point ), np .sum (direction ** 2 )
118
114
119
115
if denominator <= 0 :
120
116
return sys .float_info .max
121
117
122
- k , d = numerator / denominator , 0
123
- for i , dir in enumerate (direction ):
124
- d += (k * dir - point [i ]) ** 2
125
-
118
+ k = numerator / denominator
119
+ d = np .sum ((k * direction - point ) ** 2 )
126
120
return np .sqrt (d )
127
121
128
122
def associate (self , rps , pop , fronts ):
@@ -139,25 +133,6 @@ def associate(self, rps, pop, fronts):
139
133
else :
140
134
rps [minRp ].addPotentialMember (memberInd , minDist )
141
135
142
- def guassianElimination (self , A , b ):
143
- N = len (A )
144
- for i in range (N ):
145
- A [i ].append (b [i ])
146
-
147
- for base in range (N - 1 ):
148
- for target in range (base + 1 , N ):
149
- ratio = A [target ][base ] / A [base ][base ]
150
- for term in range (len (A [base ])):
151
- A [target ][term ] -= A [base ][term ] * ratio
152
-
153
- x = np .zeros (N )
154
- for i in range (N - 1 , - 1 , - 1 ):
155
- for known in range (i + 1 , N ):
156
- A [i ][N ] -= A [i ][known ] * x [known ]
157
-
158
- x [i ] = A [i ][N ] / A [i ][i ]
159
-
160
- return x
161
136
162
137
# ASF: Achivement Scalarization Function
163
138
def ASF (self , objs , weight ):
@@ -228,11 +203,9 @@ def constructHyperplane(self, pop, extremePoints):
228
203
intercepts , negativeIntercept = [], False
229
204
if not duplicate :
230
205
# Find the equation of the hyperplane
231
- b , A = np .ones (numObj ), [[] * len (extremePoints )]
232
- for p , extremePoint in enumerate (extremePoints ):
233
- A [p ] = pop [extremePoint ].convertedObjectives
206
+ b , A = np .ones (numObj ), [pop [extremePt ].convertedObjectives for extremePt in extremePoints ]
207
+ x = np .linalg .solve (A , b )
234
208
235
- x = self .guassianElimination (A , b )
236
209
# Find intercepts
237
210
for f in range (numObj ):
238
211
intercepts .append (1.0 / x [f ])
@@ -251,11 +224,7 @@ def normalizeObjectives(self, pop, fronts, intercepts, idealPoint):
251
224
for front in fronts :
252
225
for i , ind in enumerate (front ):
253
226
convObjs = pop [ind ].convertedObjectives
254
- for f , convObj in enumerate (convObjs ):
255
- if abs (intercepts [f ] - idealPoint [f ]) > np .finfo (float ).eps : # avoid the divide-by-zero error
256
- convObj /= intercepts [f ] - idealPoint [f ]
257
- else :
258
- convObj /= np .finfo (float ).eps
227
+ convObjs /= intercepts - idealPoint + np .finfo (float ).eps
259
228
260
229
261
230
def nondominatedSort (self , pop ):
@@ -311,14 +280,11 @@ def translateObjectives(self, pop, fronts):
311
280
for front in fronts :
312
281
for ind in front :
313
282
pop [ind ].resizeConvertedObjectives (numObj )
314
- convertedObjectives = pop [ind ].convertedObjectives
315
- convertedObjectives [f ] = pop [ind ].objectives [f ] - minf
283
+ pop [ind ].convertedObjectives [f ] = pop [ind ].objectives [f ] - minf
316
284
317
285
return idealPoint
318
286
319
287
def selection (self , cur , rps ):
320
- next = []
321
-
322
288
# ---------- Step 4 in Algorithm 1: non-dominated sorting ----------
323
289
fronts = self .nondominatedSort (cur )
324
290
@@ -329,10 +295,9 @@ def selection(self, cur, rps):
329
295
last += 1
330
296
331
297
fronts = fronts [: last ] # remove useless individuals
332
-
298
+ next = []
333
299
for t in range (len (fronts ) - 1 ):
334
- for frontIndv in fronts [t ]:
335
- next .append (cur [frontIndv ])
300
+ next += [ cur [frontIndv ] for frontIndv in fronts [t ] ]
336
301
337
302
# ---------- Steps 9-10 in Algorithm 1 ----------
338
303
if len (next ) == self ._populationSize :
0 commit comments