eckity.multi_objective_evolution.nsga2_fitness

  1from typing import List
  2
  3from overrides import overrides
  4
  5from eckity.fitness.fitness import Fitness
  6from eckity.individual import Individual
  7import random as rd
  8
  9
 10class NSGA2Fitness(Fitness):
 11	def __init__(self,
 12				 fitness: List[float] = None,
 13				 higher_is_better=False):
 14		is_evaluated = fitness is not None
 15		super().__init__(higher_is_better=higher_is_better, is_evaluated=is_evaluated)
 16		self.fitness: List[float] = fitness  # list of objectivs
 17		self.crowding = 0
 18		self.front_rank = float("inf")
 19		if self.fitness!=None and type(self.higher_is_better) is bool:
 20			self.higher_is_better = [self.higher_is_better] * len(fitness)
 21
 22
 23
 24	def set_fitness(self, fitness):
 25		if self._is_evaluated:
 26			raise AttributeError('fitness already evaluated and set to', self.fitness)
 27		self.fitness = fitness
 28		self._is_evaluated = True
 29		if type(self.higher_is_better) is bool:
 30			self.higher_is_better = [self.higher_is_better] * len(fitness)
 31
 32	@overrides
 33	def get_pure_fitness(self):
 34		if not self._is_evaluated:
 35			raise ValueError('Fitness not evaluated yet')
 36		return self.fitness
 37
 38	@overrides
 39	def set_not_evaluated(self):
 40		self._is_evaluated = False
 41		self.fitness = None
 42		self.crowding = 0
 43		self.front_rank = float("inf")
 44
 45	def check_comparable_fitnesses(self, other_fitness: Fitness, ind: Individual, other_ind: Individual):
 46		if not isinstance(other_fitness, NSGA2Fitness):
 47			raise TypeError('Expected NSGA2Fitness object in better_than, got', type(other_fitness))
 48		if not self.is_fitness_evaluated() or not other_fitness.is_fitness_evaluated():
 49			raise ValueError('Fitnesses must be evaluated before comparison')
 50		if len(other_fitness.get_augmented_fitness(other_ind)) != len(self.get_augmented_fitness(ind)):
 51			raise ValueError('Fitnesses must be of the same lngth')
 52
 53	def better_than(self, ind, other_fitness, other_ind):
 54		'''
 55
 56		Parameters
 57		----------
 58		ind:Individual
 59		other_fitness:NSGA2Fitness
 60		other_ind:Individual
 61
 62		Returns : True ind has lower rank or equal rank and bigger crwoding value
 63		-------
 64
 65		'''
 66		if self.front_rank == float("inf"):  # first iteration
 67			return bool(rd.getrandbits(1))  # random true false
 68		else:
 69			self.check_comparable_fitnesses(other_fitness, ind, other_ind)
 70			if self.front_rank == other_ind.fitness.front_rank:
 71				return self.crowding > other_ind.fitness.crowding
 72			return self.front_rank > other_ind.fitness.front_rank
 73
 74	def equal_to(self, ind, other_fitness, other_ind):
 75		return self.front_rank == other_ind.fitness.front_rank and \
 76			   self.crowding == other_ind.fitness.crowding
 77
 78	def dominate(self, ind, other_fitness, other_ind):
 79		self.check_comparable_fitnesses(other_fitness, ind, other_ind)
 80		self_fit = self.get_augmented_fitness(ind)
 81		other_fit = other_fitness.get_augmented_fitness(other_ind)
 82		return all([self._o1_at_least_o2(o1, o2, h_is_b) for h_is_b, o1, o2 in
 83					zip(self.higher_is_better, self_fit, other_fit)]) and \
 84			   any([self._o1_better_then_o2(o1, o2, h_is_b) for h_is_b, o1, o2 in
 85					zip(self.higher_is_better, self_fit, other_fit)])
 86
 87	def _o1_at_least_o2(self, o1, o2, higher_is_better):
 88		'''
 89
 90		Parameters
 91		----------
 92		o1: objective i of individual 1
 93		o2: objective i of individual 2
 94		higher_is_better :boolean - is higher better for objective i of he fitness ?
 95
 96		Returns :x1 >= x2 or x1 <= x2 according to higher is better
 97		-------
 98
 99		'''
