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), if storage_options["fitness"] has 'should_record_fitness': True and 'format': 'memory'

Raises:
  • ValueError – if generation_params["n_random"] < 0 or generation_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 or n_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:
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, or random 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 as fitness_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 genome

Parameters: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:

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 Strategy

Parameters: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 Strategy

Parameters: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 Strategy

Parameters: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 Strategy

Parameters: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 types
Returns: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 types
Returns: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 types
Returns: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 types

Parameters:
  • minimum (int/float) – the minimum allowed value
  • maximum (int/float) – the maximum allowed value
Returns:

either minimum or maximum (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 to sigma; see Mutation Functions

Valid For:"int", "[int]", "float", and "[float]" gene types
Parameters: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:
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:
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 to True

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:
update_fitness_storage(generation_num, fitness_results)

Updates storage of fitness scores if fitness_storage_options["should_record_fitness"] is set to True

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:
update_genome_storage(generation_num, fitness_results)

Updates storage of genomes (with fitness scores) if genome_storage_options["should_record_genomes"] is set to True and the generation_num matches the recording frequency

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:
should_record_genomes_now(current_generation_num)

Returns a boolean telling whether genomes should be recorded for the current_generation_num or not; Returns True if genome_storage_options["should_record_genomes"] is set to True and the generation_num matches the recording frequency, otherwise False

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, and path 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, and path 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 and path 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 and path 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 from choices

Raises:
  • ValueError – if probabilities is given but len(probabilities) != len(choices)
  • ValueError – if any element of probabilities is negative
  • ValueError – if sum(probabilities) > 1
  • ValueError – if should_replace is False but n > 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]", but True 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" but True 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