evokit.core package

Subpackages

Submodules

class evokit.core.algorithm.Algorithm[source]

Bases: ABC

Base class for all evolutionary algorithms.

Derive this class to create custom algorithms.

Tutorial: Making a Custom Algorithm.

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

Subclasses should override this method.

Initialise the state of an algorithm, including operators, the initial population(s), truncation strategy, and other parameters associated with the learning process as a whole.

generation: int

Number of already elapsed generations.

watchers: list[Watcher[Any, Any]]

Registered Watchers.

events: list[str] = []

Events that can be reported by this algorithm.

automatic_events: tuple[str, ...] = ('POST_STEP',)

Events that are automatically reported by this algorithm.

abstract step(*args: Any, **kwargs: Any) None[source]

Advance the population by one generation.

Subclasses should override this method. Use operators to update the population (or populations). Call update() to fire events for data collection mechanisms such as Watcher.

Note

After this method is called, but before control is returned to the caller, two things happen automatically:

  1. The generation of the algorithm increments by 1.

  2. The algorithm fires an POST_STEP event to all attached watchers. For more on events and watchers, see Watcher.

register(*watchers: Watcher[Any, Any]) None[source]

Attach an Watcher to this algorithm.

Parameters:

watcher – The watcher to attach.

update(event: str) None[source]

Report an event to all attached Watchers in watchers.

If the event is not in events, raise an exception.

Parameters:

event – The event to report.

Raises:

ValueError – if an reported event is not declared in events and is not an automatically reported event in automatic_events.

class evokit.core.evaluator.Evaluator[source]

Bases: ABC, Generic[D]

Base class for all evaluators.

Derive this class to create custom evaluators.

Tutorial: Getting Started with OneMax.

__init__(*args, processes: int | ProcessPoolExecutor | None = None, share_self: bool = False, **kwargs) None[source]
Parameters:
retain_fitness: bool

If this evaluator should re-evaluate an Individual whose fitness is already set.

abstract evaluate(individual: D, *args: Any, **kwargs: Any) tuple[float, ...][source]

Evaluation strategy. Return the fitness of an individual.

Subclasses should override this method.

Note

“Better” individuals should have higher fitness.

Selector should prefer individuals with higher fitness.

Parameters:

individual – The individual to evaluate.

evaluate_population(pop: Population[D], *args: Any, **kwargs: Any) None[source]

Context of evaluate().

Iterate individuals in a population. For each individual, compute its fitness with evaluate(), then assign that value to its Individual.fitness.

A subclass may override this method to implement behaviours that require access to the entire population.

Effect:

For each item in pop, set its Individual.fitness.

Note

Overrides of this method must never return a value. It does its work through effects.

class evokit.core.population.Individual[source]

Bases: ABC, Generic[R]

Base class for all individuals.

Derive this class to create custom representations.

The individual stores the encoding (genome) and fitness (fitness) of a representation.

The individual can carry information other than the genotype, such as a fitness, parents, and strategy parameter(s).

Note

Implementation should store the genotype in genome.

Tutorial: Getting Started with OneMax.

abstract __init__() None[source]
parents: tuple[Self, ...] | None

Parents of the individual, registered with inherit().

genome: R

Genotype of the individual.

can_copy_fitness: bool

If True, copy() copies fitness. Default is True.

can_copy_parents: bool

If True, copy() copies parents. Default is True.

property fitness: tuple[float, ...]

Fitness of an individual.

Writing to this property changes the fitness of the individual. If this individual has yet to be assigned a fitness, reading from this property raises an exception.

To determine if the individual has a fitness, call has_fitness().

Returns:

Fitness of the individual

Warning

If the current fitness is None, return (nan,). This may happen when, for example, an offspring has just been produced.

reset_fitness() None[source]

Reset the fitness of the individual.

Effect:

The fitness of this individual becomes None.

has_fitness() bool[source]

Return True if fitness is not None. Otherwise, return False.

abstract copy() Self[source]

Return an identical copy of the individual.

Subclasses should override this method.

Operations on in this individual should not affect the new individual. In addition to duplicating genome, the implementation should decide whether to retain other fields.

Note

Ensure that changes made to the returned value do not affect the original value.

Two fields fitness and parents are copied automatically. To override this behaviour, change should_copy_fitness and should_copy_parents.

archive() Self[source]

Return an identical copy of the individual. Same as copy(), except that this method also copies all parents, direct or indirect.

Cost-wise, this method calls copy() once for everything found in this individual’s lineage tree.

Good for keeping lineage intact for older individuals.

set_parents(parents: tuple[Self, ...], max_parents: int)[source]

