eckity.subpopulation

  1import random
  2import numpy as np
  3
  4from eckity.creators.creator import Creator
  5from eckity.creators.gp_creators.full import FullCreator
  6
  7from eckity.genetic_operators.crossovers.subtree_crossover import SubtreeCrossover
  8from eckity.genetic_operators.mutations.erc_mutation import ERCMutation
  9from eckity.genetic_operators.mutations.subtree_mutation import SubtreeMutation
 10from eckity.genetic_operators.selections.tournament_selection import TournamentSelection
 11
 12
 13class Subpopulation:
 14    """
 15    Subgroup of the experiment population.
 16
 17    Contains a specific encoding, fitness evaluation method, creator list, operator sequence and selection methods.
 18
 19    Parameters
 20    ----------
 21    evaluator: IndividualEvaluator
 22        fitness evaluation method for the individuals of this sub-population
 23
 24    creators: Creator or list of Creators, default=None
 25        possible creators to generate individuals according to the encoding
 26        of this sub-population (GPTrees, Bit Vectors etc.)
 27
 28    pcr: list of integers, default=None
 29        probability mapping for each creator in creators parameter.
 30        Length must match the length of creators parameter.
 31
 32    operators_sequence: list of Crossovers and Mutations, default=None
 33        Possible crossover and mutation actions that can change the individuals' representations.
 34        The operators will be done sequentially in each generation, by their order in the list.
 35        See eckity.genetic_operators for more details on crossover and mutation operators
 36
 37    selection_methods: list of SelectionMethods
 38        Methods for selecting individuals in each generation.
 39        See eckity.genetic_operators for more details on selection methods
 40
 41    elitism_rate: float, default=0.0
 42        What percentage of the sub-population's individuals should be kept as elites for the next generation
 43
 44    population_size: int, default=200
 45        The number of individuals in this sub-population.
 46
 47    individuals: list of Individuals, default=None
 48        The individuals list of this sub-population.
 49
 50    higher_is_better: bool, default=False
 51        Determines if the fitness value of this sub-population's individuals should be maximized or minimized.
 52
 53    Attributes
 54    ----------
 55    n_elite: int
 56        Number of the sub-population's elite individuals.
 57        In every generation, there will be n_elites slots for the elite individuals
 58        that will be copied as-is to the next generation.
 59    """
 60
 61    def __init__(self,
 62                 evaluator,
 63                 creators=None,
 64                 pcr=None,
 65                 operators_sequence=None,
 66                 selection_methods=None,
 67                 elitism_rate=0.0,
 68                 population_size=200,
 69                 individuals=None,
 70                 higher_is_better=False):
 71
 72        # verify valid creators and creation probability inputs
 73        if creators is None:
 74            full_cr = FullCreator()
 75            creators = [full_cr]
 76        elif isinstance(creators, Creator):
 77            creators = [creators]
 78        elif isinstance(creators, list):
 79            if len(creators) == 0:
 80                raise ValueError('Creators list cannot be empty')
 81            for creator in creators:
 82                if not isinstance(creator, Creator):
 83                    raise ValueError('Detected a non-creator instance as an element in creators list')
 84        else:
 85            raise ValueError(
 86                'Parameter creators must be either a Creator or a list of Creators\n '
 87                'received creators with unexpected type of', type(creators)
 88            )
 89
 90        if pcr is None:
 91            pcr = [1 / len(creators) for _ in creators]
 92
 93        if len(creators) != len(pcr):
 94            raise ValueError(f'Number of creators ({len(creators)}) \
 95                                    must match number of creation probabilities {(len(pcr))}!')
 96        if sum(pcr) != 1:
 97            raise ValueError(f'Sum of creation probabilities ({pcr}) must be 1!')
 98
 99        # set default args
