class Terminator(TerminationCriterion): # initialize def __init__(self, tolerance, max_evaluation): super().__init__() # store the parameters self.max_evaluation = max_evaluation # self.timeout = timeout self.tolerance = tolerance # prepare members self.evaluations = 0 # self.seconds = 0.0 self.counter = 0 self.front = NonDominatedSolutionsArchive() self.last_violation = None self.last_front_size = None # check violation def violation_count(self, solutions): count = 0 for solution in solutions: if not all([c >= 0.0 for c in solution.constraints]): count += 1 return count # update the front def update_front(self, solutions): new_solution_num = 0 for solution in solutions: # solution.objectives = [round(o, 0) for o in solution.objectives] if self.front.add(solution): new_solution_num += 1 return new_solution_num # update def update(self, *args, **kwargs): self.evaluations = kwargs['EVALUATIONS'] if self.evaluations % 500 == 0: print(self.evaluations) # self.seconds = kwargs['COMPUTING_TIME'] solutions = kwargs['SOLUTIONS'] # check front_size = self.update_front(solutions) violation = self.violation_count(solutions) if self.last_front_size == self.front.size() and self.last_violation == violation: self.counter += 1 else: self.counter = 0 # update self.last_front_size = self.front.size() self.last_violation = violation print('counter: ', self.counter, ' front_size: ', self.front.size(), ' violation: ', violation) # print(self.violation_count(solutions)) # finish condition @property def is_met(self): # if self.evaluations >= self.max_evaluation: # return True # return self.seconds >= self.timeout or self.counter >= self.tolerance return self.front.size() == POPULATION_SIZE and self.counter >= self.tolerance
def __init__( self, problem: Problem[S], termination_criterion: TerminationCriterion = store.default_termination_criteria ): super().__init__() self.problem = problem self.termination_criterion = termination_criterion self.observable.register(termination_criterion) self.archive = NonDominatedSolutionsArchive()
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)
class RandomSearch(Algorithm[S, R]): def __init__(self, problem: Problem[S], termination_criterion: TerminationCriterion = store. default_termination_criteria): super().__init__() self.problem = problem self.termination_criterion = termination_criterion self.observable.register(termination_criterion) self.archive = NonDominatedSolutionsArchive() def get_observable_data(self) -> dict: ctime = time.time() - self.start_computing_time return { 'PROBLEM': self.problem, 'EVALUATIONS': self.evaluations, 'SOLUTIONS': self.get_result(), 'COMPUTING_TIME': ctime } def create_initial_solutions(self) -> List[S]: return [self.problem.create_solution()] def evaluate(self, solution_list: List[S]) -> List[S]: return [self.problem.evaluate(solution_list[0])] def init_progress(self) -> None: self.evaluations = 1 observable_data = self.get_observable_data() self.observable.notify_all(**observable_data) def stopping_condition_is_met(self) -> bool: return self.termination_criterion.is_met def step(self) -> None: new_solution = self.problem.create_solution() self.problem.evaluate(new_solution) self.archive.add(new_solution) def update_progress(self) -> None: self.evaluations += 1 observable_data = self.get_observable_data() self.observable.notify_all(**observable_data) def get_result(self) -> List[S]: return self.archive.solution_list def get_name(self) -> str: return 'Random Search' @property def label(self) -> str: return f'{self.get_name()}.{self.problem.get_name()}'
def build_true_front(\ true_front : NonDominatedSolutionsArchive, \ true_front_map : Dict[str, Solution], \ solution_list : List[Solution]) -> Tuple[NonDominatedSolutionsArchive, Dict[str, Solution]]: # make true front for solution in solution_list: true_front.add(solution) true_front_map[str(solution.objectives)] = solution # return them return true_front, true_front_map
def __init__(self, tolerance, max_evaluation): super().__init__() # store the parameters self.max_evaluation = max_evaluation # self.timeout = timeout self.tolerance = tolerance # prepare members self.evaluations = 0 # self.seconds = 0.0 self.counter = 0 self.front = NonDominatedSolutionsArchive() self.last_violation = None self.last_front_size = None
def get_non_dominated_solutions(solutions: List[Solution]) -> List[Solution]: archive: Archive = NonDominatedSolutionsArchive() for solution in solutions: archive.add(solution) return archive.solution_list
def build_each_true_front(self, name: str) -> None: self.__true_front[name] = NonDominatedSolutionsArchive() self.__true_front_map[name] = dict() for ite in range(self.ite_num): solutions = self.result[name][str(ite)]['solutions'] self.__true_front[name], self.__true_front_map[name] = \ self.build_true_front(self.__true_front[name], self.__true_front_map[name], solutions)
def build_all_true_front(self) -> None: for project_name, name_list in self.which_names.items(): self.__true_front[project_name] = NonDominatedSolutionsArchive() self.__true_front_map[project_name] = dict() for name in name_list: for ite in range(self.ite_num): solutions = self.result[name][str(ite)]['solutions'] self.__true_front[project_name], self.__true_front_map[project_name] = \ self.build_true_front(self.__true_front[project_name], self.__true_front_map[project_name], solutions)
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 setUp(self): self.archive = NonDominatedSolutionsArchive()
class NonDominatedSolutionListArchiveTestCases(unittest.TestCase): def setUp(self): self.archive = NonDominatedSolutionsArchive() def test_should_constructor_create_a_non_null_object(self): self.assertIsNotNone(self.archive) def test_should_adding_one_solution_work_properly(self): solution = Solution(1, 1) self.archive.add(solution) self.assertEqual(1, self.archive.size()) self.assertEqual(solution, self.archive.solution_list[0]) def test_should_adding_two_solutions_work_properly_if_one_is_dominated(self): dominated_solution = Solution(1, 2) dominated_solution.objectives = [2.0, 2.0] dominant_solution = Solution(1, 2) dominant_solution.objectives = [1.0, 1.0] self.archive.add(dominated_solution) self.archive.add(dominant_solution) self.assertEqual(1, self.archive.size()) self.assertEqual(dominant_solution, self.archive.solution_list[0]) def test_should_adding_two_solutions_work_properly_if_both_are_non_dominated(self): solution1 = Solution(1, 2) solution1.objectives = [1.0, 0.0] solution2 = Solution(1, 2) solution2.objectives = [0.0, 1.0] self.archive.add(solution1) self.archive.add(solution2) self.assertEqual(2, self.archive.size()) self.assertTrue(solution1 in self.archive.solution_list and solution2 in self.archive.solution_list) def test_should_adding_four_solutions_work_properly_if_one_dominates_the_others(self): solution1 = Solution(1, 2) solution1.objectives = [1.0, 1.0] solution2 = Solution(1, 2) solution2.objectives = [0.0, 2.0] solution3 = Solution(1, 2) solution3.objectives = [0.5, 1.5] solution4 = Solution(1, 2) solution4.objectives = [0.0, 0.0] self.archive.add(solution1) self.archive.add(solution2) self.archive.add(solution3) self.archive.add(solution4) self.assertEqual(1, self.archive.size()) self.assertEqual(solution4, self.archive.solution_list[0]) def test_should_adding_three_solutions_work_properly_if_two_of_them_are_equal(self): solution1 = Solution(1, 2) solution1.objectives = [1.0, 1.0] solution2 = Solution(1, 2) solution2.objectives = [0.0, 2.0] solution3 = Solution(1, 2) solution3.objectives = [1.0, 1.0] self.archive.add(solution1) self.archive.add(solution2) result = self.archive.add(solution3) self.assertEqual(2, self.archive.size()) self.assertFalse(result) self.assertTrue(solution1 in self.archive.solution_list or solution3 in self.archive.solution_list)