Holland Reference¶
This page provides the core documentation reference for Holland.
Evolution¶
evolution¶
-
class
holland.evolution.
Evolver
(fitness_function, genome_params, selection_strategy, should_maximize_fitness=True)¶ Handles evolution for a population
Parameters: - fitness_function (function) – the fitness function used to evaluate individuals; see Fitness Function
- genome_params (dict) – a dictionary specifying genome parameters; see Genome Parameters
- selection_strategy (dict) – a dictionary specifying selection parameters; see Selection Strategy
- should_maximize_fitness (bool) – whether fitness should be maximized or minimized
-
evolve
(generation_params={}, initial_population=None, stop_conditions={'n_generations': 100, 'target_fitness': inf}, storage_options={}, logging_options={'format': '%(message)s', 'level': 20})¶ The heart of Holland.
Parameters: - generation_params (dict) – a dictionary specifying how to create each generation; see Generation Parameters
- initial_population (list) – an initial population
- stop_conditions (dict) – conditions for stopping execution; will stop if any of the conditions is met; see Stop Conditions below
- storage_options (dict) – configuration options for storing fitness and genomes (should contain keys
"fitness"
and"genomes"
); see Fitness Storage Options and Genome Storage Options - logging_options (dict) – options for logging passed to logging.basicConfig as
kwargs
Stop Conditions: - n_generations (int) – the number of generations to run evolution over
- target_fitness (int) – the target fitness score, will stop once the fittest individual reaches this score
Returns: - a list of fitness scores and genomes
[(fitness, genome), ...]
(fitness results); or - a tuple of fitness results (previous bullet) and list of historical fitness statistics
(fitness_results, fitness_history)
, ifstorage_options["fitness"]
has'should_record_fitness': True
and'format': 'memory'
Raises: - ValueError – if
generation_params["n_random"] < 0
orgeneration_params["n_elite"] < 0
- ValueError – if
population_size < 1
- ValueError – if
n_generations < 1
Todo
If an initial population is given but does not match the given genome parameters, some kind of error should be raised
Todo
If an initial population is given and some genomes are missing parameters, a warning is given unless a flag is set to fill those values randomly
- Dependencies:
- Example:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
from holland import evolve from math import cos, pi # specify hyper-parameters for genomes genome_parameters = { "gene1": {"type": "float", "min": -pi, "max": pi}, "gene2": {"type": "float", "min": -pi, "max": pi}, } # define a fitness function def my_fitness_function(individual): return cos(inidividual.gene1) * cos(individual.gene2) # evolve! my_population = evolve( genome_parameters, fitness_function=my_fitness_function, show_fitness_plot=True, num_generations=100, )
evaluation¶
-
class
holland.evolution.
Evaluator
(fitness_function, ascending=True)¶ Handles evaluation of genomes
Parameters: - fitness_function (func) – a function for evaluating the fitness of each genome; see Fitness Function
- ascending (bool) – whether or not to sort results in ascending order of fitness
-
evaluate_fitness
(gene_pool)¶ Evaluates the fitness of a population by applying a fitness function to each genome in the population
Parameters: gene_pool (list) – a population of genomes to evaluate Returns: a sorted list of tuples of the form (score, genome)
.
breeding¶
-
class
holland.evolution.
PopulationGenerator
(genome_params, selection_strategy, generation_params={})¶ Handles generating populations
Parameters: - genome_params (dict) – a dictionary specifying genome parameters; see Genome Parameters
- selection_strategy (dict) – a dictionary specifying selection parameters; see Selection Strategy
- generation_params (dict) – a dictionary specifying how to create the next generation; see Generation Parameters
Raises: - ValueError – if
n_random < 0
orn_elite < 0
- ValueError – if
n_random + n_elite > population_size
-
generate_next_generation
(fitness_results)¶ Generates the next generation
Parameters: fitness_results (list) – a sorted list of tuples containing a fitness score in the first position and a genome in the second (returned by evaluate_fitness()
)Returns: a list of genomes Note
For the sake of efficiency, this method expects
fitness_results
to be sorted in order to properly select genomes on the basis of fitness.evaluate_fitness()
returns sorted results.Todo
Write an example for usage
Raises: ValueError – if n_random + n_elite > population_size
- Dependencies:
-
breed_next_generation
(fitness_results, n_genomes)¶ Generates a given number of genomes by breeding, through crossover and mutation, existing genomes
Parameters: - fitness_results (list) – a sorted list of tuples containing a fitness score in the first position and a genome in the second (returned by
evaluate_fitness()
) - n_genomes (int) – the number of genomes to produce
Returns: a list of bred genomes
Raises: ValueError – if
n_genomes < 0
Note
For the sake of efficiency, this method expects
fitness_results
to be sorted in order to properly select genomes on the basis of fitness.evaluate_fitness()
returns sorted results.Todo
Write an example for usage
- Dependencies:
- fitness_results (list) – a sorted list of tuples containing a fitness score in the first position and a genome in the second (returned by
-
generate_random_genomes
(n_genomes)¶ Generates a given number of genomes based on genome parameters
Parameters: n_genomes (int) – the number of genomes to produce Returns: a list of randomly generated genomes Raises: ValueError – if n_genomes < 0
Todo
Write an example for usage
- Dependencies:
selection¶
-
class
holland.evolution.
Selector
(selection_strategy={})¶ Handles selection of genomes for breeding
Parameters: selection_strategy – parameters for selecting a breeding pool and sets of parents; see Selection Strategy
Raises: - ValueError – if any of
top
,mid
,bottom
, orrandom
is negative - ValueError – if
n_parents < 1
-
select_breeding_pool
(fitness_results)¶ Selects a pool of genomes from a population from which to draw parents for breeding the next generation
Parameters: fitness_results (list) – a sorted list of tuples containing a fitness score in the first position and a genome in the second (returned by evaluate_fitness()
)Returns: a list of tuples of the form (score, genome)
(same format asfitness_results
)Raises: ValueError – if len(fitness_results) < self.top + self.mid + self.bottom + self.random
Note
For the sake of efficiency, this method expects
fitness_results
to be sorted in order to properly select genomes on the basis of fitness.evaluate_fitness()
returns sorted results.- Dependencies:
-
select_parents
(fitness_results)¶ Selects parents from the given
fitness_results
to use for breeding a new genomeParameters: fitness_results (list) – a (not necessarily sorted list of tuples containing a fitness score in the first position and a genome in the second (returned by evaluate_fitness()
)Returns: a list of genomes (of length self.n_parents
)- Dependencies:
- ValueError – if any of
crossover¶
-
class
holland.evolution.
Crosser
(genome_params)¶ Handles genetic crossover
Parameters: genome_params (dict) – a dictionary specifying genome parameters, specifcally crossover_function
is relevant; see Genome Parameters-
cross_genomes
(parent_genomes)¶ Produces a new genome by applying crossover to multiple parent genomes
Parameters: parent_genomes – a list of parent genomes Returns: a single genome
-
mutation¶
-
class
holland.evolution.
Mutator
(genome_params)¶ Handles genetic mutation
Parameters: genome_params (dict) – a dictionary specifying genome parameters; see Genome Parameters -
mutate_genome
(genome)¶ Mutates a genome
Parameters: genome (dict) – the genome to mutate Returns: a mutated genome - Dependencies:
-
mutate_gene
(gene, gene_params)¶ Mutates a single gene
Parameters: - gene (a valid gene type) – the gene to mutate
- gene_params (dict) – parameters for a single gene; see Genome Parameters
Returns: a mutated gene
- Dependencies:
-
probabilistically_apply_mutation
(target, gene_params)¶ Either applies a mutation function to a target (gene or value of a gene) or does not, probabilistically according to the
mutation_rate
Parameters: - target (a valid, non-list, gene type) – the target to which to apply the mutation
- gene_params (dict) – parameters for a single gene; see Genome Parameters
Returns: either the mutated target or the original target
- Dependencies:
-
Library¶
fitness weighting functions¶
Fitness weighting functions are used by select_parents()
to weight fitness scores and generate probabilities for selecting a genome to be a parent of a genome in the next generation. The following functions return stock weighting functions, some with configurable parameters. See Selection Strategy for general information.
General Example:
from holland.utils import select_random weighting_function = get_some_weighting_function() breeding_pool = select_breeding_pool(fitness_results, **selection_strategy.get("pool")) # split fitness and genomes into separate lists fitness_scores, genomes = zip(*breeding_pool) weighted_scores = [weighting_function(fitness) for fitness in fitness_scores] weighted_total = sum(weighted_scores) selection_probabilities = [weighted_score / weighted_total for weighted_score in weighted_scores] parents = select_random(genomes, probabilities=selection_probabilities, n=2)
-
holland.library.fitness_weighting_functions.
get_uniform_weighting_function
()¶ Returns a function that returns a constant, regardless of input; see Selection Strategy
Returns: a function that returns a constant
-
holland.library.fitness_weighting_functions.
get_linear_weighting_function
(slope=1)¶ Returns a function that weights its input linearly according to
slope
; see Selection StrategyParameters: slope (int/float) – the multiplier for input Returns: a linear function
-
holland.library.fitness_weighting_functions.
get_polynomial_weighting_function
(power=2)¶ Returns a function that weights its input by raising the input to the
power
specified; see Selection StrategyParameters: power (int/float) – the power to raise the input to Returns: a polynomial function
-
holland.library.fitness_weighting_functions.
get_exponential_weighting_function
(base=2.718281828459045)¶ Returns a function that weights its input by raising the
base
to the power of the input; see Selection StrategyParameters: base (int/float) – the base to raise to the power of the input Returns: a exponential function
-
holland.library.fitness_weighting_functions.
get_logarithmic_weighting_function
(base=2.718281828459045)¶ Returns a function that weights its input getting the logarithm (with specified
base
) of the input; see Selection StrategyParameters: base (int/float) – the base to calculate the logarithm of the input for Returns: a logarithmic function Note
This fitness weighting function will throw an error for fitness scores less than or equal to 0.
-
holland.library.fitness_weighting_functions.
get_reciprocal_weighting_function
()¶ Returns a function that weights its input by raising the input to the -1 power; see Selection Strategy
The reciprocal weighting function is useful in cases where fitness should be minimized as the function results in granting higher selection probabilities to individuals with lower scores
Returns: a function that returns 1/input
Note
This fitness weighting function will throw an error for fitness scores equal to 0.
crossover functions¶
Crossover functions are used by cross_genomes()
to perform crossover. The following functions return stock crossover functions, some with configurable parameters. See Crossover Functions for general information.
General Example:
crossover = get_some_crossover_function() parent_genomes = select_parents(fitness_results) gene_names = parent_genomes[0].keys() offspring = {} for gene_name in gene_names: parent_genes = [pg[gene_name] for pg in parent_genomes] offspring[gene_name] = crossover(parent_genes)
-
holland.library.crossover_functions.
get_uniform_crossover_function
()¶ Returns a function that applies uniform crossover (each gene value is chosen at random from the parent genes); see Crossover Functions
Valid For: any gene type Returns: a function that accepts a list of parent genes and applies uniform crossover to them and returns a new gene
-
holland.library.crossover_functions.
get_point_crossover_function
(n_crossover_points=1)¶ Returns a function that applies point crossover (take gene values from one parent gene at a time until reaching a crossover point, then switch parent genes); see Crossover Functions
Valid For: any list-type gene Parameters: n_crossover_points (int) – number of points at which to switch to the next parent gene (should be at least len(parent_genes) - 1
)Returns: a function that accepts a list of parent genes and applies point crossover Raises: ValueError – if n_crossover_points
is negative- Dependencies:
-
holland.library.crossover_functions.
get_and_crossover_function
()¶ Returns a function that reduces the values of the parent_genes by the logical ‘and’ operation; see Crossover Functions
Valid For: "bool"
and"[bool]"
gene typesReturns: a function that accepts a list of parent genes and applies ‘and’ crossover
-
holland.library.crossover_functions.
get_or_crossover_function
()¶ Returns a function that reduces the values of the parent_genes by the logical ‘or’ operation; see Crossover Functions
Valid For: "bool"
and"[bool]"
gene typesReturns: a function that accepts a list of parent genes and applies ‘or’ crossover
mutation functions¶
Mutation functions are used by probabilistically_apply_mutation()
to apply mutation to a gene value. The following functions return stock mutation functions, some with configurable parameters. See Mutation Functions for general information.
General Example:
import random mutate = get_some_mutation_function() genome = {"gene1": [123.8, 118.2, 103.0], "gene2": [1.5, 3.7, 2.6, 1.9]} mutation_rate = 0.01 mutated_genome = {} for gene_name, gene in genome: mutated_gene = [ mutate(value) if random.random() < mutation_rate else value # apply probabilistically for value in gene ] mutated_genome[gene_name] = mutated_gene
-
holland.library.mutation_functions.
get_flip_mutation_function
()¶ Returns a function that returns the negated value of the input, where the input is a boolean value; see Mutation Functions
Valid For: "bool"
and"[bool]"
gene typesReturns: a function that returns the negated value if its input
-
holland.library.mutation_functions.
get_boundary_mutation_function
(minimum, maximum)¶ Returns a function that pushes a value to either the minimum or maximum allowed value for a gene; see Mutation Functions
Valid For: "int"
,"[int]"
,"float"
, and"[float]"
gene typesParameters: - minimum (int/float) – the minimum allowed value
- maximum (int/float) – the maximum allowed value
Returns: either
minimum
ormaximum
(equally likely)
-
holland.library.mutation_functions.
get_uniform_mutation_function
(minimum, maximum)¶ Returns a function that returns a value drawn from a uniform distribution over the closed interval [minimum, maximum]; see Mutation Functions
Valid For: any gene type
Parameters: - minimum (int/float) – the minimum allowed value
- maximum (int/float) – the maximum allowed value
Returns: a sample from a uniform distribution
-
holland.library.mutation_functions.
get_gaussian_mutation_function
(sigma)¶ Returns a function that returns a value drawn from a gaussian (normal) distribution with mean equal to
value
and standard_deviation equal tosigma
; see Mutation FunctionsValid For: "int"
,"[int]"
,"float"
, and"[float]"
gene typesParameters: sigma (int/float) – standard deviation for the gaussian distribution Returns: a sample from a gaussian distribution
Storage¶
storage manager¶
-
class
holland.storage.
StorageManager
(fitness_storage_options={}, genome_storage_options={})¶ Handles recording fitness statistics and genomes.
Parameters: - fitness_storage_options (dict) – options for storing fitness statistics; see Fitness Storage Options
- genome_storage_options (dict) – options for storing genomes and their fitness scores; see Genome Storage Options
-
update_storage
(generation_num, fitness_results)¶ Updates storage of fitness scores and genomes (with fitness scores) when called; Decisions for whether to record or not are handled by dependencies
Parameters: - generation_num (int) – the generation number of the population that generated the
fitness_results
- fitness_results (list) – the results of a round of evaluation (returned by
evaluate_fitness()
)
Returns: None
- Dependencies:
- generation_num (int) – the generation number of the population that generated the
-
react_to_interruption
(generation_num, fitness_results)¶ Updates storage of genomes (with fitness scores) in the event of an interruption during execution if
genome_storage_options["should_record_on_interrupt"]
is set toTrue
Parameters: - generation_num (int) – the generation number of the population that generated the
fitness_results
- fitness_results (list) – the results of a round of evaluation (returned by
evaluate_fitness()
)
Returns: None
- Dependencies:
- generation_num (int) – the generation number of the population that generated the
-
update_fitness_storage
(generation_num, fitness_results)¶ Updates storage of fitness scores if
fitness_storage_options["should_record_fitness"]
is set toTrue
Parameters: - generation_num (int) – the generation number of the population that generated the
fitness_results
- fitness_results (list) – the results of a round of evaluation (returned by
evaluate_fitness()
)
Returns: None
- Dependencies:
- generation_num (int) – the generation number of the population that generated the
-
update_genome_storage
(generation_num, fitness_results)¶ Updates storage of genomes (with fitness scores) if
genome_storage_options["should_record_genomes"]
is set toTrue
and thegeneration_num
matches the recording frequencyParameters: - generation_num (int) – the generation number of the population that generated the
fitness_results
- fitness_results (list) – the results of a round of evaluation (returned by
evaluate_fitness()
)
Returns: None
- Dependencies:
- generation_num (int) – the generation number of the population that generated the
-
should_record_genomes_now
(current_generation_num)¶ Returns a boolean telling whether genomes should be recorded for the
current_generation_num
or not; ReturnsTrue
ifgenome_storage_options["should_record_genomes"]
is set toTrue
and thegeneration_num
matches the recording frequency, otherwiseFalse
Parameters: generation_num (int) – the generation number of the population that generated the fitness_scores
Returns: a boolean telling whether or not genomes should be recorded
fitness¶
-
holland.storage.fitness.
record_fitness
(generation_num, fitness_scores, **storage_options)¶ Records fitness statistics for a generation to a file and returns fitness statistics
Parameters: - generation_num (int) – the generation number of the population that generated the fitness_scores
- fitness_scores (list) – the fitness scores of the generation
- storage_options (dict) – options for storing statistics, specifically
file_name
,format
, andpath
are relevant; see Fitness Storage Options
Returns: a dictionary of statistics for the fitness scores
- Dependencies:
-
holland.storage.fitness.
format_fitness_statistics
(generation_num, fitness_scores)¶ Generate statistics on fitness scores for a generation
Parameters: - generation_num (int) – the generation number of the population that generated the fitness_scores
- fitness_scores (list) – the fitness scores of the generation
Returns: a dictionary of statistics for the fitness scores
genomes and fitnesses¶
-
holland.storage.genomes_and_fitnesses.
record_genomes_and_fitnesses
(generation_num, fitness_results, **storage_options)¶ Records results of a round of evaluation
Parameters: - generation_num (int) – the generation number of the population that generated the fitness_scores
- fitness_results (list) – the results of a round of evaluation (returned by
evaluate_fitness()
) - storage_options (dict) – options for selecting which results to store and how to store them, specifically
should_add_generation_suffix
,format
,file_name
,path
,top
,mid
,bottom
are relevant; see Genome Storage Options
Returns: None
- Dependencies:
-
holland.storage.genomes_and_fitnesses.
format_genomes_and_fitnesses_for_storage
(generation_num, fitness_results, **storage_options)¶ Formats results of a round of evaluation for storage
Parameters: - generation_num (int) – the generation number of the results
- fitness_results (list) – the sorted results of a round of evaluation (returned by evaluate_fitness)
- storage_options (dict) – options for selecting which results to store, specifically
top
,mid
,bottom
are relevant; see Genome Storage Options
Returns: a dictionary of the form
{"generation": generation_num, "results": selected_results}
Note
For the sake of efficiency, this method expects
fitness_results
to be sorted in order to properly select genomes on the basis of fitness.evaluate_fitness()
returns sorted results.- Dependencies:
utils¶
-
holland.storage.utils.
record
(data, **storage_options)¶ Records data to a file
Parameters: - data (list/dict) – the data to write to the file
- storage_options (dict) – options for writing the data to a file, specifically
format
(options:'json'
,'csv'
),file_name
, andpath
are relevant; see Fitness Storage Options and Genome Storage Options
Returns: None
- Dependencies:
-
holland.storage.utils.
record_to_csv
(data, **storage_options)¶ Writes data to a file CSV format; appends a row to an existing file; a file is created if none exists yet
Parameters: - data (dict) – the data to write to the file (with column names as keys)
- storage_options (dict) – options for writing the data to a file, specifically
file_name
andpath
are relevant; see Fitness Storage Options and Genome Storage Options
Returns: None
Raises: - AssertionError – if storage_options[“file_name”] is not specified
- AssertionError – if storage_options[“path”] is not specified
- ValueError – if not all values are of type int or float
-
holland.storage.utils.
record_to_json
(data, **storage_options)¶ Writes data to a file JSON format; overwrites contents if the file already exists
Parameters: - data (list/dict) – the data to write to the file (must be valid JSON format)
- storage_options (dict) – options for writing the data to a file, specifically
file_name
andpath
are relevant; see Fitness Storage Options and Genome Storage Options
Returns: None
Raises: - AssertionError – if storage_options[“file_name”] is not specified
- AssertionError – if storage_options[“path”] is not specified
Utils¶
utility functions¶
-
holland.utils.utils.
bound_value
(value, minimum=-inf, maximum=inf, to_int=False)¶ Bounds a value between a minimum and maximum
Parameters: - value (int/float) – the value to bound
- minimum (int/float) – the lower bound
- maximum (int/float) – the upper bound
- to_int (bool) – whether or not to cast the result to an int
Returns: the bounded value
-
holland.utils.utils.
select_from
(values, top=0, mid=0, bottom=0, random=0)¶ Selects elements from a (sorted) list without replacement
Parameters: - values (list) – the list of values to select from
- top (int) – number of elements to select from the top (end) of the list
- mid (int) – number of elements to select from the middle of the list
- bottom (int) – number of elements to select from the bottom (start) of the list
- random (int) – number of elements to select randomly from the list
Returns: a list of selected elements
-
holland.utils.utils.
select_random
(choices, probabilities=None, n=1, should_replace=False)¶ Selects random elements from a list
Parameters: - choices (list) – list of elements to select from
- probabilities (list) – list of probabilities for selecting each element in
choices
; if not specified, uniform probability is used - n (int) – number of elements to select from
choices
- should_replace (bool) – specifies if selection should be done with replacement or not
Returns: a list of length
n
of elements selected randomly fromchoices
Raises: - ValueError – if
probabilities
is given butlen(probabilities) != len(choices)
- ValueError – if any element of
probabilities
is negative - ValueError – if
sum(probabilities) > 1
- ValueError – if
should_replace
isFalse
butn > len(choices)
-
holland.utils.utils.
is_numeric_type
(gene_params)¶ Determines if a gene is of a numeric type or not (whether list type or not); e.g. returns
False
if type is"bool"
or"[bool]"
, butTrue
if type is"float"
or"[float]"
Parameters: gene_params (dict) – a dictionary of parameters for a single gene; see Genome Parameters Returns: a boolean indiciating whether the gene is of a numeric type or not
-
holland.utils.utils.
is_list_type
(gene_params)¶ Determines if a gene is of a list type or not; e.g. returns
False
if type is"float"
butTrue
if type is"[float]"
Parameters: gene_params (dict) – a dictionary of parameters for a single gene; see Genome Parameters Returns: a boolean indicating whether the gene is of a list type or not