100        if operators_sequence is None:
101            operators_sequence = [SubtreeCrossover(arity=2, probability=0.9),
102                                  SubtreeMutation(arity=1, probability=0.7),
103                                  ERCMutation(arity=1, probability=0.1)]
104        if selection_methods is None:
105            selection_methods = [(TournamentSelection(tournament_size=10, higher_is_better=higher_is_better), 1)]
106
107        self.creators = creators
108        self._pcr = pcr
109        self._operators_sequence = operators_sequence
110        self.population_size = population_size
111        self._selection_methods = selection_methods
112        self.higher_is_better = higher_is_better
113        self.evaluator = evaluator
114
115        self.n_elite = round(elitism_rate * self.population_size)
116        self.individuals = individuals
117
118    def create_subpopulation_individuals(self):
119        if self.individuals is None:
120            # Select one creator to generate individuals, with respect to the creators' probabilities
121            selected_creator = random.choices(self.creators, weights=self._pcr)[
122                0]  # random.choices returns [selected_creator]
123            self.individuals = selected_creator.create_individuals(self.population_size, self.higher_is_better)
124
125    def get_operators_sequence(self):
126        return self._operators_sequence
127
128    def get_selection_methods(self):
129        return self._selection_methods
130
131    def get_best_individual(self):
132        sorted_inds = sorted(self.individuals, key=lambda ind: ind.get_augmented_fitness(),
133                             reverse=self.higher_is_better)
134        return sorted_inds[0]
135
136    def get_worst_individual(self):
137        sorted_inds = sorted(self.individuals, key=lambda ind: ind.get_augmented_fitness(),
138                             reverse=not self.higher_is_better)
139        return sorted_inds[0]
140
141    def get_average_fitness(self):
142        return np.mean([indiv.get_pure_fitness() for indiv in self.individuals])
143
144    def contains_individual(self, individual):
145        return individual in self.individuals
class Subpopulation:
 14class Subpopulation:
 15    """
 16    Subgroup of the experiment population.
 17
 18    Contains a specific encoding, fitness evaluation method, creator list, operator sequence and selection methods.
 19
 20    Parameters
 21    ----------
 22    evaluator: IndividualEvaluator
 23        fitness evaluation method for the individuals of this sub-population
 24
 25    creators: Creator or list of Creators, default=None
 26        possible creators to generate individuals according to the encoding
 27        of this sub-population (GPTrees, Bit Vectors etc.)
 28
 29    pcr: list of integers, default=None
 30        probability mapping for each creator in creators parameter.
 31        Length must match the length of creators parameter.
 32
 33    operators_sequence: list of Crossovers and Mutations, default=None
 34        Possible crossover and mutation actions that can change the individuals' representations.
 35        The operators will be done sequentially in each generation, by their order in the list.
 36        See eckity.genetic_operators for more details on crossover and mutation operators
 37
 38    selection_methods: list of SelectionMethods
 39        Methods for selecting individuals in each generation.
 40        See eckity.genetic_operators for more details on selection methods
 41
 42    elitism_rate: float, default=0.0
 43        What percentage of the sub-population's individuals should be kept as elites for the next generation
 44
 45    population_size: int, default=200
 46        The number of individuals in this sub-population.
 47
 48    individuals: list of Individuals, default=None
 49        The individuals list of this sub-population.
 50
 51    higher_is_better: bool, default=False
 52        Determines if the fitness value of this sub-population's individuals should be maximized or minimized.
 53
 54    Attributes
 55    ----------
 56    n_elite: int
 57        Number of the sub-population's elite individuals.
 58        In every generation, there will be n_elites slots for the elite individuals
 59        that will be copied as-is to the next generation.
 60    """
 61
 62    def __init__(self,
 63                 evaluator,
 64                 creators=None,
 65                 pcr=None,
 66                 operators_sequence=None,
 67                 selection_methods=None,
 68                 elitism_rate=0.0,
 69                 population_size=200,
 70                 individuals=None,
 71                 higher_is_better=False):
 72
 73        # verify valid creators and creation probability inputs
 74        if creators is None:
 75            full_cr = FullCreator()
 76            creators = [full_cr]
 77        elif isinstance(creators, Creator):
 78            creators = [creators]
 79        elif isinstance(creators, list):
 80            if len(creators) == 0:
 81                raise ValueError('Creators list cannot be empty')
 82            for creator in creators:
 83                if not isinstance(creator, Creator):
 84                    raise ValueError('Detected a non-creator instance as an element in creators list')
 85        else:
 86            raise ValueError(
 87                'Parameter creators must be either a Creator or a list of Creators\n '
 88                'received creators with unexpected type of', type(creators)
 89            )
 90
 91        if pcr is None:
 92            pcr = [1 / len(creators) for _ in creators]
 93
 94        if len(creators) != len(pcr):
 95            raise ValueError(f'Number of creators ({len(creators)}) \
 96                                    must match number of creation probabilities {(len(pcr))}!')
 97        if sum(pcr) != 1:
 98            raise ValueError(f'Sum of creation probabilities ({pcr}) must be 1!')
 99
