eckity.multi_objective_evolution.nsga2_front_sorting

  1from collections import defaultdict
  2from typing import List
  3
  4from eckity.individual import Individual
  5from eckity.population import Population
  6
  7
  8class NSGA2FrontSorting():
  9	'''
 10    This class is incharge of setitng the value of selecting only the best individuals
 11    out of the population
 12    (mening that the are dominated by as littel amount of other Individuals as posible)
 13
 14    this class allso set the values of the "front_rank" and "crowding" of each individual
 15    '''
 16
 17	def select_for_population(self, population: Population, new_pop_size=None):
 18		for sub_population in population.sub_populations:
 19			dest_inds = []
 20			dest_inds = self._select(sub_population.individuals, dest_inds, new_pop_size)
 21			sub_population.individuals = dest_inds
 22
 23	def _select(self, source_inds: List[Individual], dest_inds: List[Individual], pop_size: int):
 24		'''
 25
 26        Parameters
 27        ----------
 28        source_inds : list of individuals (sub_population.individuals)
 29        dest_inds: the pareto front
 30        pop_size :  the size we destend the pareto front to be
 31
 32        Returns :  the pareto front
 33        -------
 34
 35        '''
 36		if not pop_size:
 37			pop_size = len(source_inds) // 2
 38
 39		front_rank = 1
 40		self._init_domination_dict(source_inds)
 41		while len(dest_inds) < pop_size:
 42			new_pareto_front = self._pareto_front_finding(source_inds)
 43			self._calc_fronts_crowding(new_pareto_front)
 44			self._update_new_pareto_front_rank(new_pareto_front, front_rank)
 45
 46			total_pareto_size = len(new_pareto_front) + len(dest_inds)
 47			if total_pareto_size > pop_size:
 48				number_solutions_needed = pop_size - len(dest_inds)
 49				new_pareto_front.sort(key=lambda x: x.fitness.crowding, reverse=True)
 50				new_pareto_front = new_pareto_front[
 51								   :int(number_solutions_needed)]  # take the individuals with the largest crowding
 52			dest_inds += new_pareto_front
 53			source_inds = self._remove_pareto_front(source_inds, new_pareto_front)
 54			front_rank += 1
 55		return dest_inds
 56
 57	def _remove_pareto_front(self, source_inds, pareto_front):
 58		for dominating_ind in pareto_front:
 59			for dominated_ind in self.domination_dict[dominating_ind].dominates:
 60				self.domination_dict[dominated_ind].domination_counter -= 1
 61		return list(set(source_inds) - set(pareto_front))
 62
 63	def _update_new_pareto_front_rank(self, new_pareto_front: List[Individual], front_rank: int):
 64		for ind in new_pareto_front:
 65			ind.fitness.front_rank = front_rank
 66
 67	def _calc_fronts_crowding(self, front: List[Individual]):
 68		for ind in front:
 69			ind.fitness.crowding = 0
 70
 71		objectiv_indexes = range(len(front[0].get_pure_fitness()))
 72		for objective_index in objectiv_indexes:
 73			front.sort(key=lambda x: x.get_pure_fitness()[objective_index])  # sort for each objectiv
 74			front[0].fitness.crowding = float("inf")
 75			front[-1].fitness.crowding = float("inf")
 76			for i in range(1, len(front) - 1):
 77				curr_crowding = front[i + 1].get_pure_fitness()[objective_index] - front[i - 1].get_pure_fitness()[
 78					objective_index]
 79				curr_crowding /= (front[-1].get_pure_fitness()[objective_index] - front[0].get_pure_fitness()[
 80					objective_index])
 81				front[i].fitness.crowding += curr_crowding
 82
 83	def _init_domination_dict(self, source_inds: List[Individual]):
 84		self.domination_dict = defaultdict(lambda: DominationCounter())
 85		for i, ind1 in enumerate(source_inds):
 86			for ind2 in source_inds[i + 1:]:
 87				self._habdle_domination(ind1, ind2)
 88
 89	def _habdle_domination(self, ind1, ind2):
 90		if ind2.fitness.dominate(ind2, ind1.fitness, ind1):
 91			self._increase_domination_counter(ind2, ind1)
 92		elif ind1.fitness.dominate(ind1, ind2.fitness, ind2):
 93			self._increase_domination_counter(ind1, ind2)
 94
 95	def _increase_domination_counter(self, dominating, dominated):
 96		self.domination_dict[dominating].dominates.append(dominated)
 97		self.domination_dict[dominated].domination_counter += 1
 98
 99	def _pareto_front_finding(self, source_inds: List[Individual]):