Register parent as the parent to self.

Also unlink the max_parentsth Individual.parent, if one exists, of this individual. Consequently, the parent of an individual is unlinked if that individual ever becomes first in a long chain of parents.

This approach is not perfect, but does well to save memory. The alternative is to preserve the parent of an individual if it is part of a short chain of parents.

expunge_parents() None[source]

Reset parents.

Effect:

Set parents to None.

property uid: int

Unique identifier of this individual. Useful for tracking identity when one is copied or moves out of memory.

class evokit.core.population.Population[source]

Bases: UserList[D], Generic[D]

A flat collection of individuals.

__init__(initlist: Sequence[D] | None | Iterable[D] = None)[source]
Parameters:

initlist – If provided, an iterable of initial members.

copy() Self[source]

Return an independent population.

Changes made to items in the new population should not affect items in this population. This behaviour depends on correct implementation of Individual.copy() in each item.

Call Individual.copy() for each Individual in this population. Collect the results, then create a new population with these values.

archive() Self[source]

Returns a population wherein each individual is obtained by calling Individual.archive().

Also preserves the Individual.uid, so that the individual’s identity remains.

Warning

With a population of size N, assuming that the variator tracks P generations of parents and each individual is produced from F parents, calling this method will call Individual.copy() a total of N\times P \times F times. Be very careful.

reset_fitness() None[source]

Remove fitness values of all Individuals in the population.

Effect:

For each item in this population, set its Individual.fitness to None.

best() D[source]

Return the highest-fitness individual in this population.

evokit.core.population.save(popi: Population | Individual, file_path: str | Path) None[source]

Produce an Individual.archive() of popi, pickle it with dill, then dump the result to file_path.

Preserves, among other things, Individual.uid.

Effect:

The file file_path is created or overwritten.

evokit.core.population.load(file_path: str | Path) Individual | Population[source]

Load either an individual or a population from file_path. Return the result.

class evokit.core.selector.Selector[source]

Bases: ABC, Generic[D]

Base class for all selectors.

Derive this class to create custom selectors.

Tutorial: Making a Custom Selector.

__init__(budget: int, *args: Any, **kwargs: Any)[source]
Parameters:

budget – Number of individuals to select.

Note

Implementations that select a variable number of individuals may ignore budget.

budget

Declared size of the output population.

select_population(from_population: Population[D], *args: Any, **kwargs: Any) Population[D][source]

Select from a population to a population.

The default implementation calls select() on from_population and collects the results.

All subclasses should override either this method or select(). Consider overriding this method if selection requires information about the whole population. Example: fitness proportionate selection.

Parameters:

from_population – Population to select from.

Warning

The default implementation calls select() as long as the number of selected individuals is less than budget.

As such, if select() can return multiple individuals, then the last call may return more individuals than what the budget permits.

select(from_pool: Sequence[D], *args: Any, **kwargs: Any) tuple[D, ...][source]

Select individuals from a sequence of individuals.

All subclasses should override either this method or select_population().

Parameters:

from_pool – Tuple of individuals to select from.

Note

Each item in the returned tuple must be in from_pool.

The selector should treat higher fitness as “better”. Assume that Evaluators assign higher fitness to better individuals.

Raises:

NotImplementedError – If the subclass does not override this method.

class evokit.core.variator.Variator[source]

Bases: ABC, Generic[D]

Base class for all selectors.

Derive this class to create custom selectors.

Tutorial: Getting Started with OneMax.

__init__(*args: Any, processes: int | ProcessPoolExecutor | None = None, share_self: bool = False, **kwargs: Any) None[source]

See Variator for parameters processes and share_self.

arity: int | None

Size of input to vary().

processes

If attributes of this object will be shared when multiprocessing. See __init__().

abstract vary(parents: Sequence[D], *args: Any, **kwargs: Any) tuple[D, ...][source]

Apply the variator to a tuple of parents

Produce a tuple of individuals from a sequence of individuals.

The length of .parents is at most arity.

vary_population(population: Population[D], *args: Any, **kwargs: Any) Population[D][source]

Vary the population.

The default implementation separates population into groups of size .arity, call .vary with each group as argument, then collect and returns the result.

Parameters:

population – Population to vary.

Note

The default implementation calls Individual.reset_fitness() on each offspring to clear its fitness. Any implementation that overrides this method should do the same.

class evokit.core.variator.NullVariator[source]

Bases: Variator[D]

Variator that does not change anything

__init__() None[source]
vary(parents: Sequence[D]) tuple[D, ...][source]

Module contents

Export modules from core.