Source code for evol.individual

"""
Individual objects in `evol` are a wrapper around a chromosome.
Internally we work with individuals because that allows us to
separate the fitness calculation from the data structure. This
saves a lot of CPU power.
"""

from random import random
from typing import Any, Callable, Optional
from uuid import uuid4


[docs]class Individual: """Represents an individual in a population. The individual has a chromosome. :param chromosome: The chromosome of the individual. :param fitness: The fitness of the individual, or None. Defaults to None. """ def __init__(self, chromosome: Any, fitness: Optional[float] = None): self.age = 0 self.chromosome = chromosome self.fitness = fitness self.id = f"{str(uuid4())[:6]}" def __repr__(self): return f"<individual id:{self.id} fitness:{self.fitness}>"
[docs] @classmethod def from_dict(cls, data: dict) -> 'Individual': """Load an Individual from a dictionary. :param data: Dictionary containing the keys 'age', 'chromosome', 'fitness' and 'id'. :return: Individual """ result = cls(chromosome=data['chromosome'], fitness=data['fitness']) result.age = data['age'] result.id = data['id'] return result
def __post_evaluate(self, result): self.fitness = result
[docs] def evaluate(self, eval_function: Callable[..., float], lazy: bool = False): """Evaluate the fitness of the individual. :param eval_function: Function that reduces a chromosome to a fitness. :param lazy: If True, do no re-evaluate the fitness if the fitness is known. """ if self.fitness is None or not lazy: self.fitness = eval_function(self.chromosome)
[docs] def mutate(self, mutate_function: Callable[..., Any], probability: float = 1.0, **kwargs): """Mutate the chromosome of the individual. :param mutate_function: Function that accepts a chromosome and returns a mutated chromosome. :param probability: Probability that the individual mutates. The function is only applied in the given fraction of cases. Defaults to 1.0. :param kwargs: Arguments to pass to the mutation function. """ if probability == 1.0 or random() < probability: self.chromosome = mutate_function(self.chromosome, **kwargs) self.fitness = None