Source code for metaheuristic_designer.strategies.classic.GA

"""
Genetic Algorithm strategy.
"""

from __future__ import annotations
from typing import Optional

from ...initializer import Initializer
from ...operator import Operator, NullOperator
from ...survivor_selection_base import SurvivorSelection
from ...parent_selection_base import ParentSelection
from ...operators import CompositeOperator, BranchOperator
from ..static_population import StaticPopulation
from ...schedulable_parameter import SchedulableParameter
from ...utils import check_random_state, RNGLike


[docs] class GA(StaticPopulation): """ Genetic Algorithm. Combines crossover (applied with probability *crossover_prob*) and mutation (applied per individual with probability *mutation_prob*) via a :class:`BranchOperator`. The population size is constant. Parameters ---------- initializer : Initializer Population initializer. mutation_op : Operator Mutation operator (will be applied probabilistically). crossover_op : Operator Crossover operator (applied pairwise). parent_sel : ParentSelection Parent selection method. survivor_sel : SurvivorSelection Survivor selection method. name : str, optional Display name (default ``"GA"``). mutation_prob : float or SchedulableParameter, optional Individual-level probability of mutation (default 0.1). crossover_prob : float or SchedulableParameter, optional Pair-level probability of crossover (default 0.9). If the crossover operator supports it, this value is injected via ``update_kwargs``. random_state : RNGLike, optional Random number generator. **kwargs Forwarded to :class:`StaticPopulation`. """ def __init__( self, initializer: Initializer, mutation_op: Operator, crossover_op: Operator, parent_sel: ParentSelection, survivor_sel: SurvivorSelection, name: str = "GA", mutation_prob: float | SchedulableParameter = 0.1, crossover_prob: float | SchedulableParameter = 0.9, random_state: Optional[RNGLike] = None, **kwargs, ): # We need to do the check earlier since it will be injected into the operators # and we want everything to share the random state if possible. random_state = check_random_state(random_state) prob_mut_op = BranchOperator([mutation_op, NullOperator()], method="Random", p=mutation_prob, random_state=random_state) # Override the crossover probability if possible if hasattr(crossover_op.params, "crossover_prob"): crossover_op.update_kwargs(crossover_prob=crossover_prob) evolve_op = CompositeOperator([crossover_op, prob_mut_op]) super().__init__( initializer, operator=evolve_op, parent_sel=parent_sel, survivor_sel=survivor_sel, name=name, random_state=random_state, **kwargs )