evokit.evolvables package

Submodules

evokit.evolvables.algorithms module

Inheritance diagram of evokit.evolvables.algorithms

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']
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']
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']
step() None[source]

evokit.evolvables.binstring module

Inheritance diagram of evokit.evolvables.binstring

class evokit.evolvables.binstring.BinaryString[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) BinaryString[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]) BinaryString[source]

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

Parameters:

bit_list – A string of values 0 or 1.

Warns:
  • For efficiency, this method does not check if each item in

  • :arg:`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.binstring.CountBits[source]

Bases: Evaluator[BinaryString]

Count the number of 1 s.

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

evaluate(individual: BinaryString) tuple[float][source]
class evokit.evolvables.binstring.MutateBits[source]

Bases: Variator[BinaryString]

Randomly flip each bit in the parent.

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

__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[BinaryString]) tuple[BinaryString, ...][source]
class evokit.evolvables.binstring.OnePointCrossover[source]

Bases: Variator[BinaryString]

Split and recombine parents.

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

__init__(crossover_probability: float)[source]
Arg:

crossover_probability: Probability that crossover is performed.

vary(parents: Sequence[BinaryString]) tuple[BinaryString, ...][source]
evokit.evolvables.binstring.trial_run() list[BinaryString][source]

evokit.evolvables.funcs module

This module contains a small set of protected functions.

evokit.evolvables.funcs.sin(x: float) float[source]
evokit.evolvables.funcs.cos(x: float) float[source]
evokit.evolvables.funcs.tan(x: float) float[source]
evokit.evolvables.funcs.add(x: float, y: float) float[source]
evokit.evolvables.funcs.sub(x: float, y: float) float[source]
evokit.evolvables.funcs.mul(x: float, y: float) float[source]
evokit.evolvables.funcs.div(x: float, y: float) float[source]
evokit.evolvables.funcs.avg(x: float, y: float) float[source]
evokit.evolvables.funcs.lim(x: float, max_val: float, min_val: float) float[source]

evokit.evolvables.gp module

Inheritance diagram of evokit.evolvables.gp

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

__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.

__call__(*args: T) T[source]

Evaluate the expression tree with arguments.

Recursively evaluate expression nodes in children. Then, apply value to the results, in the same order as the children they are resolved from.

Parameters:

*args – Arguments to the program.

copy() Self[source]

Return a deep copy.

Call the python: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.

See:

??? TODO

__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

  • its (expression tree. Listing a primitive more than once increases)

  • selected. (chance of being)

  • 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 :class`ExpressionFactory` instance. Delete storage of hyperparameters and ProgramFactory.build() to the internal :class`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

  • list (shuffle that)

  • list

  • assign (then)

  • parents. (items back to respective)

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 0th 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 that

  • support – collection of points on which the program

  • objective. (is compared against)

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 module

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

  • called. (identifier when)

evokit.evolvables.lgp module

Inheritance diagram of evokit.evolvables.lgp

class evokit.evolvables.lgp.Instruction[source]

Bases: object

class evokit.evolvables.lgp.StructureType[source]

Bases: ABC

Base class for all structure scopes.

Control structures consist of a StructureType and a StructureScope. The StructureType decides how the structure is executed: for example, whether it is an if statement (If), a for loop (For), or a while loop (While).

Derive this class to create custom structure scopes.

abstract __call__(lgp: LinearProgram, instructions: Sequence[Instruction]) None[source]

Invoke instructions in the context of a linear program.

Parameters:
  • lgp – Context of execution.

  • instructions – Instructions to execute.

class evokit.evolvables.lgp.StructureScope[source]

Bases: ABC, Instruction

Base class for all structure scopes.

Control structures consist of a StructureType and a StructureScope. The StructureScope decides how many lines following the current line become part of the structure.

Derive this class to create custom structure types.

abstract __init__(stype: StructureType, *args: Any, **kwargs: Any) None[source]
Parameters:

stype – Type of the control structure.

class evokit.evolvables.lgp.StructOverLines[source]

Bases: StructureScope

Control structure that spans multiple lines.

__init__(stype: StructureType, line_count: int) None[source]
Parameters:
  • stype – Type of the control structure.

  • line_count – Number of lines that the control structure spans.

class evokit.evolvables.lgp.StructUntilLabel[source]

Bases: StructureScope

Control structure that extends to the given label.

__init__(stype: StructureType, label: str)[source]
Parameters:
  • stype – Type of the control structure.

  • label – Text of label that terminates this control structure.

class evokit.evolvables.lgp.StructNextLine[source]

Bases: StructureScope

Control structure that spans one line.

__init__(stype: StructureType)[source]
Parameters:

stype – Type of the control structure.

class evokit.evolvables.lgp.Label[source]

Bases: object

Text label.

Use with StructUntilLabel.

__init__(label: str)[source]
Parameters:

label – Text of the label.

class evokit.evolvables.lgp.For[source]

