evokit.evolvables package

Subpackages

Submodules

class evokit.evolvables.algorithms.HomogeneousAlgorithm[source]

Bases: Algorithm, ABC, Generic[T]

An algorithm with one population. Exists primarily for typing purposes.

Algorithms that use one homogeneous population should derive this class.

__init__() None[source]
step()
class evokit.evolvables.algorithms.SimpleLinearAlgorithm[source]

Bases: HomogeneousAlgorithm[T]

A very simple evolutionary algorithm.

An evolutionary algorithm that maintains one population and performs one round of selection in each step.

Each step includes the following operations:
  1. evaluate population

  2. event: POST_VARIATION

  3. select from population
    1. update population with result

  4. event: POST_EVALUATION

  5. vary population
    1. update population with result

  6. event: POST_SELECTION

__init__(population: Population[T], evaluator: Evaluator[T], selector: Selector[T], variator: Variator[T]) None[source]
events: list[str] = ['POST_VARIATION', 'POST_EVALUATION', 'POST_SELECTION']

Events that can be reported by this algorithm.

step() None[source]
class evokit.evolvables.algorithms.LinearAlgorithm[source]

Bases: HomogeneousAlgorithm[T]

A general evolutionary algorithm [SIMPLE_GA].

An evolutionary algorithm that maintains one population. Each step includes two rounds of selection.

Each step includes the following operations:
  1. evaluate population

  2. event: POST_PARENT_EVALUATION

  3. select parents from population
    1. update population with result

  4. event: POST_PARENT_SELECTION

  5. vary population

  6. event: POST_VARIATION

  7. evaluate population

  8. event: POST_OFFSPRING_EVALUATION

  9. select survivors from population
    1. update population with result

  10. event: POST_OFFSPRING_SELECTION

[SIMPLE_GA]

Introduction to Evolutionary Computing [2nd ed.], A. E. Eiben and J. E. Smith (2015), Fig 3.1

__init__(population: Population[T], parent_evaluator: Evaluator[T], parent_selector: Selector[T], variator: Variator[T], survivor_evaluator: Evaluator[T], survivor_selector: Selector[T]) None[source]
events: list[str] = ['POST_PARENT_EVALUATION', 'POST_PARENT_SELECTION', 'POST_VARIATION', 'POST_OFFSPRING_EVALUATION', 'POST_OFFSPRING_SELECTION']

Events that can be reported by this algorithm.

step() None[source]
class evokit.evolvables.algorithms.CanonicalGeneticAlgorithm[source]

Bases: HomogeneousAlgorithm[T]

The canonical genetic algorithm [CANON_GA].

An evolutionary algorithm that consecutively apply two variators. In Holland’s foundational algorithm, these are crossover followed by mutation.

Each step includes the following operations:
  1. vary population with variator1

  2. event: POST_VARIATION_1

  3. vary population with variator2

  4. event: POST_VARIATION_2

  5. evaluate population

  6. event: POST_EVALUATION

  7. select survivors from population
    1. update population with result

  8. event: POST_SELECTION

[CANON_GA]

Adaptation in Natural and Artificial Systems, Holland (1975)

__init__(population: Population[T], evaluator: Evaluator[T], selector: Selector[T], variator1: Variator[T], variator2: Variator[T]) None[source]
events: list[str] = ['POST_VARIATION_1', 'POST_VARIATION_2', 'POST_EVALUATION', 'POST_SELECTION']

Events that can be reported by this algorithm.

step() None[source]
class evokit.evolvables.bitstring.BitString[source]

Bases: Individual[int]

A string of bits.

Tutorial: Getting Started with OneMax.

__init__(value: int, size: int) None[source]
Parameters:
  • value – Integer whose binary representation is used.

  • size – Length of the binary string

static random(size: int) BitString[source]

Return a random binary string.

Each item in the returned value may be either 1 or 0 with equal probability.

Parameters:

