Skip to content

Commit 58cdf5f

Browse files
committed
Refactor of SPEA2 finished
1 parent 7210b07 commit 58cdf5f

1 file changed

Lines changed: 49 additions & 39 deletions

File tree

src/jmetal/util/ranking.py

Lines changed: 49 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
from abc import ABC, abstractmethod
2-
from typing import List, TypeVar
2+
from typing import List, TypeVar, Dict, Any
3+
import numpy as np
34

45
from jmetal.util.comparator import (
56
Comparator,
@@ -137,47 +138,56 @@ def __init__(self, comparator: Comparator = DominanceComparator()):
137138

138139
def compute_ranking(self, solutions: List[S], k: int = None):
139140
"""
140-
Compute ranking of solutions.
141-
141+
Compute ranking of solutions using vectorized operations.
142+
142143
:param solutions: Solution list.
143144
:param k: Number of individuals.
144145
"""
145-
strength: List[int] = [0 for _ in range(len(solutions))]
146-
raw_fitness: List[int] = [0 for _ in range(len(solutions))]
147-
148-
# strength(i) = | {j | j < - SolutionSet and i dominate j} |
149-
for i in range(len(solutions)):
150-
for j in range(len(solutions)):
151-
if self.comparator.compare(solutions[i], solutions[j]) < 0:
152-
strength[i] += 1
153-
154-
# Calculate the raw fitness:
155-
# rawFitness(i) = |{sum strength(j) | j <- SolutionSet and j dominate i}|
156-
for i in range(len(solutions)):
157-
for j in range(len(solutions)):
158-
if self.comparator.compare(solutions[i], solutions[j]) == 1:
159-
raw_fitness[i] += strength[j]
160-
161-
max_fitness_value: int = 0
162-
for i in range(len(solutions)):
163-
solutions[i].attributes["strength_ranking"] = raw_fitness[i]
164-
if raw_fitness[i] > max_fitness_value:
165-
max_fitness_value = raw_fitness[i]
166-
167-
# Initialize the ranked sublists. In the worst case will be max_fitness_value + 1 different sublists
168-
self.ranked_sublists = [[] for _ in range(max_fitness_value + 1)]
169-
170-
# Assign each solution to its corresponding front
171-
for solution in solutions:
172-
self.ranked_sublists[int(solution.attributes["strength_ranking"])].append(solution)
173-
174-
# Remove empty fronts
175-
counter = 0
176-
while counter < len(self.ranked_sublists):
177-
if len(self.ranked_sublists[counter]) == 0:
178-
del self.ranked_sublists[counter]
179-
else:
180-
counter += 1
146+
if not solutions:
147+
self.ranked_sublists = []
148+
return self.ranked_sublists
149+
150+
n = len(solutions)
151+
strength = [0] * n
152+
raw_fitness = [0] * n
153+
154+
# Convert objectives to a NumPy array for vectorized operations
155+
objectives = np.array([s.objectives for s in solutions])
156+
157+
# Compute strength values (number of solutions each solution dominates)
158+
for i in range(n):
159+
# Vectorized dominance check: solution i dominates j if all objectives are <= and at least one is <
160+
dominated = np.all(objectives[i] <= objectives, axis=1) & np.any(objectives[i] < objectives, axis=1)
161+
# Don't count self-dominance
162+
strength[i] = np.sum(dominated) - 1 if dominated[i] else np.sum(dominated)
163+
164+
# Compute raw fitness (sum of strengths of dominators)
165+
for i in range(n):
166+
# Find solutions that dominate i
167+
dominators = np.where(
168+
np.all(objectives <= objectives[i], axis=1) &
169+
np.any(objectives < objectives[i], axis=1)
170+
)[0]
171+
# Sum strengths of dominators
172+
raw_fitness[i] = sum(strength[d] for d in dominators)
173+
174+
# Store raw fitness in the strength_ranking attribute
175+
max_fitness = 0
176+
for i in range(n):
177+
fitness = int(raw_fitness[i])
178+
solutions[i].attributes["strength_ranking"] = fitness
179+
if fitness > max_fitness:
180+
max_fitness = fitness
181+
182+
# Group solutions by raw fitness (ascending order)
183+
fitness_to_solutions: Dict[int, List[S]] = {}
184+
for i, fit in enumerate(raw_fitness):
185+
if fit not in fitness_to_solutions:
186+
fitness_to_solutions[fit] = []
187+
fitness_to_solutions[fit].append(solutions[i])
188+
189+
# Create ranked sublists sorted by fitness (ascending order)
190+
self.ranked_sublists = [fitness_to_solutions[f] for f in sorted(fitness_to_solutions)]
181191

182192
return self.ranked_sublists
183193

0 commit comments

Comments
 (0)