Bases: StructureType

Simple “for” loop.

A control structure with this type repeats its body for count times.

__init__(count: int)[source]
class evokit.evolvables.lgp.While[source]

Bases: StructureType

While loop.

A control structure with this type repeats its body until conditional is satisfied.

Warning

This control structure may execute indefinitely. To prevent this, the class variable loop_cap imposes a bound to how many times a while loop may be repeated for.

loop_cap = 20

Maximum number of iterations a While loop can run for.

__init__(conditional: Condition)[source]
Arg:

conditional: Condition that, if satisfied, ends the structures.

class evokit.evolvables.lgp.If[source]

Bases: StructureType

Structure with conditional execution.

A control structure with this type executes once if conditional is satisfied. Otherwise, the structure is skipped and does nothing.

__init__(conditional: Condition)[source]
class evokit.evolvables.lgp.ValueRange[source]

Bases: object

ValueRange(min: ‘float’, max: ‘float’)

min: float
max: float
__init__(min: float, max: float) None
class evokit.evolvables.lgp.StateVectorType[source]

Bases: Enum

Type of a state vector.

A linear program stores three state vectors: the input vector LinearProgram.inputs, the mutable register LinearProgram.registers, and the constant register LinearProgram.constants,

input = 1
register = 2
constant = 3
evokit.evolvables.lgp.CellSpecifier

Tuple that locates an item in a state vector. The first item (StateVectorType) specifies the state vector, then

the second item (int) gives the index.

alias of tuple[StateVectorType, Annotated[int]]

class evokit.evolvables.lgp.Operation[source]

Bases: Instruction

Algebraic operation.

Call function with args as arguments. Assign the result to the register at position target.

The argument operands can index constants and registers. Registers start at index 0; constants are represented as negative numbers starting at index -1. See LinearProgram for the source of this behaviour.

__init__(function: Callable[[...], float], target: int, operands: tuple[tuple[StateVectorType, int], ...])[source]
Parameters:
  • function – Function to apply to operands.

  • target – Register to deposit the result to.

  • operands – Arguments to function.

class evokit.evolvables.lgp.Condition[source]

Bases: object

Base class for predicates, or conditions.

Conditions are used by conditional control structures, such as If and While.

__init__(function: Callable[[...], bool], args: tuple[int, ...])[source]
Parameters:
  • function – TODO

  • args – TODO

class evokit.evolvables.lgp.LinearProgram[source]

Bases: object

Context for executing linear programs.

A LinearProgram stores states (such as registers and constants) of the program.

__init__(registers: Iterable[float], constants: Iterable[float], inputs: Iterable[float])[source]
Parameters:
  • coarity – Size of the output vector, taken from the end of the register vector.

  • inputs – Input registers.

  • input_can_change – If True, then append inputs to the register vector. Otherwise, append inputs to the constant vector.

  • initialiser – Initialiser for the register vector. Can be one of: * a number, which populates each register; * a sequence of numbers, which is converted to the register; or * a nullary function, whose return value populates each register.

  • reg_length – Length of the register vector. If initialiser is a sequence, then its length must match s.

  • constants – The constant vector.

Note

Both constants and registers are indexed by integers.

  • Indices for registers begin at 0. Examples: 0, 1, 2, …

  • Indices for constants begin at -1. Examples: -1, -2, -3, …

registers: ndarray[Any, dtype[float64]]

The register vector stores mutable state variables. Set with set_register().

constants: ndarray[Any, dtype[float64]]

The constant vector stores immutable state variables. Set with set_constants().

set_registers(registers: Iterable[float]) None[source]

Update the register vector with registers.

set_constants(constants: Iterable[float]) None[source]

Update the constant vector with constants.

set_inputs(inputs: Iterable[float]) None[source]

Update the input vector with inputs.

get_state_vector(celltype: StateVectorType) ndarray[Any, dtype[float64]][source]

Return the state vector specified by cellspec.

run(instructions: Sequence[Instruction]) None[source]

Execute instructions in this context.

Effect:

Instructions, for example Operation s, may alter the state of this context.

check_condition(cond: Condition) bool[source]

Check if cond is satisfied in the current context.

run_instruction(instruction: Instruction, instructions: Sequence[Instruction], pos: int) int[source]

Execute an instruction.

Execute the instruction instruction in sequence instructions at position pos.

Return the number of lines advanced as a result. Running a single operation advances the execution pointer by 1; running control structures may skip more lines.

Arg:

instruction: Instruction to run. instructions: Sequence of instruction to run instruction in. pos: Position of current execution pointer.

evokit.evolvables.selectors module

Inheritance diagram of evokit.evolvables.selectors

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\). 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]
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.

Retain and update the highest-fitness individual encountered so far. Each time the selector is called, append that individual to the end of the output population.

Modify select_population of sel to use elitism. If sel already overrides select_population, that implementation is destroyed.

Parameters:

sel – A selector

Returns:

A selector

Module contents