100		if higher_is_better:
101			return o1 >= o2
102		else:
103			return o1 <= o2
104
105	def _o1_better_then_o2(self, o1, o2, higher_is_better):
106		'''
107
108		Parameters
109		----------
110		o1: objective i of individual 1
111		o2: objective i of individual 2
112		higher_is_better :boolean - is higher better for objective i of he fitness ?
113
114		Returns :x1 > x2 or x1 < x2 according to higher is better
115		-------
116
117		'''
118		if higher_is_better:
119			return o1 > o2
120		else:
121			return o1 < o2
122
123	# def equal_to(self, ind, other_fitness, other_ind):
124	#     self.check_comparable_fitnesses(other_fitness,ind,other_ind)
125	#     self_fit = self.get_augmented_fitness(ind)
126	#     other_fit = other_fitness.get_augmented_fitness(other_ind)
127	#     all([x1 == x2 for x1, x2 in zip(self_fit, other_fit)])
128
129	def __getstate__(self):
130		state = self.__dict__.copy()
131		if not self.should_cache_between_gens:
132			state['_is_evaluated'] = False
133			state['fitness'] = None
134		return state
class NSGA2Fitness(eckity.fitness.fitness.Fitness):
 11class NSGA2Fitness(Fitness):
 12	def __init__(self,
 13				 fitness: List[float] = None,
 14				 higher_is_better=False):
 15		is_evaluated = fitness is not None
 16		super().__init__(higher_is_better=higher_is_better, is_evaluated=is_evaluated)
 17		self.fitness: List[float] = fitness  # list of objectivs
 18		self.crowding = 0
 19		self.front_rank = float("inf")
 20		if self.fitness!=None and type(self.higher_is_better) is bool:
 21			self.higher_is_better = [self.higher_is_better] * len(fitness)
 22
 23
 24
 25	def set_fitness(self, fitness):
 26		if self._is_evaluated:
 27			raise AttributeError('fitness already evaluated and set to', self.fitness)
 28		self.fitness = fitness
 29		self._is_evaluated = True
 30		if type(self.higher_is_better) is bool:
 31			self.higher_is_better = [self.higher_is_better] * len(fitness)
 32
 33	@overrides
 34	def get_pure_fitness(self):
 35		if not self._is_evaluated:
 36			raise ValueError('Fitness not evaluated yet')
 37		return self.fitness
 38
 39	@overrides
 40	def set_not_evaluated(self):
 41		self._is_evaluated = False
 42		self.fitness = None
 43		self.crowding = 0
 44		self.front_rank = float("inf")
 45
 46	def check_comparable_fitnesses(self, other_fitness: Fitness, ind: Individual, other_ind: Individual):
 47		if not isinstance(other_fitness, NSGA2Fitness):
 48			raise TypeError('Expected NSGA2Fitness object in better_than, got', type(other_fitness))
 49		if not self.is_fitness_evaluated() or not other_fitness.is_fitness_evaluated():
 50			raise ValueError('Fitnesses must be evaluated before comparison')
 51		if len(other_fitness.get_augmented_fitness(other_ind)) != len(self.get_augmented_fitness(ind)):
 52			raise ValueError('Fitnesses must be of the same lngth')
 53
 54	def better_than(self, ind, other_fitness, other_ind):
 55		'''
 56
 57		Parameters
 58		----------
 59		ind:Individual
 60		other_fitness:NSGA2Fitness
 61		other_ind:Individual
 62
 63		Returns : True ind has lower rank or equal rank and bigger crwoding value
 64		-------
 65
 66		'''
 67		if self.front_rank == float("inf"):  # first iteration
 68			return bool(rd.getrandbits(1))  # random true false
 69		else:
 70			self.check_comparable_fitnesses(other_fitness, ind, other_ind)
 71			if self.front_rank == other_ind.fitness.front_rank:
 72				return self.crowding > other_ind.fitness.crowding
 73			return self.front_rank > other_ind.fitness.front_rank
 74
 75	def equal_to(self, ind, other_fitness, other_ind):
 76		return self.front_rank == other_ind.fitness.front_rank and \
 77			   self.crowding == other_ind.fitness.crowding
 78
 79	def dominate(self, ind, other_fitness, other_ind):
 80		self.check_comparable_fitnesses(other_fitness, ind, other_ind)
 81		self_fit = self.get_augmented_fitness(ind)
 82		other_fit = other_fitness.get_augmented_fitness(other_ind)
 83		return all([self._o1_at_least_o2(o1, o2, h_is_b) for h_is_b, o1, o2 in
 84					zip(self.higher_is_better, self_fit, other_fit)]) and \
 85			   any([self._o1_better_then_o2(o1, o2, h_is_b) for h_is_b, o1, o2 in
 86					zip(self.higher_is_better, self_fit, other_fit)])
 87
 88	def _o1_at_least_o2(self, o1, o2, higher_is_better):
 89		'''
 90
 91		Parameters
 92		----------
 93		o1: objective i of individual 1
 94		o2: objective i of individual 2
 95		higher_is_better :boolean - is higher better for objective i of he fitness ?
 96
 97		Returns :x1 >= x2 or x1 <= x2 according to higher is better
 98		-------
 99
100		'''
101		if higher_is_better:
102			return o1 >= o2
103		else:
104			return o1 <= o2
105
106	def _o1_better_then_o2(self, o1, o2, higher_is_better):
107		'''
108
109		Parameters
110		----------
111		o1: objective i of individual 1
112		o2: objective i of individual 2
113		higher_is_better :boolean - is higher better for objective i of he fitness ?
114
115		Returns :x1 > x2 or x1 < x2 according to higher is better
116		-------
117
118		'''
119		if higher_is_better:
120			return o1 > o2
121		else:
122			return o1 < o2
123
124	# def equal_to(self, ind, other_fitness, other_ind):
125	#     self.check_comparable_fitnesses(other_fitness,ind,other_ind)
126	#     self_fit = self.get_augmented_fitness(ind)
127	#     other_fit = other_fitness.get_augmented_fitness(other_ind)
128	#     all([x1 == x2 for x1, x2 in zip(self_fit, other_fit)])
129
130	def __getstate__(self):
131		state = self.__dict__.copy()
132		if not self.should_cache_between_gens:
133			state['_is_evaluated'] = False
134			state['fitness'] = None
135		return state

