def __init__(self, comparator: Comparator = DominanceComparator()): super(BinaryTournamentSelection, self).__init__() self.comparator = comparator
class OMOPSO(ParticleSwarmOptimization): def __init__( self, problem: FloatProblem, swarm_size: int, uniform_mutation: UniformMutation, non_uniform_mutation: NonUniformMutation, leaders: Optional[BoundedArchive], epsilon: float, termination_criterion: TerminationCriterion, swarm_generator: Generator = store.default_generator, swarm_evaluator: Evaluator = store.default_evaluator, ): """This class implements the OMOPSO algorithm as described in todo Update this reference * SMPSO: A new PSO-based metaheuristic for multi-objective optimization The implementation of OMOPSO provided in jMetalPy follows the algorithm template described in the algorithm templates section of the documentation. :param problem: The problem to solve. :param swarm_size: Size of the swarm. :param leaders: Archive for leaders. """ super(OMOPSO, self).__init__(problem=problem, swarm_size=swarm_size) self.swarm_generator = swarm_generator self.swarm_evaluator = swarm_evaluator self.termination_criterion = termination_criterion self.observable.register(termination_criterion) self.uniform_mutation = uniform_mutation self.non_uniform_mutation = non_uniform_mutation self.leaders = leaders self.epsilon = epsilon self.epsilon_archive = NonDominatedSolutionsArchive( EpsilonDominanceComparator(epsilon)) self.c1_min = 1.5 self.c1_max = 2.0 self.c2_min = 1.5 self.c2_max = 2.0 self.r1_min = 0.0 self.r1_max = 1.0 self.r2_min = 0.0 self.r2_max = 1.0 self.weight_min = 0.1 self.weight_max = 0.5 self.change_velocity1 = -1 self.change_velocity2 = -1 self.dominance_comparator = DominanceComparator() self.speed = numpy.zeros( (self.swarm_size, self.problem.number_of_variables), dtype=float) def create_initial_solutions(self) -> List[FloatSolution]: return [ self.swarm_generator.new(self.problem) for _ in range(self.swarm_size) ] def evaluate(self, solution_list: List[FloatSolution]): return self.swarm_evaluator.evaluate(solution_list, self.problem) def stopping_condition_is_met(self) -> bool: return self.termination_criterion.is_met def initialize_global_best(self, swarm: List[FloatSolution]) -> None: for particle in swarm: if self.leaders.add(particle): self.epsilon_archive.add(copy(particle)) def initialize_particle_best(self, swarm: List[FloatSolution]) -> None: for particle in swarm: particle.attributes["local_best"] = copy(particle) def initialize_velocity(self, swarm: List[FloatSolution]) -> None: for i in range(self.swarm_size): for j in range(self.problem.number_of_variables): self.speed[i][j] = 0.0 def update_velocity(self, swarm: List[FloatSolution]) -> None: for i in range(self.swarm_size): best_particle = copy(swarm[i].attributes["local_best"]) best_global = self.select_global_best() r1 = round(random.uniform(self.r1_min, self.r1_max), 1) r2 = round(random.uniform(self.r2_min, self.r2_max), 1) c1 = round(random.uniform(self.c1_min, self.c1_max), 1) c2 = round(random.uniform(self.c2_min, self.c2_max), 1) w = round(random.uniform(self.weight_min, self.weight_max), 1) for var in range(swarm[i].number_of_variables): self.speed[i][var] = ( w * self.speed[i][var] + (c1 * r1 * (best_particle.variables[var] - swarm[i].variables[var])) + (c2 * r2 * (best_global.variables[var] - swarm[i].variables[var]))) def update_position(self, swarm: List[FloatSolution]) -> None: for i in range(self.swarm_size): particle = swarm[i] for j in range(particle.number_of_variables): particle.variables[j] += self.speed[i][j] if particle.variables[j] < self.problem.lower_bound[j]: particle.variables[j] = self.problem.lower_bound[j] self.speed[i][j] *= self.change_velocity1 if particle.variables[j] > self.problem.upper_bound[j]: particle.variables[j] = self.problem.upper_bound[j] self.speed[i][j] *= self.change_velocity2 def update_global_best(self, swarm: List[FloatSolution]) -> None: for particle in swarm: if self.leaders.add(copy(particle)): self.epsilon_archive.add(copy(particle)) def update_particle_best(self, swarm: List[FloatSolution]) -> None: for i in range(self.swarm_size): flag = self.dominance_comparator.compare( swarm[i], swarm[i].attributes["local_best"]) if flag != 1: swarm[i].attributes["local_best"] = copy(swarm[i]) def perturbation(self, swarm: List[FloatSolution]) -> None: self.non_uniform_mutation.set_current_iteration(self.evaluations / self.swarm_size) for i in range(self.swarm_size): if (i % 3) == 0: self.non_uniform_mutation.execute(swarm[i]) else: self.uniform_mutation.execute(swarm[i]) def select_global_best(self) -> FloatSolution: leaders = self.leaders.solution_list if len(leaders) > 2: particles = random.sample(leaders, 2) if self.leaders.comparator.compare(particles[0], particles[1]) < 1: best_global = copy(particles[0]) else: best_global = copy(particles[1]) else: best_global = copy(self.leaders.solution_list[0]) return best_global def __velocity_constriction(self, value: float, delta_max: [], delta_min: [], variable_index: int) -> float: result = value if value > delta_max[variable_index]: result = delta_max[variable_index] if value < delta_min[variable_index]: result = delta_min[variable_index] return result def __inertia_weight(self, wmax: float): return wmax def __constriction_coefficient(self, c1: float, c2: float) -> float: rho = c1 + c2 if rho <= 4: result = 1.0 else: result = 2.0 / (2.0 - rho - sqrt(pow(rho, 2.0) - 4.0 * rho)) return result def init_progress(self) -> None: self.evaluations = self.swarm_size self.leaders.compute_density_estimator() self.initialize_velocity(self.solutions) self.initialize_particle_best(self.solutions) self.initialize_global_best(self.solutions) def update_progress(self) -> None: self.evaluations += self.swarm_size self.leaders.compute_density_estimator() observable_data = self.get_observable_data() observable_data["SOLUTIONS"] = self.epsilon_archive.solution_list self.observable.notify_all(**observable_data) def get_result(self) -> List[FloatSolution]: return self.epsilon_archive.solution_list def get_name(self) -> str: return "OMOPSO"
def __init__(self, max_population_size: int, dominance_comparator: Comparator = DominanceComparator()): super(RankingAndCrowdingDistanceSelection, self).__init__() self.max_population_size = max_population_size self.dominance_comparator = dominance_comparator
def run(self) -> List[S]: pool_1_size = self.population_size pool_2_size = self.population_size selection_operator_1 = BinaryTournamentSelection() crossover_operator_1 = IntegerSBXCrossover(1.0, 20.0) mutation_operator_1 = IntegerPolynomialMutation( 1.0 / self.problem.number_of_variables, 20.0) selection_operator_2 = DifferentialEvolutionSelection() crossover_operator_2 = DifferentialEvolutionCrossover(0.2, 0.5, 0.5) dominance = DominanceComparator() max_iterations = self.max_iterations iterations = 0 parent_1: List[IntegerSolution] = [None, None] generational_hv: List[float] = [] current_gen = 0 """Create the initial subpopulation pools and evaluate them""" pool_1: List[IntegerSolution] = [] for i in range(pool_1_size): pool_1.append(self.problem.create_solution()) pool_1[i] = self.problem.evaluate(pool_1[i]) pool_2: List[IntegerSolution] = [] for i in range(pool_2_size): pool_2.append(self.problem.create_solution()) pool_2[i] = self.problem.evaluate(pool_2[i]) evaluations = pool_1_size + pool_2_size mix = self.mix_interval problem = self.problem h = HyperVolume(reference_point=[1] * self.problem.number_of_objectives) initial_population = True """The main evolutionary cycle""" while iterations < max_iterations: combi: List[IntegerSolution] = [] if not initial_population: offspring_pop_1: List[IntegerSolution] = [] offspring_pop_2: List[IntegerSolution] = [] """Evolve pool 1""" for i in range(pool_1_size): parent_1[0] = selection_operator_1.execute(pool_1) parent_1[1] = selection_operator_1.execute(pool_1) child_1: IntegerSolution = crossover_operator_1.execute( parent_1)[0] child_1 = mutation_operator_1.execute(child_1) child_1 = problem.evaluate(child_1) evaluations += 1 offspring_pop_1.append(child_1) """Evolve pool 2""" for i in range(pool_2_size): parent_2: List[ IntegerSolution] = selection_operator_2.execute(pool_2) crossover_operator_2.current_individual = pool_2[i] child_2 = crossover_operator_2.execute(parent_2) child_2 = problem.evaluate(child_2[0]) evaluations += 1 result = dominance.compare(pool_2[i], child_2) if result == -1: offspring_pop_2.append(pool_2[i]) elif result == 1: offspring_pop_2.append(child_2) else: offspring_pop_2.append(child_2) offspring_pop_2.append(pool_2[i]) ind_1 = pool_1[random.randint(0, pool_1_size - 1)] ind_2 = pool_2[random.randint(0, pool_2_size - 1)] offspring_pop_1.append(ind_1) offspring_pop_2.append(ind_2) offspring_pop_1.extend(pool_1) pool_1 = self.r.replace(offspring_pop_1[:pool_1_size], offspring_pop_1[pool_1_size:]) pool_2 = self.r.replace(offspring_pop_2[:pool_2_size], offspring_pop_2[pool_2_size:]) mix -= 1 if mix == 0: """Time to perform fitness sharing""" mix = self.mix_interval combi = combi + pool_1 + pool_2 # print("Combi size: ", len(combi)) """pool1size/10""" combi = self.r.replace( combi[:int(pool_1_size / 10)], combi[int(pool_1_size / 10):len(combi)], ) """ print( "Sizes: ", len(pool_1) + len(combi), len(pool_2) + len(combi), "\n", ) """ pool_1 = self.r.replace(pool_1, combi) pool_2 = self.r.replace(pool_2, combi) if initial_population: initial_population = False iterations += 1 print("Iterations: ", str(iterations)) """ hval_1 = h.compute([s.objectives for s in pool_1]) hval_2 = h.compute([s.objectives for s in pool_2]) print("hval_1: ", str(hval_1)) print("hval_2: ", str(hval_2), "\n") """ new_gen = int(evaluations / self.report_interval) if new_gen > current_gen: combi = combi + pool_1 + pool_2 combi = self.r.replace(combi[:(2 * pool_1_size)], combi[(2 * pool_1_size):]) hval = h.compute([s.objectives for s in combi]) for i in range(current_gen, new_gen, 1): generational_hv.append(hval) current_gen = new_gen """#Write runtime generational HV to file""" """Return the first non dominated front""" combi_ini: List[IntegerSolution] = [] combi_ini.extend(pool_1) combi_ini.extend(pool_2) combi_ini = self.r.replace( combi_ini[:pool_1_size + pool_2_size], combi_ini[pool_1_size + pool_2_size:], ) return combi_ini
def default_comparator(self): return DominanceComparator()
class BMOPSO(ParticleSwarmOptimization): def __init__( self, problem: BinaryProblem, swarm_size: int, mutation: BitFlipMutation, leaders: Optional[BoundedArchive], epsilon: float, termination_criterion: TerminationCriterion, swarm_generator: Generator = store.default_generator, swarm_evaluator: Evaluator = store.default_evaluator, ): super(BMOPSO, self).__init__(problem=problem, swarm_size=swarm_size) self.swarm_generator = swarm_generator self.swarm_evaluator = swarm_evaluator self.termination_criterion = termination_criterion self.observable.register(termination_criterion) self.mutation_operator = mutation self.leaders = leaders self.epsilon = epsilon self.epsilon_archive = NonDominatedSolutionListArchive( # EpsilonDominanceComparator(epsilon) DominanceComparator()) self.c1_min = 1.5 self.c1_max = 2.0 self.c2_min = 1.5 self.c2_max = 2.0 self.r1_min = 0.0 self.r1_max = 1.0 self.r2_min = 0.0 self.r2_max = 1.0 self.weight_min = 0.1 self.weight_max = 0.5 self.change_velocity1 = -1 self.change_velocity2 = -1 self.dominance_comparator = DominanceComparator() self.speed = numpy.zeros( ( self.swarm_size, self.problem.number_of_variables, self.problem.number_of_tests, ), dtype=float, ) def create_initial_solutions(self) -> List[BinarySolution]: return [ self.swarm_generator.new(self.problem) for _ in range(self.swarm_size) ] def evaluate(self, solution_list: List[BinarySolution]): return self.swarm_evaluator.evaluate(solution_list, self.problem) def stopping_condition_is_met(self) -> bool: return self.termination_criterion.is_met def initialize_global_best(self, swarm: List[BinarySolution]) -> None: for particle in swarm: if self.leaders.add(particle): self.epsilon_archive.add(copy(particle)) def initialize_particle_best(self, swarm: List[BinarySolution]) -> None: for particle in swarm: particle.attributes["local_best"] = copy(particle) def initialize_velocity(self, swarm: List[BinarySolution]) -> None: for i in range(self.swarm_size): for j in range(self.problem.number_of_variables): self.speed[i][j] = 0.0 def update_velocity(self, swarm: List[BinarySolution]) -> None: for i in range(self.swarm_size): best_particle = copy(swarm[i].attributes["local_best"]) best_global = self.select_global_best() r1 = round(random.uniform(self.r1_min, self.r1_max), 1) r2 = round(random.uniform(self.r2_min, self.r2_max), 1) c1 = round(random.uniform(self.c1_min, self.c1_max), 1) c2 = round(random.uniform(self.c2_min, self.c2_max), 1) w = round(random.uniform(self.weight_min, self.weight_max), 1) for var in range(swarm[i].number_of_variables): best_particle_diff = numpy.subtract( numpy.array(best_particle.variables[var]), numpy.array(swarm[i].variables[var]), dtype=numpy.float32, ) best_global_diff = numpy.subtract( numpy.array(best_global.variables[var]), numpy.array(swarm[i].variables[var]), dtype=numpy.float32, ) self.speed[i][var] = (w * numpy.array(self.speed[i][var]) + (c1 * r1 * best_particle_diff) + (c2 * r2 * best_global_diff)) def update_position(self, swarm: List[BinarySolution]) -> None: for i in range(self.swarm_size): particle = swarm[i] for j in range(particle.number_of_variables): particle.variables[j] = self.compute_position(self.speed[i][j]) def compute_position(self, speed): updated_positions = (numpy.random.random_sample(speed.shape) < self._sigmoid(speed)) * 1 return list(numpy.array(updated_positions, dtype=bool)) def _sigmoid(self, x): return 1 / (1 + numpy.exp(-x)) def update_global_best(self, swarm: List[BinarySolution]) -> None: for particle in swarm: if self.leaders.add(copy(particle)): self.epsilon_archive.add(copy(particle)) def update_particle_best(self, swarm: List[BinarySolution]) -> None: for i in range(self.swarm_size): flag = self.dominance_comparator.compare( swarm[i], swarm[i].attributes["local_best"]) if flag != 1: swarm[i].attributes["local_best"] = copy(swarm[i]) def perturbation(self, swarm: List[BinarySolution]) -> None: for i in range(self.swarm_size): if (i % 6) == 0: self.mutation_operator.execute(swarm[i]) def select_global_best(self) -> BinarySolution: leaders = self.leaders.solution_list if len(leaders) > 2: particles = random.sample(leaders, 2) if self.leaders.comparator.compare(particles[0], particles[1]) < 1: best_global = copy(particles[0]) else: best_global = copy(particles[1]) else: best_global = copy(self.leaders.solution_list[0]) return best_global def init_progress(self) -> None: self.evaluations = self.swarm_size self.leaders.compute_density_estimator() self.initialize_velocity(self.solutions) self.initialize_particle_best(self.solutions) self.initialize_global_best(self.solutions) def update_progress(self) -> None: self.evaluations += self.swarm_size self.leaders.compute_density_estimator() observable_data = self.get_observable_data() observable_data["SOLUTIONS"] = self.epsilon_archive.solution_list self.observable.notify_all(**observable_data) def get_result(self) -> List[BinarySolution]: return self.epsilon_archive.solution_list def get_name(self) -> str: return "my-BMOPSO"
def __init__(self): super(NonDominatedSolutionListArchive, self).__init__() self.comparator = DominanceComparator()
class DominanceComparatorTestCases(unittest.TestCase): def setUp(self): self.comparator = DominanceComparator() def test_should_dominance_comparator_raise_an_exception_if_the_first_solution_is_null( self): solution = None solution2 = FloatSolution(3, 2, [], []) with self.assertRaises(Exception): self.comparator.compare(solution, solution2) def test_should_dominance_comparator_raise_an_exception_if_the_second_solution_is_null( self): solution = FloatSolution(3, 2, [], []) solution2 = None with self.assertRaises(Exception): self.comparator.compare(solution, solution2) def test_should_dominance_comparator_return_zero_if_the_two_solutions_have_one_objective_with_the_same_value( self): solution = FloatSolution(3, 1, [], []) solution2 = FloatSolution(3, 1, [], []) solution.objectives = [1.0] solution2.objectives = [1.0] self.assertEqual(0, self.comparator.compare(solution, solution2)) def test_should_dominance_comparator_return_one_if_the_two_solutions_have_one_objective_and_the_second_one_is_lower( self): solution = FloatSolution(3, 1, [], []) solution2 = FloatSolution(3, 1, [], []) solution.objectives = [2.0] solution2.objectives = [1.0] self.assertEqual(1, self.comparator.compare(solution, solution2)) def test_should_dominance_comparator_return_minus_one_if_the_two_solutions_have_one_objective_and_the_first_one_is_lower( self): solution = FloatSolution(3, 1, [], []) solution2 = FloatSolution(3, 1, [], []) solution.objectives = [1.0] solution2.objectives = [2.0] self.assertEqual(-1, self.comparator.compare(solution, solution2)) def test_should_dominance_comparator_work_properly_case_a(self): """ Case A: solution1 has objectives [-1.0, 5.0, 9.0] and solution2 has [2.0, 6.0, 15.0] """ solution = FloatSolution(3, 3, [], []) solution2 = FloatSolution(3, 3, [], []) solution.objectives = [-1.0, 5.0, 9.0] solution2.objectives = [2.0, 6.0, 15.0] self.assertEqual(-1, self.comparator.compare(solution, solution2)) def test_should_dominance_comparator_work_properly_case_b(self): """ Case b: solution1 has objectives [-1.0, 5.0, 9.0] and solution2 has [-1.0, 5.0, 10.0] """ solution = FloatSolution(3, 3, [], []) solution2 = FloatSolution(3, 3, [], []) solution.objectives = [-1.0, 5.0, 9.0] solution2.objectives = [-1.0, 5.0, 10.0] self.assertEqual(-1, self.comparator.compare(solution, solution2)) def test_should_dominance_comparator_work_properly_case_c(self): """ Case c: solution1 has objectives [-1.0, 5.0, 9.0] and solution2 has [-2.0, 5.0, 9.0] """ solution = FloatSolution(3, 3, [], []) solution2 = FloatSolution(3, 3, [], []) solution.objectives = [-1.0, 5.0, 9.0] solution2.objectives = [-2.0, 5.0, 9.0] self.assertEqual(1, self.comparator.compare(solution, solution2)) def test_should_dominance_comparator_work_properly_case_d(self): """ Case d: solution1 has objectives [-1.0, 5.0, 9.0] and solution2 has [-1.0, 5.0, 8.0] """ solution = FloatSolution(3, 3, [], []) solution2 = FloatSolution(3, 3, [], []) solution.objectives = [-1.0, 5.0, 9.0] solution2.objectives = [-1.0, 5.0, 8.0] self.assertEqual(1, self.comparator.compare(solution, solution2)) def test_should_dominance_comparator_work_properly_case_3(self): """ Case d: solution1 has objectives [-1.0, 5.0, 9.0] and solution2 has [-2.0, 5.0, 10.0] """ solution = FloatSolution(3, 3, [], []) solution2 = FloatSolution(3, 3, [], []) solution.objectives = [-1.0, 5.0, 9.0] solution2.objectives = [-2.0, 5.0, 10.0] self.assertEqual(0, self.comparator.compare(solution, solution2)) def test_should_dominance_comparator_work_properly_with_constrains_case_1( self): """ Case 1: solution1 has a higher degree of constraint violation than solution 2 """ solution1 = FloatSolution(3, 3, [], []) solution2 = FloatSolution(3, 3, [], []) solution1.attributes["overall_constraint_violation"] = -0.1 solution2.attributes["overall_constraint_violation"] = -0.3 solution1.objectives = [-1.0, 5.0, 9.0] solution2.objectives = [-2.0, 5.0, 10.0] self.assertEqual(-1, self.comparator.compare(solution1, solution2)) def test_should_dominance_comparator_work_properly_with_constrains_case_2( self): """ Case 2: solution1 has a lower degree of constraint violation than solution 2 """ solution1 = FloatSolution(3, 3, [], []) solution2 = FloatSolution(3, 3, [], []) solution1.attributes["overall_constraint_violation"] = -0.3 solution2.attributes["overall_constraint_violation"] = -0.1 solution1.objectives = [-1.0, 5.0, 9.0] solution2.objectives = [-2.0, 5.0, 10.0] self.assertEqual(1, self.comparator.compare(solution1, solution2))
def setUp(self): self.comparator = DominanceComparator()
def __init__(self, dominance_comparator: Comparator = DominanceComparator()): super(NonDominatedSolutionsArchive, self).__init__() self.comparator = dominance_comparator
def run(self) -> List[S]: # selection operator 1 selection_operator_1 = BinaryTournamentSelection() # selection operator 2 selection_operator_2 = DifferentialEvolutionSelection() # crossover operator 1 crossover_operator_1 = SBXCrossover(1.0, 20.0) # crossover operator 2 crossover_operator_2 = DifferentialEvolutionCrossover(0.2, 0.5, 0.5) # crossover operator 3 crossover_operator_3 = DifferentialEvolutionCrossover(1.0, 0.5, 0.5) # mutation operator 1 mutation_operator_1 = PolynomialMutation( 1.0 / self.problem.number_of_variables, 20.0) # dominance comparator dominance = DominanceComparator() # array that stores the "generational" HV quality generational_hv: List[float] = [] parent_1: List[FloatSolution] = [None, None] parent_2: List[FloatSolution] = [] parent_3: List[FloatSolution] = [] # initialize some local and global variables pool_1: List[FloatSolution] = [] pool_2: List[FloatSolution] = [] # size of elite subset used for fitness sharing between subpopulations nrOfDirectionalSolutionsToEvolve = int(self.population_size / 5) # subpopulation 1 pool_1_size = int(self.population_size - (nrOfDirectionalSolutionsToEvolve / 2)) # subpopulation 2 pool_2_size = int(self.population_size - (nrOfDirectionalSolutionsToEvolve / 2)) print( str(pool_1_size) + " - " + str(nrOfDirectionalSolutionsToEvolve) + " - " + str(self.mix_interval)) evaluations = 0 current_gen = 0 directionalArchiveSize = 2 * self.population_size weights = self.__create_uniform_weights( directionalArchiveSize, self.problem.number_of_objectives) directionalArchive = self.__create_directional_archive(weights) neighbourhoods = self.__create_neighbourhoods(directionalArchive, self.population_size) nrOfReplacements = 1 iniID = 0 # Create the initial pools # pool1 pool_1: List[FloatSolution] = [] for _ in range(pool_1_size): new_solution = self.problem.create_solution() new_solution = self.problem.evaluate(new_solution) evaluations += 1 pool_1.append(new_solution) self.__update_extreme_values(new_solution) dr = directionalArchive[iniID] dr.curr_sol = new_solution iniID += 1 # pool2 pool_2: List[FloatSolution] = [] for _ in range(pool_2_size): new_solution = self.problem.create_solution() new_solution = self.problem.evaluate(new_solution) evaluations += 1 pool_2.append(new_solution) self.__update_extreme_values(new_solution) dr = directionalArchive[iniID] dr.curr_sol = new_solution iniID += 1 # directional archive initialization pool_A: List[FloatSolution] = [] while iniID < directionalArchiveSize: new_solution = self.problem.create_solution() new_solution = self.problem.evaluate(new_solution) evaluations += 1 pool_A.append(new_solution) self.__update_extreme_values(new_solution) dr = directionalArchive[iniID] dr.curr_sol = new_solution iniID += 1 mix = self.mix_interval h = HyperVolume(reference_point=[1] * self.problem.number_of_objectives) insertionRate: List[float] = [0, 0, 0] bonusEvals: List[int] = [0, 0, nrOfDirectionalSolutionsToEvolve] testRun = True # record the generational HV of the initial population combiAll: List[FloatSolution] = [] cGen = int(evaluations / self.report_interval) if cGen > 0: combiAll = pool_1 + pool_2 + pool_A combiAll = self.r.replace( combiAll[:pool_1_size + pool_2_size], combiAll[pool_1_size + pool_2_size:], ) hval = h.compute([s.objectives for s in combiAll]) for _ in range(cGen): generational_hv.append(hval) current_gen = cGen # the main loop of the algorithm while evaluations < self.max_evaluations: offspringPop1: List[FloatSolution] = [] offspringPop2: List[FloatSolution] = [] offspringPop3: List[FloatSolution] = [] dirInsertPool1: List[FloatSolution] = [] dirInsertPool2: List[FloatSolution] = [] dirInsertPool3: List[FloatSolution] = [] # evolve pool1 - using SPEA2 evolutionary model nfe: int = 0 while nfe < (pool_1_size + bonusEvals[0]): parent_1[0] = selection_operator_1.execute(pool_1) parent_1[1] = selection_operator_1.execute(pool_1) child1a: FloatSolution = crossover_operator_1.execute( parent_1)[0] child1a = mutation_operator_1.execute(child1a) child1a = self.problem.evaluate(child1a) evaluations += 1 nfe += 1 offspringPop1.append(child1a) dirInsertPool1.append(child1a) # evolve pool2 - using DEMO SP evolutionary model i: int = 0 unselectedIDs: List[int] = [] for ID in range(len(pool_2)): unselectedIDs.append(ID) nfe = 0 while nfe < (pool_2_size + bonusEvals[1]): index = random.randint(0, len(unselectedIDs) - 1) i = unselectedIDs[index] unselectedIDs.pop(index) parent_2 = selection_operator_2.execute(pool_2) crossover_operator_2.current_individual = pool_2[i] child2 = crossover_operator_2.execute(parent_2) child2 = self.problem.evaluate(child2[0]) evaluations += 1 nfe += 1 result = dominance.compare(pool_2[i], child2) if result == -1: # solution i dominates child offspringPop2.append(pool_2[i]) elif result == 1: # child dominates offspringPop2.append(child2) else: # the two solutions are non-dominated offspringPop2.append(child2) offspringPop2.append(pool_2[i]) dirInsertPool2.append(child2) if len(unselectedIDs) == 0: for ID in range(len(pool_2)): unselectedIDs.append(random.randint( 0, len(pool_2) - 1)) # evolve pool3 - Directional Decomposition DE/rand/1/bin IDs = self.__compute_neighbourhood_Nfe_since_last_update( neighbourhoods, directionalArchive, nrOfDirectionalSolutionsToEvolve) nfe = 0 for j in range(len(IDs)): if nfe < bonusEvals[2]: nfe += 1 else: break cID = IDs[j] chosenSol: FloatSolution = None if directionalArchive[cID].curr_sol != None: chosenSol = directionalArchive[cID].curr_sol else: chosenSol = pool_1[0] print("error!") parent_3: List[FloatSolution] = [None, None, None] r1 = random.randint(0, len(neighbourhoods[cID]) - 1) r2 = random.randint(0, len(neighbourhoods[cID]) - 1) r3 = random.randint(0, len(neighbourhoods[cID]) - 1) while r2 == r1: r2 = random.randint(0, len(neighbourhoods[cID]) - 1) while r3 == r1 or r3 == r2: r3 = random.randint(0, len(neighbourhoods[cID]) - 1) parent_3[0] = directionalArchive[r1].curr_sol parent_3[1] = directionalArchive[r2].curr_sol parent_3[2] = directionalArchive[r3].curr_sol crossover_operator_3.current_individual = chosenSol child3 = crossover_operator_3.execute(parent_3)[0] child3 = mutation_operator_1.execute(child3) child3 = self.problem.evaluate(child3) evaluations += 1 dirInsertPool3.append(child3) # compute directional improvements # pool1 improvements = 0 for j in range(len(dirInsertPool1)): testSol = dirInsertPool1[j] self.__update_extreme_values(testSol) improvements += self.__update_neighbourhoods( directionalArchive, testSol, nrOfReplacements) insertionRate[0] += (1.0 * improvements) / len(dirInsertPool1) # pool2 improvements = 0 for j in range(len(dirInsertPool2)): testSol = dirInsertPool2[j] self.__update_extreme_values(testSol) improvements += self.__update_neighbourhoods( directionalArchive, testSol, nrOfReplacements) insertionRate[1] += (1.0 * improvements) / len(dirInsertPool2) # pool3 improvements = 0 for j in range(len(dirInsertPool3)): testSol = dirInsertPool3[j] self.__update_extreme_values(testSol) improvements += self.__update_neighbourhoods( directionalArchive, testSol, nrOfReplacements) # on java, dividing a floating number by 0, returns NaN # on python, dividing a floating number by 0, returns an exception if len(dirInsertPool3) == 0: insertionRate[2] = None else: insertionRate[2] += (1.0 * improvements) / len(dirInsertPool3) for dr in directionalArchive: offspringPop3.append(dr.curr_sol) offspringPop1 = offspringPop1 + pool_1 pool_1 = self.r.replace(offspringPop1[:pool_1_size], offspringPop1[pool_1_size:]) pool_2 = self.r.replace(offspringPop2[:pool_2_size], offspringPop2[pool_2_size:]) combi: List[FloatSolution] = [] mix -= 1 if mix == 0: mix = self.mix_interval combi = combi + pool_1 + pool_2 + offspringPop3 print("Combi size: " + str(len(combi))) combi = self.r.replace( combi[:nrOfDirectionalSolutionsToEvolve], combi[nrOfDirectionalSolutionsToEvolve:], ) insertionRate[0] /= self.mix_interval insertionRate[1] /= self.mix_interval if insertionRate[2] != None: insertionRate[2] /= self.mix_interval """ print( "Insertion rates: " + str(insertionRate[0]) + " - " + str(insertionRate[1]) + " - " + str(insertionRate[2]) + " - Test run:" + str(testRun) ) """ if testRun: if (insertionRate[0] > insertionRate[1]) and ( insertionRate[0] > insertionRate[2]): print("SPEA2 win - bonus run!") bonusEvals[0] = nrOfDirectionalSolutionsToEvolve bonusEvals[1] = 0 bonusEvals[2] = 0 if (insertionRate[1] > insertionRate[0]) and ( insertionRate[1] > insertionRate[2]): print("DE win - bonus run!") bonusEvals[0] = 0 bonusEvals[1] = nrOfDirectionalSolutionsToEvolve bonusEvals[2] = 0 if (insertionRate[2] > insertionRate[0]) and ( insertionRate[2] > insertionRate[1]): print("Directional win - no bonus!") bonusEvals[0] = 0 bonusEvals[1] = 0 bonusEvals[2] = nrOfDirectionalSolutionsToEvolve else: print("Test run - no bonus!") bonusEvals[0] = 0 bonusEvals[1] = 0 bonusEvals[2] = nrOfDirectionalSolutionsToEvolve testRun = not testRun insertionRate[0] = 0.0 insertionRate[1] = 0.0 insertionRate[2] = 0.0 pool_1 = pool_1 + combi pool_2 = pool_2 + combi print("Sizes: " + str(len(pool_1)) + " " + str(len(pool_2))) pool_1 = self.r.replace(pool_1[:pool_1_size], pool_1[pool_1_size:]) pool_2 = self.r.replace(pool_2[:pool_2_size], pool_2[pool_2_size:]) self.__clear_Nfe_history(directionalArchive) hVal1 = h.compute([s.objectives for s in pool_1]) hVal2 = h.compute([s.objectives for s in pool_2]) hVal3 = h.compute([s.objectives for s in offspringPop3]) newGen = int(evaluations / self.report_interval) if newGen > current_gen: print("Hypervolume: " + str(newGen) + " - " + str(hVal1) + " - " + str(hVal2) + " - " + str(hVal3)) combi = combi + pool_1 + pool_2 + offspringPop3 combi = self.r.replace(combi[:self.population_size * 2], combi[self.population_size * 2:]) hval = h.compute([s.objectives for s in combi]) for j in range(current_gen, newGen): generational_hv.append(hval) current_gen = newGen # return the final combined non-dominated set of maximum size = (populationSize * 2) combiAll: List[FloatSolution] = [] combiAll = combiAll + pool_1 + pool_2 + pool_A combiAll = self.r.replace(combiAll[:self.population_size * 2], combiAll[self.population_size * 2:]) return combiAll
def __init__(self, comparator: Comparator = DominanceComparator()): super(Ranking, self).__init__() self.number_of_comparisons = 0 self.ranked_sublists = [] self.comparator = comparator
def __init__(self, comparator: Comparator = DominanceComparator()): super(FastNonDominatedRanking, self).__init__(comparator)
def __init__(self, comparator: Comparator = DominanceComparator()): super(StrengthRanking, self).__init__(comparator)
class SMPSO(ParticleSwarmOptimization): def __init__( self, problem: FloatProblem, swarm_size: int, mutation: Mutation, leaders: Optional[BoundedArchive], termination_criterion: TerminationCriterion = store. default_termination_criteria, swarm_generator: Generator = store.default_generator, swarm_evaluator: Evaluator = store.default_evaluator, ): """This class implements the SMPSO algorithm as described in * SMPSO: A new PSO-based metaheuristic for multi-objective optimization * MCDM 2009. DOI: `<http://dx.doi.org/10.1109/MCDM.2009.4938830/>`_. The implementation of SMPSO provided in jMetalPy follows the algorithm template described in the algorithm templates section of the documentation. :param problem: The problem to solve. :param swarm_size: Size of the swarm. :param max_evaluations: Maximum number of evaluations/iterations. :param mutation: Mutation operator (see :py:mod:`jmetal.operator.mutation`). :param leaders: Archive for leaders. """ super(SMPSO, self).__init__(problem=problem, swarm_size=swarm_size) self.swarm_generator = swarm_generator self.swarm_evaluator = swarm_evaluator self.termination_criterion = termination_criterion self.observable.register(termination_criterion) self.mutation_operator = mutation self.leaders = leaders self.c1_min = 1.5 self.c1_max = 2.5 self.c2_min = 1.5 self.c2_max = 2.5 self.r1_min = 0.0 self.r1_max = 1.0 self.r2_min = 0.0 self.r2_max = 1.0 self.min_weight = 0.1 self.max_weight = 0.1 self.change_velocity1 = -1 self.change_velocity2 = -1 self.dominance_comparator = DominanceComparator() self.speed = numpy.zeros( (self.swarm_size, self.problem.number_of_variables), dtype=float) self.delta_max, self.delta_min = ( numpy.empty(problem.number_of_variables), numpy.empty(problem.number_of_variables), ) def create_initial_solutions(self) -> List[FloatSolution]: return [ self.swarm_generator.new(self.problem) for _ in range(self.swarm_size) ] def evaluate(self, solution_list: List[FloatSolution]): return self.swarm_evaluator.evaluate(solution_list, self.problem) def stopping_condition_is_met(self) -> bool: return self.termination_criterion.is_met def initialize_global_best(self, swarm: List[FloatSolution]) -> None: for particle in swarm: self.leaders.add(copy(particle)) def initialize_particle_best(self, swarm: List[FloatSolution]) -> None: for particle in swarm: particle.attributes["local_best"] = copy(particle) def initialize_velocity(self, swarm: List[FloatSolution]) -> None: for i in range(self.problem.number_of_variables): self.delta_max[i] = (self.problem.upper_bound[i] - self.problem.lower_bound[i]) / 2.0 self.delta_min = -1.0 * self.delta_max def update_velocity(self, swarm: List[FloatSolution]) -> None: for i in range(self.swarm_size): best_particle = copy(swarm[i].attributes["local_best"]) best_global = self.select_global_best() r1 = round(random.uniform(self.r1_min, self.r1_max), 1) r2 = round(random.uniform(self.r2_min, self.r2_max), 1) c1 = round(random.uniform(self.c1_min, self.c1_max), 1) c2 = round(random.uniform(self.c2_min, self.c2_max), 1) wmax = self.max_weight wmin = self.min_weight for var in range(swarm[i].number_of_variables): self.speed[i][var] = self.__velocity_constriction( self.__constriction_coefficient(c1, c2) * ((self.__inertia_weight(wmax) * self.speed[i][var]) + (c1 * r1 * (best_particle.variables[var] - swarm[i].variables[var])) + (c2 * r2 * (best_global.variables[var] - swarm[i].variables[var]))), self.delta_max, self.delta_min, var, ) def update_position(self, swarm: List[FloatSolution]) -> None: for i in range(self.swarm_size): particle = swarm[i] for j in range(particle.number_of_variables): particle.variables[j] += self.speed[i][j] if particle.variables[j] < self.problem.lower_bound[j]: particle.variables[j] = self.problem.lower_bound[j] self.speed[i][j] *= self.change_velocity1 if particle.variables[j] > self.problem.upper_bound[j]: particle.variables[j] = self.problem.upper_bound[j] self.speed[i][j] *= self.change_velocity2 def update_global_best(self, swarm: List[FloatSolution]) -> None: for particle in swarm: self.leaders.add(copy(particle)) def update_particle_best(self, swarm: List[FloatSolution]) -> None: for i in range(self.swarm_size): flag = self.dominance_comparator.compare( swarm[i], swarm[i].attributes["local_best"]) if flag != 1: swarm[i].attributes["local_best"] = copy(swarm[i]) def perturbation(self, swarm: List[FloatSolution]) -> None: for i in range(self.swarm_size): if (i % 6) == 0: self.mutation_operator.execute(swarm[i]) def select_global_best(self) -> FloatSolution: leaders = self.leaders.solution_list if len(leaders) > 2: particles = random.sample(leaders, 2) if self.leaders.comparator.compare(particles[0], particles[1]) < 1: best_global = copy(particles[0]) else: best_global = copy(particles[1]) else: best_global = copy(self.leaders.solution_list[0]) return best_global def __velocity_constriction(self, value: float, delta_max: [], delta_min: [], variable_index: int) -> float: result = value if value > delta_max[variable_index]: result = delta_max[variable_index] if value < delta_min[variable_index]: result = delta_min[variable_index] return result def __inertia_weight(self, wmax: float): return wmax def __constriction_coefficient(self, c1: float, c2: float) -> float: rho = c1 + c2 if rho <= 4: result = 1.0 else: result = 2.0 / (2.0 - rho - sqrt(pow(rho, 2.0) - 4.0 * rho)) return result def init_progress(self) -> None: self.evaluations = self.swarm_size self.leaders.compute_density_estimator() self.initialize_velocity(self.solutions) self.initialize_particle_best(self.solutions) self.initialize_global_best(self.solutions) def update_progress(self) -> None: self.evaluations += self.swarm_size self.leaders.compute_density_estimator() observable_data = self.get_observable_data() observable_data["SOLUTIONS"] = self.leaders.solution_list self.observable.notify_all(**observable_data) def get_result(self) -> List[FloatSolution]: return self.leaders.solution_list def get_name(self) -> str: return "SMPSO"
class SMPSO(ParticleSwarmOptimization): def __init__(self, problem: FloatProblem, swarm_size: int, max_evaluations: int, mutation: Mutation[FloatSolution], leaders: BoundedArchive[FloatSolution], observable: Observable = DefaultObservable(), evaluator: Evaluator[FloatSolution] = SequentialEvaluator[ FloatSolution]()): super(SMPSO, self).__init__() self.problem = problem self.swarm_size = swarm_size self.max_evaluations = max_evaluations self.mutation: Mutation[FloatSolution] = mutation self.leaders = leaders self.observable = observable self.evaluator = evaluator self.evaluations = 0 self.c1_min = 1.5 self.c1_max = 2.5 self.c2_min = 1.5 self.c2_max = 2.5 self.min_weight = 0.1 self.max_weight = 0.1 self.change_velocity1 = -1 self.change_velocity2 = -1 self.dominance_comparator = DominanceComparator() self.speed = numpy.zeros( (self.swarm_size, self.problem.number_of_variables), dtype=float) self.delta_max = numpy.empty(problem.number_of_variables) self.delta_min = numpy.empty(problem.number_of_variables) for i in range(problem.number_of_variables): self.delta_max[i] = (self.problem.upper_bound[i] - self.problem.lower_bound[i]) / 2.0 self.delta_min = -1.0 * self.delta_max def init_progress(self) -> None: self.evaluations = self.swarm_size self.leaders.compute_density_estimator() def update_progress(self) -> None: self.evaluations += self.swarm_size self.leaders.compute_density_estimator() observable_data = { 'evaluations': self.evaluations, 'population': self.swarm, 'computing time': self.get_current_computing_time() } self.observable.notify_all(**observable_data) def is_stopping_condition_reached(self) -> bool: return self.evaluations >= self.max_evaluations def create_initial_swarm(self) -> List[FloatSolution]: swarm = [] for i in range(self.swarm_size): swarm.append(self.problem.create_solution()) return swarm def evaluate_swarm(self, swarm: List[FloatSolution]) -> List[FloatSolution]: return self.evaluator.evaluate(swarm, self.problem) def initialize_global_best(self, swarm: List[FloatSolution]) -> None: for particle in self.swarm: self.leaders.add(particle) def initialize_particle_best(self, swarm: List[FloatSolution]) -> None: for particle in self.swarm: particle.attributes["local_best"] = copy(particle) def initialize_velocity(self, swarm: List[FloatSolution]) -> None: pass # Velocity initialized in the constructor def update_velocity(self, swarm: List[FloatSolution]) -> None: for i in range(self.swarm_size): particle = copy(self.swarm[i]) best_particle = copy(self.swarm[i].attributes["local_best"]) best_global = self.__select_global_best() r1 = Random.random() r2 = Random.random() c1 = Random.uniform(self.c1_min, self.c1_max) c2 = Random.uniform(self.c2_min, self.c2_max) wmin = self.min_weight wmax = self.max_weight for var in range(self.problem.number_of_variables): self.speed[i][var] = \ self.__velocity_constriction(self.__constriction_coefficient(c1, c2) * \ (wmax * self.speed[i][var] + c1 * r1 * (best_particle.variables[var] - particle.variables[var]) + c2 * r2 * (best_global.variables[var] - particle.variables[var])), var) def update_position(self, swarm: List[FloatSolution]) -> None: for i in range(self.swarm_size): particle = self.swarm[i] for j in particle.variables: particle.variables[j] += self.speed[i][j] if particle.variables[j] < self.problem.lower_bound[j]: particle.variables[j] = self.problem.lower_bound[j] self.speed[i][j] *= self.change_velocity1 if particle.variables[j] > self.problem.upper_bound[j]: particle.variables[j] = self.problem.upper_bound[j] self.speed[i][j] *= self.change_velocity2 def perturbation(self, swarm: List[FloatSolution]) -> None: for particle in self.swarm: self.mutation.execute(particle) def update_global_best(self, swarm: List[FloatSolution]) -> None: for particle in self.swarm: self.leaders.add(copy(particle)) def update_particle_best(self, swarm: List[FloatSolution]) -> None: for i in range(self.swarm_size): flag = self.dominance_comparator.compare( self.swarm[i], self.swarm[i].attribute["local_best"]) if flag is not 1: swarm[i].attributes["local_best"] = copy(self.swarm[i]) def get_result(self) -> List[FloatSolution]: self.leaders.solution_list def __select_global_best(self) -> FloatSolution: #pos1 = Random.randint(0, len(self.leaders.solution_list) - 1) #pos2 = Random.randint(0, len(self.leaders.solution_list) - 1) best_global = None particles = Random.sample(self.leaders.solution_list, 2) if self.leaders.get_comparator().compare(particles[0], particles[1]) < 1: best_global = copy(particles[0]) else: best_global = copy(particles[1]) return best_global def __velocity_constriction(self, value: float, variable_index: int) -> float: result = None if value > self.delta_max[variable_index]: result = self.delta_max[variable_index] if value < self.delta_min[variable_index]: result = self.delta_min[variable_index] return result def __constriction_coefficient(self, c1: float, c2: float) -> float: result = 0.0 rho = c1 + c2 if rho <= 4: result = 1.0 else: result = 2.0 / (2.0 - rho - numpy.sqrt(pow(rho, 2.0) - 4.0 * rho)) return result
from jmetal.util.termination_criterion import StoppingByEvaluations if __name__ == '__main__': binary_string_length = 512 problem = OneMax(binary_string_length) max_evaluations = 20000 algorithm = NSGAII( problem=problem, population_size=100, offspring_population_size=1, mutation=BitFlipMutation(probability=1.0 / binary_string_length), crossover=SPXCrossover(probability=1.0), termination_criterion=StoppingByEvaluations(max=max_evaluations), dominance_comparator=DominanceComparator() ) algorithm.observable.register(observer=PrintObjectivesObserver(1000)) algorithm.run() front = algorithm.get_result() # Save results to file print_function_values_to_file(front, 'FUN.'+ algorithm.get_name()+"-"+problem.get_name()) print_variables_to_file(front, 'VAR.' + algorithm.get_name()+"-"+problem.get_name()) print('Algorithm (continuous problem): ' + algorithm.get_name()) print('Problem: ' + problem.get_name()) print('Computing time: ' + str(algorithm.total_computing_time))
class StandardPSO(ParticleSwarmOptimization): def __init__(self, problem: FloatProblem, swarm_size: int, leaders: Optional[BoundedArchive], termination_criterion: TerminationCriterion = store. default_termination_criteria, swarm_generator: Generator = store.default_generator, swarm_evaluator: Evaluator = store.default_evaluator, omega: float = 0.8, phi_p: float = 1.0, phi_g: float = 1.0, learning_rate: float = 1.0): """ This class implements a standard PSO algorithm. """ super(StandardPSO, self).__init__(problem=problem, swarm_size=swarm_size) self.swarm_generator = swarm_generator self.swarm_evaluator = swarm_evaluator self.termination_criterion = termination_criterion self.observable.register(termination_criterion) self.leaders = leaders self.omega = omega # Weight of previous speed. self.phi_p = phi_p # How the difference between local best and particle influences the speed change. self.phi_g = phi_g # How the difference between global best and particle influences the speed change. self.learning_rate = learning_rate # How speed influences position change. self.dominance_comparator = DominanceComparator() self.speed = np.zeros( (self.swarm_size, self.problem.number_of_variables), dtype=float) def create_initial_solutions(self) -> List[FloatSolution]: return [ self.swarm_generator.new(self.problem) for _ in range(self.swarm_size) ] def evaluate(self, solution_list: List[FloatSolution]): return self.swarm_evaluator.evaluate(solution_list, self.problem) def stopping_condition_is_met(self) -> bool: return self.termination_criterion.is_met def initialize_global_best(self, swarm: List[FloatSolution]) -> None: for particle in swarm: self.leaders.add(copy(particle)) def initialize_particle_best(self, swarm: List[FloatSolution]) -> None: for particle in swarm: particle.attributes['local_best'] = copy(particle) def initialize_velocity(self, swarm: List[FloatSolution]) -> None: pass def update_velocity(self, swarm: List[FloatSolution]) -> None: for i in range(self.swarm_size): best_particle = copy(swarm[i].attributes['local_best']) best_global = self.select_global_best() for var in range(swarm[i].number_of_variables): r_p = random.random() r_g = random.random() self.speed[i][var] = self.omega * self.speed[i][var] + \ self.phi_p * r_p * (best_particle.variables[var] - swarm[i].variables[var]) + \ self.phi_g * r_g * (best_global.variables[var] - swarm[i].variables[var]) def update_position(self, swarm: List[FloatSolution]) -> None: for i in range(self.swarm_size): particle = swarm[i] for j in range(particle.number_of_variables): particle.variables[j] += self.learning_rate * self.speed[i][j] if particle.variables[j] < self.problem.lower_bound[j]: particle.variables[j] = self.problem.lower_bound[j] self.speed[i][j] *= -1 if particle.variables[j] > self.problem.upper_bound[j]: particle.variables[j] = self.problem.upper_bound[j] self.speed[i][j] *= -1 def update_global_best(self, swarm: List[FloatSolution]) -> None: for particle in swarm: self.leaders.add(copy(particle)) def update_particle_best(self, swarm: List[FloatSolution]) -> None: for i in range(self.swarm_size): flag = self.dominance_comparator.compare( swarm[i], swarm[i].attributes['local_best']) if flag != 1: swarm[i].attributes['local_best'] = copy(swarm[i]) def select_global_best(self) -> FloatSolution: leaders = self.leaders.solution_list if len(leaders) > 2: particles = random.sample(leaders, 2) if self.leaders.comparator.compare(particles[0], particles[1]) < 1: best_global = copy(particles[0]) else: best_global = copy(particles[1]) else: best_global = copy(self.leaders.solution_list[0]) return best_global def init_progress(self) -> None: self.evaluations = self.swarm_size self.leaders.compute_density_estimator() self.initialize_velocity(self.solutions) self.initialize_particle_best(self.solutions) self.initialize_global_best(self.solutions) def step(self): self.update_velocity(self.solutions) self.update_position(self.solutions) self.solutions = self.evaluate(self.solutions) self.update_global_best(self.solutions) self.update_particle_best(self.solutions) def update_progress(self) -> None: self.evaluations += self.swarm_size self.leaders.compute_density_estimator() observable_data = self.get_observable_data() observable_data['SOLUTIONS'] = self.leaders.solution_list self.observable.notify_all(**observable_data) def get_result(self) -> List[FloatSolution]: return self.leaders.solution_list[0] def get_name(self) -> str: return 'StandardPSO' def perturbation(self, swarm: List[FloatSolution]) -> None: pass