Population

Individual

class gaggle.population.individual.Individual(individual_args: IndividualArgs = None, sys_args: SysArgs = None)[source]

Bases: Module

An object that stores a single candidate solution to the given problem (aka a chromosome). This is the parent class for any other individual type. The gene_pool field stores the entire chromosome formatted as pytorch model parameters.

CONFIG_GENE_POOL = 'gene_pool_config'
CONFIG_INDIVIDUAL_ARGS = 'individual_args_config'
apply_bounds(lower_bound=None, upper_bound=None)[source]

Apply parameter bounds.

Parameters:
  • lower_bound

  • upper_bound

Returns:

static clip(tensor, lower_bound=None, upper_bound=None)[source]

torch.clip wrapper in case the individual created does not use a type support by torch.clip. If that is the case, the individual can overwrite this clip method to the desired behavior.

Parameters:
  • tensor – torch tensor to clip

  • lower_bound – min value

  • upper_bound – max value

Returns:

forward(*args, **kwargs)[source]

By default we returned a flattened tensor of the model parameters.

Notes

We do not return the metadata that can be used to reconstruct the gene_pool dictionary as this should not be used to modify the parameters directly (the tensor does not link back to the parameters).

Parameters:
  • *args

  • **kwargs

Returns:

A flattened pytorch tensor of length self.genome_size.

abstract generate_gene_pool(*args, **kwargs) dict[slice(<class 'int'>, dict[slice(<class 'str'>, <class 'torch.nn.parameter.Parameter'>, None), slice(<class 'str'>, <class 'int'>, None)], None)][source]

Should return a dictionary of dictionaries where the inner dictionary has a “param” and a “size” key for each of the nn.Parameters in the dictionary

get_gene_pool()[source]

Returns the gene pool of the individual if it already exists, otherwise generates it then returns it.

Returns:

The individual’s gene pool as a dictionary

get_genome_size()[source]

Returns the genome size of the individual if it already exists, otherwise generates it then returns it. If the gene pool has not been generated when this is called, it will generate it.

Returns:

The individual’s genome size as an int.

initialize(*args, **kwargs) Module[source]

Represents the initialization rule for an individual. It should modify the gene pool.

Parameters:
  • *args

  • **kwargs

Returns:

self

save(outdir_args: OutdirArgs = None) dict[source]

Saves the individual to a file in the path provided by outdir_args.

Parameters:

outdir_args

Returns:

Individual_factory

class gaggle.population.individual_factory.IndividualFactory[source]

Bases: object

Factory that generates pre-existing available Individuals. IndividualFactory.individuals stores said Individuals as a dictionary with their name as key and the uninitialized Individual object as value.

classmethod from_individual_args(individual_args: IndividualArgs = None, sys_args: SysArgs = None, *args, **kwargs)[source]

Initializes the requested Individual from the dictionary of available Individuals.

This is done by using the attribute individual_args.individual_name as the lookup key to IndividualFactory.individuals. :param individual_args: :param sys_args: :param *args: :param **kwargs:

Returns:

Initialized Individual object.

individuals = {'nn': <class 'gaggle.population.base_individuals.nn_individual.NNIndividual'>, 'numpy': <class 'gaggle.population.base_individuals.numpy_individual.NumpyIndividual'>, 'pytorch': <class 'gaggle.population.base_individuals.pytorch_individual.PytorchIndividual'>, 'rl': <class 'gaggle.population.base_individuals.rl_individual.RLIndividual'>}
classmethod update(key, individual)[source]

Add a new Individual to the dictionary of Individuals that can be created.

It is added to IndidividualFactory.individuals

Parameters:
  • key – dataset name that will be used as the dictionary lookup key

  • individual – Individual class object, it needs to not be already initialized

Population_manager

class gaggle.population.population_manager.PopulationManager(ga_args: GAArgs = None, individual_args: IndividualArgs = None, sys_args: SysArgs = None, default_individual: Type[Individual] = None, *args, **kwargs)[source]

