Why EvoKit?
Operators are Easy to Make
Define only what matters, let the framework automate wht it can.
The stock OneMax evaluator is written just in 3 lines! [1]
class CountBits(Evaluator[BinaryString]):
def evaluate(self, individual: BinaryString) -> tuple[float,]:
return (individual.genome.bit_count(),)
Operators are Interchangeable
Operators of the same type are interchangeable. That is:
All evaluators and variators of the same representation are interchangeable.
All selectors are interchangeable.
All algorithms work with all configurations of compatible operators.
Completely Documented
All public members are documented (see [evokit] for the API documentation).
All private members (except for well-known dunders) are documented. You can find examples like this in the source code:
def _get_arity(fun: Callable[..., Any]
| Expression[Any]
| Symbol
| Any) -> int:
"""Return the arity of an object.
If the argument is callable, return the length of its signature.
Otherwise, return 0.
Does not work with built-in functions and other objects that do not
work with :meth:`.inspect.signature`.
Args:
fun: An object
"""
Well Described
EvoKit describes exactly what it does.
All methods (public or private) have type hints:
def __init__(self: Self,
population: Population[T],
evaluator: Evaluator[T],
selector: Selector[T],
variator: Variator[T]) -> None:
All return values are explained:
def has_fitness(self) -> bool:
"""Return `True` if :attr:`.fitness` is not None.
Otherwise, return `False`.
"""
return self._fitness is not None
All effects are documented:
def reset_fitness(self) -> None:
"""Reset the fitness of the individual.
Effect:
The :attr:`.fitness` of this individual becomes ``None``.
"""
self._fitness = None
All managed attributes are explained:
def step(self: Self, *args: Any, **kwargs: Any) -> None:
"""Advance the population by one generation.
nothing prevents you from firing them inside :meth:`step`.
The :attr:`automatic_events` class attribute reports these
events, like how :attr:`events` reports regular events.
"""
Transparent
Core modules (in core) do not depend on any external module.
Reproducible
All randomness in existing modules come from random and
can be reproduced by setting the same random.seed().