100		pareto_front = [ind for ind in source_inds if self.domination_dict[ind].domination_counter == 0]
101		return pareto_front
102
103
104class DominationCounter:
105	def __init__(self):
106		'''
107        self.dominates : a list of all the individuals this individual dominates
108        self.domination_counter : a counter of how many other individuals dominates this one
109        '''
110		self.dominates = []
111		self.domination_counter = 0
class NSGA2FrontSorting:
  9class NSGA2FrontSorting():
 10	'''
 11    This class is incharge of setitng the value of selecting only the best individuals
 12    out of the population
 13    (mening that the are dominated by as littel amount of other Individuals as posible)
 14
 15    this class allso set the values of the "front_rank" and "crowding" of each individual
 16    '''
 17
 18	def select_for_population(self, population: Population, new_pop_size=None):
 19		for sub_population in population.sub_populations:
 20			dest_inds = []
 21			dest_inds = self._select(sub_population.individuals, dest_inds, new_pop_size)
 22			sub_population.individuals = dest_inds
 23
 24	def _select(self, source_inds: List[Individual], dest_inds: List[Individual], pop_size: int):
 25		'''
 26
 27        Parameters
 28        ----------
 29        source_inds : list of individuals (sub_population.individuals)
 30        dest_inds: the pareto front
 31        pop_size :  the size we destend the pareto front to be
 32
 33        Returns :  the pareto front
 34        -------
 35
 36        '''
 37		if not pop_size:
 38			pop_size = len(source_inds) // 2
 39
 40		front_rank = 1
 41		self._init_domination_dict(source_inds)
 42		while len(dest_inds) < pop_size:
 43			new_pareto_front = self._pareto_front_finding(source_inds)
 44			self._calc_fronts_crowding(new_pareto_front)
 45			self._update_new_pareto_front_rank(new_pareto_front, front_rank)
 46
 47			total_pareto_size = len(new_pareto_front) + len(dest_inds)
 48			if total_pareto_size > pop_size:
 49				number_solutions_needed = pop_size - len(dest_inds)
 50				new_pareto_front.sort(key=lambda x: x.fitness.crowding, reverse=True)
 51				new_pareto_front = new_pareto_front[
 52								   :int(number_solutions_needed)]  # take the individuals with the largest crowding
 53			dest_inds += new_pareto_front
 54			source_inds = self._remove_pareto_front(source_inds, new_pareto_front)
 55			front_rank += 1
 56		return dest_inds
 57
 58	def _remove_pareto_front(self, source_inds, pareto_front):
 59		for dominating_ind in pareto_front:
 60			for dominated_ind in self.domination_dict[dominating_ind].dominates:
 61				self.domination_dict[dominated_ind].domination_counter -= 1
 62		return list(set(source_inds) - set(pareto_front))
 63
 64	def _update_new_pareto_front_rank(self, new_pareto_front: List[Individual], front_rank: int):
 65		for ind in new_pareto_front:
 66			ind.fitness.front_rank = front_rank
 67
 68	def _calc_fronts_crowding(self, front: List[Individual]):
 69		for ind in front:
 70			ind.fitness.crowding = 0
 71
 72		objectiv_indexes = range(len(front[0].get_pure_fitness()))
 73		for objective_index in objectiv_indexes:
 74			front.sort(key=lambda x: x.get_pure_fitness()[objective_index])  # sort for each objectiv
 75			front[0].fitness.crowding = float("inf")
 76			front[-1].fitness.crowding = float("inf")
 77			for i in range(1, len(front) - 1):
 78				curr_crowding = front[i + 1].get_pure_fitness()[objective_index] - front[i - 1].get_pure_fitness()[
 79					objective_index]
 80				curr_crowding /= (front[-1].get_pure_fitness()[objective_index] - front[0].get_pure_fitness()[
 81					objective_index])
 82				front[i].fitness.crowding += curr_crowding
 83
 84	def _init_domination_dict(self, source_inds: List[Individual]):
 85		self.domination_dict = defaultdict(lambda: DominationCounter())
 86		for i, ind1 in enumerate(source_inds):
 87			for ind2 in source_inds[i + 1:]:
 88				self._habdle_domination(ind1, ind2)
 89
 90	def _habdle_domination(self, ind1, ind2):
 91		if ind2.fitness.dominate(ind2, ind1.fitness, ind1):
 92			self._increase_domination_counter(ind2, ind1)
 93		elif ind1.fitness.dominate(ind1, ind2.fitness, ind2):
 94			self._increase_domination_counter(ind1, ind2)
 95
 96	def _increase_domination_counter(self, dominating, dominated):
 97		self.domination_dict[dominating].dominates.append(dominated)
 98		self.domination_dict[dominated].domination_counter += 1
 99
100	def _pareto_front_finding(self, source_inds: List[Individual]):
101		pareto_front = [ind for ind in source_inds if self.domination_dict[ind].domination_counter == 0]
102		return pareto_front

This class is incharge of setitng the value of selecting only the best individuals out of the population (mening that the are dominated by as littel amount of other Individuals as posible)

this class allso set the values of the "front_rank" and "crowding" of each individual

def select_for_population(self, population: eckity.population.Population, new_pop_size=None):
18	def select_for_population(self, population: Population, new_pop_size=None):
19		for sub_population in population.sub_populations:
20			dest_inds = []
21			dest_inds = self._select(sub_population.individuals, dest_inds, new_pop_size)
22			sub_population.individuals = dest_inds
class DominationCounter:
105class DominationCounter:
106	def __init__(self):
107		'''
108        self.dominates : a list of all the individuals this individual dominates
109        self.domination_counter : a counter of how many other individuals dominates this one
110        '''
111		self.dominates = []
112		self.domination_counter = 0
DominationCounter()
106	def __init__(self):
107		'''
108        self.dominates : a list of all the individuals this individual dominates
109        self.domination_counter : a counter of how many other individuals dominates this one
110        '''
111		self.dominates = []
112		self.domination_counter = 0

self.dominates : a list of all the individuals this individual dominates self.domination_counter : a counter of how many other individuals dominates this one

dominates
domination_counter