This class is responsible for handling the fitness score of some Individual (checking if fitness is evaluated, comparing fitness scores with other individuals etc.)

context: list of Individuals individuals involved in calculating the fitness (co-evolution)

trials: list of floats fitness results for previous trials done to calculate fitness (co-evolution)

_is_evaluated: bool declares if fitness score is evaluated and updated in the current generation

is_relative_fitness: bool declares whether the fitness score is absolute or relative

should_cache_between_gens: bool declares whether the fitness score should reset at the end of each generation

higher_is_better: bool declares the fitness direction. i.e., if it should be minimized or maximized

NSGA2Fitness(fitness: List[float] = None, higher_is_better=False)
12	def __init__(self,
13				 fitness: List[float] = None,
14				 higher_is_better=False):
15		is_evaluated = fitness is not None
16		super().__init__(higher_is_better=higher_is_better, is_evaluated=is_evaluated)
17		self.fitness: List[float] = fitness  # list of objectivs
18		self.crowding = 0
19		self.front_rank = float("inf")
20		if self.fitness!=None and type(self.higher_is_better) is bool:
21			self.higher_is_better = [self.higher_is_better] * len(fitness)
fitness: List[float]
crowding
front_rank
def set_fitness(self, fitness):
25	def set_fitness(self, fitness):
26		if self._is_evaluated:
27			raise AttributeError('fitness already evaluated and set to', self.fitness)
28		self.fitness = fitness
29		self._is_evaluated = True
30		if type(self.higher_is_better) is bool:
31			self.higher_is_better = [self.higher_is_better] * len(fitness)
@overrides
def get_pure_fitness(self):
33	@overrides
34	def get_pure_fitness(self):
35		if not self._is_evaluated:
36			raise ValueError('Fitness not evaluated yet')
37		return self.fitness