size – Size of the generated binary string.

copy() Self[source]

Return a copy of this object.

Operations performed on the returned value do not affect this object.

get(pos: int) Literal[1] | Literal[0][source]

Return the bit at position pos.

Parameters:

pos – Position of the returned bit value.

Raises:

IndexError – If pos is out of range.`

set(pos: int) None[source]

Set the bit at position pos to 0.

Parameters:

pos – Position of the bit value to set.

Effect:

Change genome.

Raises:

IndexError – If pos is out of range.`

clear(pos: int) None[source]

Set the bit at position pos to 0.

Parameters:

pos – Position of the bit value to clear.

Effect:

Change genome.

Raises:

IndexError – If pos is out of range.`

flip(pos: int) None[source]

Flip the bit at position pos.

Parameters:

pos – Position of the bit value to flip.

Effect:

Change genome.

Raises:

IndexError – If pos is outside of range.

to_bit_list() list[int][source]

Return a list of bits that represents the binary value of genome.

classmethod from_bit_list(bit_list: list[int]) BitString[source]

Return a BitString whose genome is the value of bit_list parsed as binary.

Parameters:

bit_list – A string of values 0 or 1.

Warning

For efficiency, this method does not check if each item in bit_list is one of 1 and 0.

Effectively, even numbers will be treated as 1 s whereas odd numbers will be treated as 0 s.

class evokit.evolvables.bitstring.CountBits[source]

Bases: Evaluator[BitString]

Count the number of 1 s.

Evaluator for BitString. For each 1 in the binary string, incur a reward of 1.

evaluate(individual: BitString) tuple[float][source]
class evokit.evolvables.bitstring.MutateBits[source]

Bases: Variator[BitString]

Randomly flip each bit in the parent.

1-to-1 variator for BitString. At each bit in the parent, flip it with probability mutation_rate`.

..note::

This operator can use Numpy (if installed) to speed up bit flips by orders of magnitude.

__init__(mutation_rate: float, *, processes: int | ProcessPoolExecutor | None = None, share_self: bool = False)[source]
Parameters:

mutation_rate – Probability to flip each bit in the parent.

Raises:

ValueError – If mutation_rate is not in range [0,1].

vary(parents: Sequence[BitString]) tuple[BitString, ...][source]
class evokit.evolvables.bitstring.OnePointCrossover[source]

Bases: Variator[BitString]

Split and recombine parents.

2-to-1 variator for BitString. Split parents at position k, then interleave the segments.

__init__(crossover_probability: float)[source]
Parameters:

crossover_probability – Probability that crossover is performed.

vary(parents: Sequence[BitString]) tuple[BitString, ...][source]
evokit.evolvables.bitstring.trial_run() list[BitString][source]
class evokit.evolvables.gp.Expression[source]

Bases: Generic[T]

A node in an expression tree.

Recursive data structure that implements program trees. An Expression is also a Callable that only accepts arguments passed by position.

The attribute value is the value of this node.

__init__(arity: int, value: T | Callable[..., T] | Symbol, children: list[Expression[T]], factory: ExpressionFactory[T] | None = None)[source]
arity: int

Arity of the expression node.

value: T | Callable[[...], T] | Symbol

Value of the expression node.

children

Children of the expression node.

property factory: ExpressionFactory[T]

The ExpressionFactory, if any, that built this object.

The ExpressionFactory maintains hyperparameters that instruct the construction of this object.

copy() Self[source]

Return a deep copy.

Call the copy(self, ...) method on value, each item in children, and value (if value implements a method named copy). Use the results to create a new Expression

nodes() tuple[Expression[T], ...][source]

Return a flat list view of all nodes and subnodes.

Note that operations performed on items in the returned list affect the original objects.

class evokit.evolvables.gp.Symbol[source]

Bases: object

Dummy object used by ExpressionFactory. This object represents a positional argument, as opposed to, for example, a constant value or an expression that evaluates to a value.