100        # set default args
101        if operators_sequence is None:
102            operators_sequence = [SubtreeCrossover(arity=2, probability=0.9),
103                                  SubtreeMutation(arity=1, probability=0.7),
104                                  ERCMutation(arity=1, probability=0.1)]
105        if selection_methods is None:
106            selection_methods = [(TournamentSelection(tournament_size=10, higher_is_better=higher_is_better), 1)]
107
108        self.creators = creators
109        self._pcr = pcr
110        self._operators_sequence = operators_sequence
111        self.population_size = population_size
112        self._selection_methods = selection_methods
113        self.higher_is_better = higher_is_better
114        self.evaluator = evaluator
115
116        self.n_elite = round(elitism_rate * self.population_size)
117        self.individuals = individuals
118
119    def create_subpopulation_individuals(self):
120        if self.individuals is None:
121            # Select one creator to generate individuals, with respect to the creators' probabilities
122            selected_creator = random.choices(self.creators, weights=self._pcr)[
123                0]  # random.choices returns [selected_creator]
124            self.individuals = selected_creator.create_individuals(self.population_size, self.higher_is_better)
125
126    def get_operators_sequence(self):
127        return self._operators_sequence
128
129    def get_selection_methods(self):
130        return self._selection_methods
131
132    def get_best_individual(self):
133        sorted_inds = sorted(self.individuals, key=lambda ind: ind.get_augmented_fitness(),
134                             reverse=self.higher_is_better)
135        return sorted_inds[0]
136
137    def get_worst_individual(self):
138        sorted_inds = sorted(self.individuals, key=lambda ind: ind.get_augmented_fitness(),
139                             reverse=not self.higher_is_better)
140        return sorted_inds[0]
141
142    def get_average_fitness(self):
143        return np.mean([indiv.get_pure_fitness() for indiv in self.individuals])
144
145    def contains_individual(self, individual):
146        return individual in self.individuals

Subgroup of the experiment population.

Contains a specific encoding, fitness evaluation method, creator list, operator sequence and selection methods.

Parameters
  • evaluator (IndividualEvaluator): fitness evaluation method for the individuals of this sub-population
  • creators (Creator or list of Creators, default=None): possible creators to generate individuals according to the encoding of this sub-population (GPTrees, Bit Vectors etc.)
  • pcr (list of integers, default=None): probability mapping for each creator in creators parameter. Length must match the length of creators parameter.
  • operators_sequence (list of Crossovers and Mutations, default=None): Possible crossover and mutation actions that can change the individuals' representations. The operators will be done sequentially in each generation, by their order in the list. See eckity.genetic_operators for more details on crossover and mutation operators
  • selection_methods (list of SelectionMethods): Methods for selecting individuals in each generation. See eckity.genetic_operators for more details on selection methods
  • elitism_rate (float, default=0.0): What percentage of the sub-population's individuals should be kept as elites for the next generation
  • population_size (int, default=200): The number of individuals in this sub-population.
  • individuals (list of Individuals, default=None): The individuals list of this sub-population.
  • higher_is_better (bool, default=False): Determines if the fitness value of this sub-population's individuals should be maximized or minimized.