Bases: object

Stores and manages all the individuals keeping track of their fitness. To avoid wasteful computation, we optionally keep track of an individual’s freshness and only recompute its fitness if it was modified since its fitness was last computed.

The Population Manager also provides a standardized interface for the evolutionary operators to access and update individuals. It stores all the individual-related meta-information required for the operators, such as which parents have been chosen, which individuals will be crossed over etc. This simplifies the operator pipeline by avoiding the need for operators to interface with each other directly.

apply_bounds(ids: list[int])[source]

Applies the parameter value bounds if they were set to a value other than None in the individual_args. This calls each individual’s own apply_bounds with the lower and upper bound. :param ids: list of ids of the individuals to which this needs to be applied

Returns:

create_buffer(key: str, initial_value=None)[source]

Wrapper that allows for storage of custom buffers. This can be used to store meta-data when building custom operators that need to communicate with one-another.

Parameters:
  • key – unique key associated with the buffer that will serve as lookup

  • initial_value – initial value of the buffer, can be anything

Returns:

eval()[source]

Sets the individuals to evaluation mode. Is used if individuals have evaluation specific configurations.

Returns:

get_buffer(key: str)[source]

Gets a buffer associated with the key key that was created using self.create_buffer

Parameters:

key

Returns:

get_fitness()[source]
get_freshness()[source]
get_gene_count()[source]

Assuming all individuals have the same genome size, returns the genome size of the first individual (which if the assumption holds should be the genome size of all individuals in the population.

Returns:

Genome size as an int.

get_individual(individual_idx: int)[source]
get_individual_fitness(individual_id: int)[source]

Get an individual’s fitness

Parameters:

individual_id

Returns:

get_mating_tuples()[source]
get_num_protected()[source]
get_parents()[source]
get_population()[source]
get_protected()[source]
get_to_mutate()[source]
is_fresh(individual_id: int)[source]

Check if an individual with id individual_id is fresh. Meaning whether its fitness needs to be recomputed or not.

Parameters:

individual_id

Returns:

A boolean that reflects whether the individual’s fitness needs to be recomputed or

not. True if it does, False otherwise

set_freshness(individual_id: int, freshness: bool)[source]

Set an individual’s freshness.

Parameters:
  • individual_id

  • freshness

Returns:

set_individual_fitness(individual_id: int, fitness: float)[source]

Set an individual’s fitness.

Parameters:
  • individual_id

  • fitness

Returns:

train()[source]

Sets the individuals to training mode. Is used if individuals have training specific configurations.

Returns:

update_buffer(key: str, new_value)[source]

Sets the value of a buffer associated with key key that was created using self.create_buffer using new value new_value.

Parameters:
  • key

  • new_value

Returns:

update_mating_tuples(new_tuples: list[tuple])[source]

Update the list of mating tuples with a new list of mating tuples.

Parameters:

new_tuples

Returns:

update_parents(new_parents: list[int])[source]

Update the list of parent ids with a new list of parent ids.

Parameters:

new_parents

Returns:

update_population(new_individuals: dict[slice(<class 'int'>, <class 'gaggle.population.individual.Individual'>, None)], new_freshness: dict[slice(<class 'int'>, <class 'bool'>, None)])[source]

Update the entire population as well as its freshness with new dictionaries of {id: Individual} and {id: bool}.

Parameters:
  • new_individuals

  • new_freshness

Returns:

update_protected(new_protected: list[int])[source]

Update the list of protected individual ids (individuals that will survive to the next generation no matter what, similar to elitism) with a new list of protected individual ids.

Parameters:

new_protected

Returns:

update_to_mutate(new_to_mutate: list[int])[source]

Update the list of individual ids that need to be mutated during the next call to a Mutation operator with a new list of individual ids.

Parameters:

new_to_mutate

Returns: