Why EvoKit?

Operators are Easy to Make

When extending a framework, you can just define what matters. The framework takes care of the rest.

Define the OneMax evaluator in 3 lines!

class CountBits(Evaluator[BinaryString]):
    def evaluate(self, s1: BinaryString) -> tuple[float]:
        return (s1.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]).

All private member (except for well-known dunders) are thoroughly described. You can find examples like this in the source code:

def _get_arity(fun: Callable | Expression | 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,
                 population: Population[T],
                 evaluator: Evaluator[T],
                 selector: Selector[T],
                 variator: Variator[T]) -> None:
  • All return values are explained:

    def has_fitness(self) -> bool:
        """Return if the individual has a fitness value.
        """
        return self._fitness is not None
  • All effects are documented:

    def reset_fitness(self) -> None:
        """Reset the fitness of the individual.

        Set the :attr:`.fitness` of the individual to ``None``.

        Effect:
            The `.fitness` of this individual becomes ``None``.
        """
        self._fitness = None
  • All managed attributes are explained:

    def step(self) -> None:
        """Advance the population by one generation.

        Note:
            Do not manually increment :attr:`generation`. This property
            is automatically managed.
        """

Transparent

Core modules (in core) do not depend on any external module.

All randomness come from random and can be reproduced by setting the right random.seed().