Attributes
  • n_elite (int): Number of the sub-population's elite individuals. In every generation, there will be n_elites slots for the elite individuals that will be copied as-is to the next generation.
Subpopulation( evaluator, creators=None, pcr=None, operators_sequence=None, selection_methods=None, elitism_rate=0.0, population_size=200, individuals=None, higher_is_better=False)
 62    def __init__(self,
 63                 evaluator,
 64                 creators=None,
 65                 pcr=None,
 66                 operators_sequence=None,
 67                 selection_methods=None,
 68                 elitism_rate=0.0,
 69                 population_size=200,
 70                 individuals=None,
 71                 higher_is_better=False):
 72
 73        # verify valid creators and creation probability inputs
 74        if creators is None:
 75            full_cr = FullCreator()
 76            creators = [full_cr]
 77        elif isinstance(creators, Creator):
 78            creators = [creators]
 79        elif isinstance(creators, list):
 80            if len(creators) == 0:
 81                raise ValueError('Creators list cannot be empty')
 82            for creator in creators:
 83                if not isinstance(creator, Creator):
 84                    raise ValueError('Detected a non-creator instance as an element in creators list')
 85        else:
 86            raise ValueError(
 87                'Parameter creators must be either a Creator or a list of Creators\n '
 88                'received creators with unexpected type of', type(creators)
 89            )
 90
 91        if pcr is None:
 92            pcr = [1 / len(creators) for _ in creators]
 93
 94        if len(creators) != len(pcr):
 95            raise ValueError(f'Number of creators ({len(creators)}) \
 96                                    must match number of creation probabilities {(len(pcr))}!')
 97        if sum(pcr) != 1:
 98            raise ValueError(f'Sum of creation probabilities ({pcr}) must be 1!')
 99
100        # set default args
101        if operators_sequence is None:
102            operators_sequence = [SubtreeCrossover(arity=2, probability=0.9),
103                                  SubtreeMutation(arity=1, probability=0.7),
104                                  ERCMutation(arity=1, probability=0.1)]
105        if selection_methods is None:
106            selection_methods = [(TournamentSelection(tournament_size=10, higher_is_better=higher_is_better), 1)]
107
108        self.creators = creators
109        self._pcr = pcr
110        self._operators_sequence = operators_sequence
111        self.population_size = population_size
112        self._selection_methods = selection_methods
113        self.higher_is_better = higher_is_better
114        self.evaluator = evaluator
115
116        self.n_elite = round(elitism_rate * self.population_size)
117        self.individuals = individuals
creators
population_size
higher_is_better
evaluator
n_elite
individuals
def create_subpopulation_individuals(self):
119    def create_subpopulation_individuals(self):
120        if self.individuals is None:
121            # Select one creator to generate individuals, with respect to the creators' probabilities
122            selected_creator = random.choices(self.creators, weights=self._pcr)[
123                0]  # random.choices returns [selected_creator]
124            self.individuals = selected_creator.create_individuals(self.population_size, self.higher_is_better)
def get_operators_sequence(self):
126    def get_operators_sequence(self):
127        return self._operators_sequence
def get_selection_methods(self):
129    def get_selection_methods(self):
130        return self._selection_methods
def get_best_individual(self):
132    def get_best_individual(self):
133        sorted_inds = sorted(self.individuals, key=lambda ind: ind.get_augmented_fitness(),
134                             reverse=self.higher_is_better)
135        return sorted_inds[0]
def get_worst_individual(self):
137    def get_worst_individual(self):
138        sorted_inds = sorted(self.individuals, key=lambda ind: ind.get_augmented_fitness(),
139                             reverse=not self.higher_is_better)
140        return sorted_inds[0]
def get_average_fitness(self):
142    def get_average_fitness(self):
143        return np.mean([indiv.get_pure_fitness() for indiv in self.individuals])
def contains_individual(self, individual):
145    def contains_individual(self, individual):
146        return individual in self.individuals