eckity.algorithms.simple_evolution
This module implements the SimpleEvolution class.
1""" 2This module implements the SimpleEvolution class. 3""" 4 5from time import time 6from overrides import overrides 7 8from eckity.algorithms.algorithm import Algorithm 9from eckity.breeders.simple_breeder import SimpleBreeder 10from eckity.evaluators.simple_population_evaluator import SimplePopulationEvaluator 11from eckity.termination_checkers.threshold_from_target_termination_checker \ 12 import ThresholdFromTargetTerminationChecker 13 14 15class SimpleEvolution(Algorithm): 16 """ 17 Simple case evolutionary algorithm. 18 19 Basic evolutionary algorithm that contains one subpopulation. 20 Does not include and is not meant for multi-objective, co-evolution etc. 21 22 Parameters 23 ---------- 24 population: Population 25 The population to be evolved. Contains only one subpopulation in simple case. 26 Consists of a list of individuals. 27 28 statistics: Statistics or list of Statistics, default=None 29 Provide multiple statistics on the population during the evolutionary run. 30 31 breeder: SimpleBreeder, default=SimpleBreeder instance 32 Responsible for applying the selection method and operator sequence on the individuals 33 in each generation. Applies on one subpopulation in simple case. 34 35 population_evaluator: SimplePopulationEvaluator, default=SimplePopulationEvaluator instance 36 Responsible for evaluating each individual's fitness concurrently and returns the best individual 37 of each subpopulation (returns a single individual in simple case). 38 39 max_generation: int, default=1000 40 Maximal number of generations to run the evolutionary process. 41 Note the evolution could end before reaching max_generation, depending on the termination checker. 42 43 events: dict(str, dict(object, function)), default=None 44 Dictionary of events, where each event holds a dictionary of (subscriber, callback method). 45 46 event_names: list of strings, default=None 47 Names of events to publish during the evolution. 48 49 termination_checker: TerminationChecker, default=ThresholdFromTargetTerminationChecker() 50 Responsible for checking if the algorithm should finish before reaching max_generation. 51 52 max_workers: int, default=None 53 Maximal number of worker nodes for the Executor object that evaluates the fitness of the individuals. 54 55 random_generator: module, default=random 56 Random generator module. 57 58 random_seed: float or int, default=current system time 59 Random seed for deterministic experiment. 60 61 generation_seed: int, default=None 62 Current generation seed. Useful for resuming a previously paused experiment. 63 64 best_of_run_: Individual, default=None 65 The individual that has the best fitness in the entire evolutionary run. 66 67 best_of_gen: Individual, default=None 68 The individual that has the best fitness in the current generation. 69 70 worst_of_gen: Individual, default=None 71 The individual that has the worst fitness in the current generation. 72 73 generation_num: int, default=0 74 Current generation number 75 """ 76 77 def __init__(self, 78 population, 79 statistics=None, 80 breeder=SimpleBreeder(), 81 population_evaluator=SimplePopulationEvaluator(), 82 max_generation=500, 83 events=None, 84 event_names=None, 85 termination_checker=ThresholdFromTargetTerminationChecker(threshold=0), 86 executor='thread', 87 max_workers=None, 88 random_generator=None, 89 random_seed=time(), 90 generation_seed=None, 91 best_of_run_=None, 92 best_of_gen=None, 93 worst_of_gen=None, 94 generation_num=0): 95 96 if event_names is None: 97 _event_names = ['before_eval', 'after_eval', 'before_breeding', 'after_breeding'] 98 else: 99 _event_names = event_names 100 101 if statistics is None: 102 statistics = [] 103 104 super().__init__(population, statistics=statistics, breeder=breeder, population_evaluator=population_evaluator, 105 events=events, event_names=_event_names, executor=executor, max_workers=max_workers, 106 random_generator=random_generator, random_seed=random_seed, generation_seed=generation_seed, 107 termination_checker=termination_checker, generation_num=generation_num) 108 109 self.termination_checker = termination_checker 110 self.best_of_run_ = best_of_run_ 111 self.best_of_gen = best_of_gen 112 self.worst_of_gen = worst_of_gen 113 self.max_generation = max_generation 114 115 self.final_generation_ = None 116 117 def initialize(self): 118 """ 119 Initialize the evolutionary algorithm 120 121 Register statistics to `after_generation` event 122 """ 123 super().initialize() 124 for stat in self.statistics: 125 self.register('after_generation', stat.write_statistics) 126 127 @overrides 128 def generation_iteration(self, gen): 129 """ 130 Performs one iteration of the evolutionary run, for the current generation 131 132 Parameters 133 ---------- 134 gen: 135 current generation number (for example, generation #100) 136 137 Returns 138 ------- 139 None. 140 """ 141 142 # breed population 143 self.breeder.breed(self.population) 144 145 # Evaluate the entire population and get the best individual 146 self.best_of_gen = self.population_evaluator.act(self.population) 147 148 if self.best_of_gen.better_than(self.best_of_run_): 149 self.best_of_run_ = self.best_of_gen 150 151 self.worst_of_gen = self.population.sub_populations[0].get_worst_individual() 152 153 def execute(self, **kwargs): 154 """ 155 Compute output using best evolved individual. 156 Use `execute` in a non-sklearn setting. 157 Input keyword arguments that set variable values. 158 For example if `terminal_set=['x', 'y', 1, -1]` then call `execute(x=..., y=...)`. 159 160 Parameters 161 ---------- 162 **kwargs : keyword arguments 163 The input to the program (tree). 164 165 Returns 166 ------- 167 object 168 Output as computed by the best individual of the evolutionary run. 169 170 """ 171 return self.best_of_run_.execute(**kwargs) 172 173 def finish(self): 174 """ 175 Finish the evolutionary run by showing the best individual and printing the best fitness 176 """ 177 # todo should move to finisher 178 self.best_of_run_.show() 179 180 def get_individual_evaluator(self): 181 return self.population.sub_populations[0].evaluator 182 183 def get_average_fitness(self): # TODO check if it should be here or register statistic to breeder or sub pop 184 return self.population.get_average_fitness() 185 186 def event_name_to_data(self, event_name): 187 if event_name == "init": 188 return { 189 "population": self.population, 190 "statistics": self.statistics, 191 "breeder": self.breeder, 192 "termination_checker": self.termination_checker, 193 "max_generation": self.max_generation, 194 "events": self.events, 195 "max_workers": self.max_workers 196 } 197 198 # default case 199 return { 200 "population": self.population, 201 "best_of_run_": self.best_of_run_, 202 "best_of_gen": self.best_of_gen, 203 "generation_num": self.generation_num 204 } 205
16class SimpleEvolution(Algorithm): 17 """ 18 Simple case evolutionary algorithm. 19 20 Basic evolutionary algorithm that contains one subpopulation. 21 Does not include and is not meant for multi-objective, co-evolution etc. 22 23 Parameters 24 ---------- 25 population: Population 26 The population to be evolved. Contains only one subpopulation in simple case. 27 Consists of a list of individuals. 28 29 statistics: Statistics or list of Statistics, default=None 30 Provide multiple statistics on the population during the evolutionary run. 31 32 breeder: SimpleBreeder, default=SimpleBreeder instance 33 Responsible for applying the selection method and operator sequence on the individuals 34 in each generation. Applies on one subpopulation in simple case. 35 36 population_evaluator: SimplePopulationEvaluator, default=SimplePopulationEvaluator instance 37 Responsible for evaluating each individual's fitness concurrently and returns the best individual 38 of each subpopulation (returns a single individual in simple case). 39 40 max_generation: int, default=1000 41 Maximal number of generations to run the evolutionary process. 42 Note the evolution could end before reaching max_generation, depending on the termination checker. 43 44 events: dict(str, dict(object, function)), default=None 45 Dictionary of events, where each event holds a dictionary of (subscriber, callback method). 46 47 event_names: list of strings, default=None 48 Names of events to publish during the evolution. 49 50 termination_checker: TerminationChecker, default=ThresholdFromTargetTerminationChecker() 51 Responsible for checking if the algorithm should finish before reaching max_generation. 52 53 max_workers: int, default=None 54 Maximal number of worker nodes for the Executor object that evaluates the fitness of the individuals. 55 56 random_generator: module, default=random 57 Random generator module. 58 59 random_seed: float or int, default=current system time 60 Random seed for deterministic experiment. 61 62 generation_seed: int, default=None 63 Current generation seed. Useful for resuming a previously paused experiment. 64 65 best_of_run_: Individual, default=None 66 The individual that has the best fitness in the entire evolutionary run. 67 68 best_of_gen: Individual, default=None 69 The individual that has the best fitness in the current generation. 70 71 worst_of_gen: Individual, default=None 72 The individual that has the worst fitness in the current generation. 73 74 generation_num: int, default=0 75 Current generation number 76 """ 77 78 def __init__(self, 79 population, 80 statistics=None, 81 breeder=SimpleBreeder(), 82 population_evaluator=SimplePopulationEvaluator(), 83 max_generation=500, 84 events=None, 85 event_names=None, 86 termination_checker=ThresholdFromTargetTerminationChecker(threshold=0), 87 executor='thread', 88 max_workers=None, 89 random_generator=None, 90 random_seed=time(), 91 generation_seed=None, 92 best_of_run_=None, 93 best_of_gen=None, 94 worst_of_gen=None, 95 generation_num=0): 96 97 if event_names is None: 98 _event_names = ['before_eval', 'after_eval', 'before_breeding', 'after_breeding'] 99 else: 100 _event_names = event_names 101 102 if statistics is None: 103 statistics = [] 104 105 super().__init__(population, statistics=statistics, breeder=breeder, population_evaluator=population_evaluator, 106 events=events, event_names=_event_names, executor=executor, max_workers=max_workers, 107 random_generator=random_generator, random_seed=random_seed, generation_seed=generation_seed, 108 termination_checker=termination_checker, generation_num=generation_num) 109 110 self.termination_checker = termination_checker 111 self.best_of_run_ = best_of_run_ 112 self.best_of_gen = best_of_gen 113 self.worst_of_gen = worst_of_gen 114 self.max_generation = max_generation 115 116 self.final_generation_ = None 117 118 def initialize(self): 119 """ 120 Initialize the evolutionary algorithm 121 122 Register statistics to `after_generation` event 123 """ 124 super().initialize() 125 for stat in self.statistics: 126 self.register('after_generation', stat.write_statistics) 127 128 @overrides 129 def generation_iteration(self, gen): 130 """ 131 Performs one iteration of the evolutionary run, for the current generation 132 133 Parameters 134 ---------- 135 gen: 136 current generation number (for example, generation #100) 137 138 Returns 139 ------- 140 None. 141 """ 142 143 # breed population 144 self.breeder.breed(self.population) 145 146 # Evaluate the entire population and get the best individual 147 self.best_of_gen = self.population_evaluator.act(self.population) 148 149 if self.best_of_gen.better_than(self.best_of_run_): 150 self.best_of_run_ = self.best_of_gen 151 152 self.worst_of_gen = self.population.sub_populations[0].get_worst_individual() 153 154 def execute(self, **kwargs): 155 """ 156 Compute output using best evolved individual. 157 Use `execute` in a non-sklearn setting. 158 Input keyword arguments that set variable values. 159 For example if `terminal_set=['x', 'y', 1, -1]` then call `execute(x=..., y=...)`. 160 161 Parameters 162 ---------- 163 **kwargs : keyword arguments 164 The input to the program (tree). 165 166 Returns 167 ------- 168 object 169 Output as computed by the best individual of the evolutionary run. 170 171 """ 172 return self.best_of_run_.execute(**kwargs) 173 174 def finish(self): 175 """ 176 Finish the evolutionary run by showing the best individual and printing the best fitness 177 """ 178 # todo should move to finisher 179 self.best_of_run_.show() 180 181 def get_individual_evaluator(self): 182 return self.population.sub_populations[0].evaluator 183 184 def get_average_fitness(self): # TODO check if it should be here or register statistic to breeder or sub pop 185 return self.population.get_average_fitness() 186 187 def event_name_to_data(self, event_name): 188 if event_name == "init": 189 return { 190 "population": self.population, 191 "statistics": self.statistics, 192 "breeder": self.breeder, 193 "termination_checker": self.termination_checker, 194 "max_generation": self.max_generation, 195 "events": self.events, 196 "max_workers": self.max_workers 197 } 198 199 # default case 200 return { 201 "population": self.population, 202 "best_of_run_": self.best_of_run_, 203 "best_of_gen": self.best_of_gen, 204 "generation_num": self.generation_num 205 }
Simple case evolutionary algorithm.
Basic evolutionary algorithm that contains one subpopulation. Does not include and is not meant for multi-objective, co-evolution etc.
Parameters
- population (Population): The population to be evolved. Contains only one subpopulation in simple case. Consists of a list of individuals.
- statistics (Statistics or list of Statistics, default=None): Provide multiple statistics on the population during the evolutionary run.
- breeder (SimpleBreeder, default=SimpleBreeder instance): Responsible for applying the selection method and operator sequence on the individuals in each generation. Applies on one subpopulation in simple case.
- population_evaluator (SimplePopulationEvaluator, default=SimplePopulationEvaluator instance): Responsible for evaluating each individual's fitness concurrently and returns the best individual of each subpopulation (returns a single individual in simple case).
- max_generation (int, default=1000): Maximal number of generations to run the evolutionary process. Note the evolution could end before reaching max_generation, depending on the termination checker.
- events (dict(str, dict(object, function)), default=None): Dictionary of events, where each event holds a dictionary of (subscriber, callback method).
- event_names (list of strings, default=None): Names of events to publish during the evolution.
- termination_checker (TerminationChecker, default=ThresholdFromTargetTerminationChecker()): Responsible for checking if the algorithm should finish before reaching max_generation.
- max_workers (int, default=None): Maximal number of worker nodes for the Executor object that evaluates the fitness of the individuals.
- random_generator (module, default=random): Random generator module.
- random_seed (float or int, default=current system time): Random seed for deterministic experiment.
- generation_seed (int, default=None): Current generation seed. Useful for resuming a previously paused experiment.
- best_of_run_ (Individual, default=None): The individual that has the best fitness in the entire evolutionary run.
- best_of_gen (Individual, default=None): The individual that has the best fitness in the current generation.
- worst_of_gen (Individual, default=None): The individual that has the worst fitness in the current generation.
- generation_num (int, default=0): Current generation number
SimpleEvolution( population, statistics=None, breeder=<eckity.breeders.simple_breeder.SimpleBreeder object>, population_evaluator=<eckity.evaluators.simple_population_evaluator.SimplePopulationEvaluator object>, max_generation=500, events=None, event_names=None, termination_checker=<eckity.termination_checkers.threshold_from_target_termination_checker.ThresholdFromTargetTerminationChecker object>, executor='thread', max_workers=None, random_generator=None, random_seed=1688113158.6392407, generation_seed=None, best_of_run_=None, best_of_gen=None, worst_of_gen=None, generation_num=0)
78 def __init__(self, 79 population, 80 statistics=None, 81 breeder=SimpleBreeder(), 82 population_evaluator=SimplePopulationEvaluator(), 83 max_generation=500, 84 events=None, 85 event_names=None, 86 termination_checker=ThresholdFromTargetTerminationChecker(threshold=0), 87 executor='thread', 88 max_workers=None, 89 random_generator=None, 90 random_seed=time(), 91 generation_seed=None, 92 best_of_run_=None, 93 best_of_gen=None, 94 worst_of_gen=None, 95 generation_num=0): 96 97 if event_names is None: 98 _event_names = ['before_eval', 'after_eval', 'before_breeding', 'after_breeding'] 99 else: 100 _event_names = event_names 101 102 if statistics is None: 103 statistics = [] 104 105 super().__init__(population, statistics=statistics, breeder=breeder, population_evaluator=population_evaluator, 106 events=events, event_names=_event_names, executor=executor, max_workers=max_workers, 107 random_generator=random_generator, random_seed=random_seed, generation_seed=generation_seed, 108 termination_checker=termination_checker, generation_num=generation_num) 109 110 self.termination_checker = termination_checker 111 self.best_of_run_ = best_of_run_ 112 self.best_of_gen = best_of_gen 113 self.worst_of_gen = worst_of_gen 114 self.max_generation = max_generation 115 116 self.final_generation_ = None
def
initialize(self):
118 def initialize(self): 119 """ 120 Initialize the evolutionary algorithm 121 122 Register statistics to `after_generation` event 123 """ 124 super().initialize() 125 for stat in self.statistics: 126 self.register('after_generation', stat.write_statistics)
Initialize the evolutionary algorithm
Register statistics to after_generation
event
@overrides
def
generation_iteration(self, gen):
128 @overrides 129 def generation_iteration(self, gen): 130 """ 131 Performs one iteration of the evolutionary run, for the current generation 132 133 Parameters 134 ---------- 135 gen: 136 current generation number (for example, generation #100) 137 138 Returns 139 ------- 140 None. 141 """ 142 143 # breed population 144 self.breeder.breed(self.population) 145 146 # Evaluate the entire population and get the best individual 147 self.best_of_gen = self.population_evaluator.act(self.population) 148 149 if self.best_of_gen.better_than(self.best_of_run_): 150 self.best_of_run_ = self.best_of_gen 151 152 self.worst_of_gen = self.population.sub_populations[0].get_worst_individual()
Performs one iteration of the evolutionary run, for the current generation
Parameters
- gen:: current generation number (for example, generation #100)
Returns
- None.
def
execute(self, **kwargs):
154 def execute(self, **kwargs): 155 """ 156 Compute output using best evolved individual. 157 Use `execute` in a non-sklearn setting. 158 Input keyword arguments that set variable values. 159 For example if `terminal_set=['x', 'y', 1, -1]` then call `execute(x=..., y=...)`. 160 161 Parameters 162 ---------- 163 **kwargs : keyword arguments 164 The input to the program (tree). 165 166 Returns 167 ------- 168 object 169 Output as computed by the best individual of the evolutionary run. 170 171 """ 172 return self.best_of_run_.execute(**kwargs)
Compute output using best evolved individual.
Use execute
in a non-sklearn setting.
Input keyword arguments that set variable values.
For example if terminal_set=['x', 'y', 1, -1]
then call execute(x=..., y=...)
.
Parameters
- **kwargs (keyword arguments): The input to the program (tree).
Returns
- object: Output as computed by the best individual of the evolutionary run.
def
finish(self):
174 def finish(self): 175 """ 176 Finish the evolutionary run by showing the best individual and printing the best fitness 177 """ 178 # todo should move to finisher 179 self.best_of_run_.show()
Finish the evolutionary run by showing the best individual and printing the best fitness
def
event_name_to_data(self, event_name):
187 def event_name_to_data(self, event_name): 188 if event_name == "init": 189 return { 190 "population": self.population, 191 "statistics": self.statistics, 192 "breeder": self.breeder, 193 "termination_checker": self.termination_checker, 194 "max_generation": self.max_generation, 195 "events": self.events, 196 "max_workers": self.max_workers 197 } 198 199 # default case 200 return { 201 "population": self.population, 202 "best_of_run_": self.best_of_run_, 203 "best_of_gen": self.best_of_gen, 204 "generation_num": self.generation_num 205 }
Convert a given event name to relevant data of the Algorithm for the event
Parameters
- event_name (string): name of the event that is happening
Returns
- dict: Algorithm data regarding the given event