__init__(pos: int)[source]
pos: int
class evokit.evolvables.gp.ExpressionFactory[source]

Bases: Generic[T]

Factory class for Expression.

Build Expression instances with supplied hyperparameters. Register the factory itself with each expression built by setting Expression.factory.

Please see evolvables.funcs for a set of primitives, or define custom functions.

Note

If arity = 0, then primitives must include at least one literal. Otherwise, the tree cannot be built, as no terminal node can be drawn.

See:

Expression.factory

__init__(primitives: tuple[T | Callable[..., T], ...], arity: int)[source]
Parameters:
  • primitives – instructions and terminals that occupy nodes of the expression tree. Listing a primitive more than once increases its chance of being selected.

  • arity – Arity of constructed Expression instances.

Raises:
  • ValueError if arity=0 and primitives does not contain

  • nullary values. The tree cannot be built without terminals.

build(node_budget: int, layer_budget: int, nullary_ratio: float | None = None) Expression[T][source]

Build an expression tree to specifications.

The parameters node_budget and layer_budget are no constraints. Rather, if the tree exceeds these budgets, then only nullary values can be drawn. This ensures that the tree does not exceed these budgets by too much.

Costs are incurred after a batch nodes are drawn.

Parameters:
  • node_budget – Total number of nodes in the tree.

  • layer_budget – Depth of the tree.

  • nullary_ratio – Probability of drawing a nullary node.

Raises:

