def test_should_replacement_return_the_list_if_the_offspring_list_is_empty(self): """ 5 1 4 2 3 3 2 1 4 0 1 2 3 4 5 """ ranking = StrengthRanking() density_estimator = KNearestNeighborDensityEstimator(1) replacement = RankingAndDensityEstimatorReplacement(ranking, density_estimator) solution1 = Solution(2, 2) solution1.objectives = [1, 5] solution2 = Solution(2, 2) solution2.objectives = [2, 4] solution3 = Solution(2, 2) solution3.objectives = [3, 3] solution4 = Solution(2, 2) solution4.objectives = [5, 1] solution_list = [solution1, solution2, solution3, solution4] result_list = replacement.replace(solution_list, []) self.assertEqual(4, len(result_list)) self.assertEqual(0, solution1.attributes["strength_ranking"]) self.assertEqual(0, solution2.attributes["strength_ranking"]) self.assertEqual(0, solution3.attributes["strength_ranking"]) self.assertEqual(0, solution4.attributes["strength_ranking"])
def test_should_replacement_return_the_right_value_case1(self): """ 5 1 4 2 3 3 2 1 4 0 1 2 3 4 5 List: 1,2,3 OffspringList: 4 Expected result: 4, 1, 3 """ ranking = StrengthRanking() density_estimator = KNearestNeighborDensityEstimator(1) replacement = RankingAndDensityEstimatorReplacement(ranking, density_estimator) solution1 = Solution(2, 2) solution1.objectives = [1, 5] solution2 = Solution(2, 2) solution2.objectives = [2, 4] solution3 = Solution(2, 2) solution3.objectives = [3, 3] solution4 = Solution(2, 2) solution4.objectives = [5, 1] solution_list = [solution1, solution2, solution3] offspring_list = [solution4] result_list = replacement.replace(solution_list, offspring_list) self.assertEqual(3, len(result_list)) self.assertTrue(solution1 in result_list) self.assertTrue(solution3 in result_list) self.assertTrue(solution4 in result_list)
def replacement(self, population: List[S], offspring_population: List[S]) -> List[List[S]]: """ This method joins the current and offspring populations to produce the population of the next generation by applying the ranking and crowding distance selection. :param population: Parent population. :param offspring_population: Offspring population. :return: New population after ranking and crowding distance selection is applied. """ ranking = FastNonDominatedRanking(self.dominance_comparator) density_estimator = CrowdingDistance() r = RankingAndDensityEstimatorReplacement(ranking, density_estimator, RemovalPolicyType.ONE_SHOT) solutions = r.replace(population, offspring_population) front = self.get_result() if type(front) is not list: solutions = [front] for solution in front: print(solution.variables[0]) for solution in front: print(str(front.index(solution)) + ": ", sep=' ', end='', flush=True) print(solution.objectives, sep=' ', end='', flush=True) print() return solutions
def replacement(self, population: List[S], offspring_population: List[S]) -> List[List[S]]: ranking = StrengthRanking(self.dominance_comparator) density_estimator = KNearestNeighborDensityEstimator() r = RankingAndDensityEstimatorReplacement(ranking, density_estimator, RemovalPolicyType.SEQUENTIAL) solutions = r.replace(population, offspring_population) front = get_non_dominated_solutions(solutions) objective1 = -1 / self.Uobjecive1 * np.array( [solution.objectives[0] for solution in front]) objective2 = -1 / self.Uobjecive2 * np.array( [solution.objectives[1] for solution in front]) HV = calculateHypervolume(list(zip(objective1, objective2))) print('Hypervolume;', HV) self.hypervolumeByGeneration.append(HV) # DO IGD calculation here IGD = InvertedGenerationalDistance(self.reference_front) igd = IGD.compute( list( zip(-np.array([solution.objectives[0] for solution in front]), -np.array([solution.objectives[1] for solution in front])))) print('IGD1:', igd) # obj1front=1/self.Uobjecive1*self.reference_front[:, 0] # obj2front=1/self.Uobjecive2*self.reference_front[:,1] # igd2 = calculateIGD(list(zip(objective1,objective2)), list(zip(obj1front,obj2front))) # print('IGD2:',igd2) self.IGDbyGeneration.append(igd) return solutions
def replacement(self, population: List[S], offspring_population: List[S]) -> List[List[S]]: ranking = FastNonDominatedRanking(self.dominance_comparator) density_estimator = CrowdingDistance() r = RankingAndDensityEstimatorReplacement(ranking, density_estimator, RemovalPolicyType.ONE_SHOT) solutions = r.replace(population, offspring_population) return solutions
def test_should_replacement_return_the_right_value_case3(self): """""" points_population = [ [0.13436424411240122, 4.323216008886963], [0.23308445025757263, 4.574937990387161], [0.17300740157905092, 4.82329350808847], [0.9571162814602269, 3.443495331489301], [0.25529404008730594, 3.36387501100745], [0.020818108509287336, 5.1051826661880515], [0.8787178982088466, 3.2716009445324103], [0.6744550697237632, 3.901350307095427], [0.7881164487252263, 3.1796004913916516], [0.1028341459863098, 4.9409270526888935], ] points_offspring_population = [ [0.3150521745650882, 4.369120371847888], [0.8967291504209932, 2.506948771242972], [0.6744550697237632, 3.9361442668874504], [0.9571162814602269, 3.4388386707431433], [0.13436424411240122, 4.741872175943253], [0.25529404008730594, 2.922302861104415], [0.23308445025757263, 4.580180404770213], [0.23308445025757263, 4.591260299892424], [0.9571162814602269, 2.9865495383518694], [0.25529404008730594, 3.875587748122183], ] ranking = FastNonDominatedRanking() density_estimator = KNearestNeighborDensityEstimator(1) population = [] for i in range(len(points_population)): population.append(Solution(2, 2)) population[i].objectives = points_population[i] offspring_population = [] for i in range(len(points_offspring_population)): offspring_population.append(Solution(2, 2)) offspring_population[i].objectives = points_offspring_population[i] replacement = RankingAndDensityEstimatorReplacement(ranking, density_estimator) result_list = replacement.replace(population, offspring_population) self.assertEqual(10, len(result_list)) for solution in result_list[0:4]: self.assertEqual(0, solution.attributes["dominance_ranking"]) for solution in result_list[5:9]: self.assertEqual(1, solution.attributes["dominance_ranking"])
def replacement(self, population: List[S], offspring_population: List[S]) -> List[List[S]]: """This method joins the current and offspring populations to produce the population of the next generation by applying the ranking and crowding distance selection. :param population: Parent population. :param offspring_population: Offspring population. :return: New population after ranking and crowding distance selection is applied. """ ranking = StrengthRanking(self.dominance_comparator) density_estimator = KNearestNeighborDensityEstimator() r = RankingAndDensityEstimatorReplacement(ranking, density_estimator, RemovalPolicyType.SEQUENTIAL) solutions = r.replace(population, offspring_population) return solutions
def replacement(self, population: List[S], offspring_population: List[S]) -> List[List[S]]: """ This method joins the current and offspring populations to produce the population of the next generation by applying the ranking and crowding distance selection. :param population: Parent population. :param offspring_population: Offspring population. :return: New population after ranking and crowding distance selection is applied. """ ranking = FastNonDominatedRanking() density_estimator = CrowdingDistance() r = RankingAndDensityEstimatorReplacement(ranking, density_estimator, RemovalPolicyType.ONE_SHOT) solutions = r.replace(population, offspring_population) return solutions
def test_should_replacement_return_the_right_value_case2(self): """ 5 1 4 2 3 3 2 5 1 4 0 1 2 3 4 5 List: 1,2,4 OffspringList: 3,5 Expected result: 1, 5, 4 """ ranking = StrengthRanking() density_estimator = KNearestNeighborDensityEstimator(1) replacement = RankingAndDensityEstimatorReplacement(ranking, density_estimator) solution1 = Solution(2, 2) solution1.objectives = [1, 5] solution2 = Solution(2, 2) solution2.objectives = [2, 4] solution3 = Solution(2, 2) solution3.objectives = [3, 3] solution4 = Solution(2, 2) solution4.objectives = [5, 1] solution5 = Solution(2, 2) solution5.objectives = [2.5, 2.5] solution_list = [solution1, solution2, solution4] offspring_list = [solution3, solution5] result_list = replacement.replace(solution_list, offspring_list) self.assertEqual(0, solution1.attributes["strength_ranking"]) self.assertEqual(0, solution2.attributes["strength_ranking"]) self.assertEqual(1, solution3.attributes["strength_ranking"]) self.assertEqual(0, solution4.attributes["strength_ranking"]) self.assertEqual(0, solution5.attributes["strength_ranking"]) self.assertEqual(3, len(result_list)) self.assertTrue(solution1 in result_list) self.assertTrue(solution5 in result_list) self.assertTrue(solution4 in result_list)
def replacement(self, population: List[S], offspring_population: List[S]) -> List[List[S]]: """ This method joins the current and offspring populations to produce the population of the next generation by applying the ranking and crowding distance selection. :param population: Parent population. :param offspring_population: Offspring population. :return: New population after ranking and crowding distance selection is applied. """ ranking = FastNonDominatedRanking(self.dominance_comparator) density_estimator = CrowdingDistance() # gradient steps # append new solutions to the offspring grad_sols = self.problem.step_discrepancy(population) grad_sols = self.evaluate(grad_sols) offspring_population.extend(grad_sols) r = RankingAndDensityEstimatorReplacement(ranking, density_estimator, RemovalPolicyType.ONE_SHOT) solutions = r.replace(population, offspring_population) return solutions
class DECMO_INTEG(Algorithm[S, R]): def __init__( self, problem: Problem, dominance_comparator: Comparator = store.default_comparator, max_iterations: int = 250, individual_population_size: int = 100, report_interval: int = 100, ): super().__init__() self.problem = problem self.population_size = individual_population_size self.max_iterations = max_iterations self.report_interval = report_interval self.mix_interval = self.population_size / 10 """Replacement""" ranking = FastNonDominatedRanking(dominance_comparator) density_estimator = CrowdingDistance() self.r = RankingAndDensityEstimatorReplacement( ranking, density_estimator, RemovalPolicyType.SEQUENTIAL) 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 get_result(self) -> R: return self.solutions def get_name(self) -> str: return "DECMO" def create_initial_solutions(self) -> List[S]: pass def evaluate(self, IntegerSolutions: List[S]) -> List[S]: pass def stopping_condition_is_met(self) -> bool: pass def get_observable_data(self) -> dict: pass def init_progress(self) -> None: pass def step(self) -> None: pass def update_progress(self): pass
def run(self): """ Execute the algorithm. """ self.start_computing_time = time.time() create_solution = dask.delayed(self.problem.create_solution) evaluate_solution = dask.delayed(self.problem.evaluate) task_pool = as_completed([], with_results=True) for _ in range(self.number_of_cores): new_solution = create_solution() new_evaluated_solution = evaluate_solution(new_solution) future = self.client.compute(new_evaluated_solution) task_pool.add(future) batches = task_pool.batches() auxiliar_population = [] while len(auxiliar_population) < self.population_size: batch = next(batches) for _, received_solution in batch: auxiliar_population.append(received_solution) if len(auxiliar_population) < self.population_size: break # submit as many new tasks as we collected for _ in batch: new_solution = create_solution() new_evaluated_solution = evaluate_solution(new_solution) future = self.client.compute(new_evaluated_solution) task_pool.add(future) self.init_progress() # perform an algorithm step to create a new solution to be evaluated while not self.stopping_condition_is_met(): batch = next(batches) for _, received_solution in batch: offspring_population = [received_solution] # replacement ranking = FastNonDominatedRanking(self.dominance_comparator) density_estimator = CrowdingDistance() r = RankingAndDensityEstimatorReplacement( ranking, density_estimator, RemovalPolicyType.ONE_SHOT) auxiliar_population = r.replace(auxiliar_population, offspring_population) # selection mating_population = [] for _ in range(2): solution = self.selection_operator.execute( auxiliar_population) mating_population.append(solution) # Reproduction and evaluation new_task = self.client.submit(reproduction, mating_population, self.problem, self.crossover_operator, self.mutation_operator) task_pool.add(new_task) # update progress self.evaluations += 1 self.solutions = auxiliar_population self.update_progress() if self.stopping_condition_is_met(): break self.total_computing_time = time.time() - self.start_computing_time # at this point, computation is done for future, _ in task_pool: future.cancel()
class DECMO2(Algorithm[S, R]): def __init__( self, problem: Problem, dominance_comparator: Comparator = store.default_comparator, max_evaluations: int = 250, individual_population_size: int = 100, report_interval: int = 100, dataDirectory: str = "./decmopy/decmo2/weigths", ): super().__init__() self.problem = problem self.population_size = individual_population_size self.max_evaluations = max_evaluations self.report_interval = report_interval self.dataDirectory = dataDirectory self.mix_interval = 1 """Replacement""" ranking = FastNonDominatedRanking(dominance_comparator) density_estimator = CrowdingDistance() self.r = RankingAndDensityEstimatorReplacement( ranking, density_estimator, RemovalPolicyType.SEQUENTIAL) self.MIN_VALUES = 0 self.MAX_VALUES = 1 min_values: List[float] = [] max_values: List[float] = [] for _ in range(problem.number_of_objectives): min_values.append(sys.float_info.max) max_values.append(sys.float_info.min) self.extreme_values: List[List[float]] = [] self.extreme_values.append(min_values) self.extreme_values.append(max_values) 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 __compute_euclidean_distance(self, vector1: List[float], vector2: List[float]): value = 0.0 for i in range(len(vector1)): value += (vector1[i] - vector2[i]) * (vector1[i] - vector2[i]) return math.sqrt(value) def __create_uniform_weights(self, dirArchiveSize: int, nrOfObjectives: int): lmdb = np.zeros(shape=(dirArchiveSize, nrOfObjectives)) if nrOfObjectives == 2 and dirArchiveSize < 500: for n in range(dirArchiveSize): a = 1.0 * n / (dirArchiveSize - 1) lmdb[n][0] = a lmdb[n][1] = 1 - a print(lmdb[n][0]) print(lmdb[n][1]) else: dataFileName = ("W" + str(nrOfObjectives) + "D_" + str(dirArchiveSize) + ".dat") data_path = self.dataDirectory + "/" + dataFileName print(dataFileName) print(data_path) dg = DistribGen() dg.create_distribution(self.problem.number_of_objectives, dirArchiveSize, data_path) try: i = j = 0 with open(data_path) as f: # lines = f.readlines() lines = [line.rstrip() for line in f] for line in lines: words = line.split() # "tokenizer" j = 0 for word in words: value = float(word.replace(",", ".")) lmdb[i][j] = value j += 1 i += 1 except Exception as e: print(e) print("initUniformWeight: failed when reading for file: " + data_path) return lmdb def __create_directional_archive(self, lmbd: List[float]): directionalArchive: List[DirectionRec] = [] for i in range(len(lmbd)): di = DirectionRec(i, lmbd[i], None, sys.float_info.max, 0) directionalArchive.append(di) return directionalArchive def __compute_neighbourhood_Nfe_since_last_update( self, neighbourhoods: List[List[int]], directionalArchive: List[DirectionRec], intensificationClusters: int, ): averageNfe: List[CompRec] = [] ID = 0 for neighbourhood in neighbourhoods: avg = 0.0 for nID in neighbourhood: avg += directionalArchive[nID].nfeSinceLastUpdate avg /= len(neighbourhood) averageNfe.append(CompRec(ID, avg)) ID += 1 averageNfe.sort() result: List[int] = [] for i in range(intensificationClusters): result.append(averageNfe[len(averageNfe) - 1 - i].id) return result def __create_neighbourhoods(self, dirArchive: List[DirectionRec], neighborhood_size: int): neighbourhoods: List[List[int]] = [] for di1 in dirArchive: distToNeighbour: List[CompRec] = [] for di2 in dirArchive: if di1.id != di2.id: distToNeighbour.append( CompRec( di2.id, self.__compute_euclidean_distance( di1.weigh_vector, di2.weigh_vector), )) distToNeighbour.sort() neighbourhood: List[int] = [] for i in range(neighborhood_size): if i < len(distToNeighbour): neighbourhood.append(distToNeighbour[i].id) neighbourhoods.append(neighbourhood) return neighbourhoods def __update_neighbourhoods( self, directionalArchive: List[DirectionRec], newSolution: FloatSolution, nrOfReplacements: int, ): improvedDistances: List[CompRec] = [] isImprovement = False for cdr in directionalArchive: newFitnessValue = self.__evaluate_Tchebycheff_Fitness( newSolution, cdr.weigh_vector) if newFitnessValue < cdr.fitness_value: improvedDistances.append(CompRec(cdr.id, newFitnessValue)) isImprovement = True else: cdr.nfeSinceLastUpdate = cdr.nfeSinceLastUpdate + 1 improvedDistances.sort() improvedDistances.reverse() if isImprovement: for _ in range(nrOfReplacements): j = 0 cdr = directionalArchive[improvedDistances[j].id] cdr.curr_sol = newSolution cdr.fitness_value = improvedDistances[j].value cdr.nfeSinceLastUpdate = 0 return 1 return 0 def __evaluate_Tchebycheff_Fitness(self, individual: FloatSolution, lmbd: List[float]): max = sys.float_info.min for i in range(self.problem.number_of_objectives): diff = abs(individual.objectives[i] - self.extreme_values[self.MIN_VALUES][i]) tcheFuncVal: float = None if lmbd[i] == 0: tcheFuncVal = 0.000001 * diff else: tcheFuncVal = diff * lmbd[i] if tcheFuncVal > max: max = tcheFuncVal return max def __update_extreme_values(self, sol: FloatSolution): for i in range(self.problem.number_of_objectives): objValue = sol.objectives[i] if objValue < self.extreme_values[self.MIN_VALUES][i]: self.extreme_values[self.MIN_VALUES][i] = objValue if objValue > self.extreme_values[self.MAX_VALUES][i]: self.extreme_values[self.MAX_VALUES][i] = objValue def __clear_Nfe_history(self, directionalArchive: List[DirectionRec]): for dr in directionalArchive: dr.nfeSinceLastUpdate = 0 def get_result(self) -> R: return self.solutions def get_name(self) -> str: return "DECMO" def create_initial_solutions(self) -> List[S]: pass def evaluate(self, solutions: List[S]) -> List[S]: pass def stopping_condition_is_met(self) -> bool: pass def get_observable_data(self) -> dict: pass def init_progress(self) -> None: pass def step(self) -> None: pass def update_progress(self): pass