Returns the pure fitness score of the individual (before applying balancing methods like bloat control)

@overrides
def set_not_evaluated(self):
39	@overrides
40	def set_not_evaluated(self):
41		self._is_evaluated = False
42		self.fitness = None
43		self.crowding = 0
44		self.front_rank = float("inf")

Set this fitness score status to be not evaluated

def check_comparable_fitnesses( self, other_fitness: eckity.fitness.fitness.Fitness, ind: eckity.individual.Individual, other_ind: eckity.individual.Individual):
46	def check_comparable_fitnesses(self, other_fitness: Fitness, ind: Individual, other_ind: Individual):
47		if not isinstance(other_fitness, NSGA2Fitness):
48			raise TypeError('Expected NSGA2Fitness object in better_than, got', type(other_fitness))
49		if not self.is_fitness_evaluated() or not other_fitness.is_fitness_evaluated():
50			raise ValueError('Fitnesses must be evaluated before comparison')
51		if len(other_fitness.get_augmented_fitness(other_ind)) != len(self.get_augmented_fitness(ind)):
52			raise ValueError('Fitnesses must be of the same lngth')
def better_than(self, ind, other_fitness, other_ind):
54	def better_than(self, ind, other_fitness, other_ind):
55		'''
56
57		Parameters
58		----------
59		ind:Individual
60		other_fitness:NSGA2Fitness
61		other_ind:Individual
62
63		Returns : True ind has lower rank or equal rank and bigger crwoding value
64		-------
65
66		'''
67		if self.front_rank == float("inf"):  # first iteration
68			return bool(rd.getrandbits(1))  # random true false
69		else:
70			self.check_comparable_fitnesses(other_fitness, ind, other_ind)
71			if self.front_rank == other_ind.fitness.front_rank:
72				return self.crowding > other_ind.fitness.crowding
73			return self.front_rank > other_ind.fitness.front_rank
Parameters
  • ind (Individual):

  • other_fitness (NSGA2Fitness):

  • other_ind (Individual):

  • Returns (True ind has lower rank or equal rank and bigger crwoding value):

  • -------

def equal_to(self, ind, other_fitness, other_ind):
75	def equal_to(self, ind, other_fitness, other_ind):
76		return self.front_rank == other_ind.fitness.front_rank and \
77			   self.crowding == other_ind.fitness.crowding

Compares between the current fitness of the individual ind to the fitness score other_fitness of other_ind

Parameters
  • ind (Individual): the individual instance that holds this Fitness instance
  • other_fitness (Fitness): the Fitness instance of the other individual
  • other_ind (Individual): the other individual instance which is being compared to the individual ind
Returns
  • bool: True if this fitness is equal to the other fitness, False otherwise
def dominate(self, ind, other_fitness, other_ind):
79	def dominate(self, ind, other_fitness, other_ind):
80		self.check_comparable_fitnesses(other_fitness, ind, other_ind)
81		self_fit = self.get_augmented_fitness(ind)
82		other_fit = other_fitness.get_augmented_fitness(other_ind)
83		return all([self._o1_at_least_o2(o1, o2, h_is_b) for h_is_b, o1, o2 in
84					zip(self.higher_is_better, self_fit, other_fit)]) and \
85			   any([self._o1_better_then_o2(o1, o2, h_is_b) for h_is_b, o1, o2 in
86					zip(self.higher_is_better, self_fit, other_fit)])