ValueError` if nullary_ratio is not in range [0...1]

draw_primitive(nullary_ratio: float | None = None, free_draw: bool = False) T | Callable[..., T] | Symbol[source]

Return an item from primitive_pool

Parameters:
  • nullary_ratio – Probability of drawing terminals. If set, non-terminals are drawn with probability (1-nullary_ratio).

  • free_draw – if True, then the call does not affect or respect constraints on node counts. For example, it can still draw non-terminal nodes, even while exceeding node count and depth constraints.

primitive_by_arity(arity: int) T | Callable[..., T] | Symbol[source]

Draw a instruction or terminal of the given arity.

If no primitive of the given arity exists, return an empty list.

class evokit.evolvables.gp.Program[source]

Bases: Individual[Expression[T]]

A tree-based genetic program.

Tutorial: Symbolic Regression with Genetic Programming.

__init__(expr: Expression[T])[source]
copy() Self[source]
class evokit.evolvables.gp.ProgramFactory[source]

Bases: Generic[T]

Convenience factory class for Program.

Contain an ExpressionFactory instance. Delete storage of hyperparameters and ProgramFactory.build() to the internal ExpressionFactory.

__init__(primitives: tuple[T | Callable[..., T], ...], arity: int)[source]
build(node_budget: int, layer_budget: int, nullary_ratio: float | None = None) Program[T][source]
class evokit.evolvables.gp.CrossoverSubtree[source]

Bases: Variator[Program[T]]

Crossover operator that randomly exchange subtrees of parents.

Select an internal node from each parent. Then, select one child of each internal node and exchange these child nodes. Doing so also exchanges subtrees that begin at these child nodes.

__init__(shuffle: bool = False)[source]
Parameters:

shuffle – If True: collect all child nodes of both internal nodes into one list, shuffle that list, then assign items back to respective parents.

vary(parents: Sequence[Program[T]]) tuple[Program[T], ...][source]
class evokit.evolvables.gp.MutateNode[source]

Bases: Variator[Program[T]]

Mutator that changes the primitive in a uniformly random node to a uniformly selected primitive of the same arity.

__init__() None[source]
vary(parents: Sequence[Program[T]]) tuple[Program[T], ...][source]
Parameters:

parents – Collection where the 0:sup:th item is the parent.

:raises ValueError` if the parent’s Program.genome: :raises does not have :attr:`Expression.factory set.:

class evokit.evolvables.gp.MutateSubtree[source]

Bases: Variator[Program[T]]

Mutation operator that randomly mutates subtrees.

Uniformly select an internal node, then uniformly select a child of that node. Replace that child with a subtree, constructed by calling ExpressionFactory.build() of the associated ExpressionFactory found in Expression.factory.

__init__(node_budget: int, layer_budget: int, nullary_ratio: float | None = None) None[source]
vary(parents: Sequence[Program[T]]) tuple[Program[T], ...][source]
class evokit.evolvables.gp.SymbolicEvaluator[source]

Bases: Evaluator[Program[float]]

Evaluator for symbolic regression.

Compare the output of a program tree against a given objective function, over a fixed set of points. Assign higher fitness to programs whose output is closer to that of the objective function.

__init__(objective: Callable[..., float], support: tuple[tuple[float, ...], ...])[source]
Parameters:
  • objective – Function to compare against.

  • support – Collection of points on which the program is compared against objective.

Raises:

TypeError – if the first item in support does not match the arity of objective.

evaluate(individual: Program[float]) tuple[float][source]
class evokit.evolvables.gp.PenaliseNodeCount[source]

Bases: Evaluator[Program[float]]

Evaluator that favours smaller program trees.

For each node in the given program tree, incur a penalty of coefficient.

__init__(coefficient: float)[source]
Parameters:
  • coefficient – penalty coefficient for each node in the

  • tree. (program)

evaluate(individual: Program[float]) tuple[float][source]
evokit.evolvables.gp_visualiser.ident = 0

Global counter of the number of dispatched identifiers.

evokit.evolvables.gp_visualiser.p2dot(gp: ~evokit.evolvables.gp.Program[~typing.Any], dispatcher: ~typing.Callable[[], str] = <function _dispatch_ident>) Digraph[source]

Visualise a tree-based genetic program.

Return a graphviz.Digraph that represents the given tree-based genetic program.

Parameters:
  • gp – Genetic program to visualise.

  • dispatcherCallable that should return a unique identifier when called.

evokit.evolvables.prefabs.make_onemax(pop_size: int, ind_size: int, mutate_p: float, variator_processes: int | ProcessPoolExecutor | None = None, evaluator_processes: int | ProcessPoolExecutor | None = None, max_parents=5) SimpleLinearAlgorithm[BitString][source]

Create a simple elitist onemax algorithm that tracks 5 generations of parents.

Useful for playing around with features.

class evokit.evolvables.selectors.NullSelector[source]

Bases: Selector[D]

Selector that does nothing.

__init__()[source]
select_population(from_population: Population[D]) Population[D][source]

Return all items in from_population in new population.

class evokit.evolvables.selectors.TruncationSelector[source]

Bases: Selector[D]

Simple selector that select individuals with highest fitness.

__init__(budget: int)[source]
select_population(from_population: Population[D]) Population[D][source]
class evokit.evolvables.selectors.TournamentSelector[source]

Bases: Selector[D]

Tournament selector:

  1. From the population, select uniform sample of size bracket_size.

  2. Iterate through the sample, stop when a selection is made. At index i, select that item with probability p * (1- p)^i (where p is p). If no selection is made when reaching the end of the sample, select the last item.

  3. Repeat until budget items are selected.

__init__(budget: int, bracket_size: int = 2, p: float = 1)[source]
bracket_size: int

Size of a tournament bracket.

p: float

Selection probability.

select(from_pool: Sequence[D]) tuple[D][source]

Tournament selection.

Select a uniform sample, then select the best member in that sample.

evokit.evolvables.selectors.Elitist(sel: Selector[D]) Selector[D][source]

Decorator that adds elitism to a selector.

Wrap sel.select_population, so that the selector becomes elitist.

An elitist selector retains (and updates) the highest-fitness individual encountered so far, and always deposits that individual to the selected pool.

Parameters:

sel – A selector.

Module contents