.. _api-ref-intro: Welcome to the Metaheuristic Designer API ========================================= The library is built around a **layered architecture**. At the bottom you find abstract interfaces (the “Base Classes” below) that define the contracts for every optimisation component. On top of them sit concrete implementations: pre-built initializers, operators, encodings, selection schemes, and full search strategies. An :class:`Algorithm` object glues everything together and runs the optimisation loop. If you want to **jump straight into code**, take a look at the :doc:`Quick Start ` or follow the :doc:`Algorithm Configuration ` guide – they show how to assemble a complete optimiser in a few lines. For plotting your results, see the :doc:`Plotting Tutorial `. Ready‑to‑run algorithms are provided by the :doc:`Simple API ` page. Base Classes ------------ These are the interfaces from which to inherit to implement a new component for any optimization algorithm. .. csv-table:: :header: "Module name", "Description" ":py:class:`SchedulableParameter`", "Prototype of a parameter that changes in value as iterations go on." ":py:class:`ParametrizableMixin`", "Mixin used by interfaces to hold schedulable parameters." ":py:class:`ObjectiveFunc`", "Abstract objective function with built‑in fitness conversion." ":py:class:`ConstraintHandler`", "Prototype of a constraint handler class." ":py:class:`Initializer`", "Prototype of a population initializer." ":py:class:`Encoding`", "Prototype of an encoding and decoding genotypes of the population." ":py:class:`ParentSelection`", "Prototype of a parent selection method." ":py:class:`SurvivorSelection`", "Prototype of a survivor selection method." ":py:class:`Operator`", "Prototype of an operator on individuals." ":py:class:`SearchStrategy`", "Prototype of a search strategy applied each generation." ":py:class:`Algorithm`", "Prototype of a full optimization algorithm." Almost every interface works with the :py:class:`Population` class internally. Lambda Implementations ---------------------- Classes that allow implementing optimization modules with a lambda function, avoiding the need to inherit from a base class. .. csv-table:: :header: "Module name", "Description" ":py:class:`ObjectiveFromLambda`", "Objective function from a function." ":py:class:`ConstraintHandlerFromLambda`", "Constraint Handler from a function." ":py:class:`InitializerFromLambda`", "Population initializer from a function." ":py:class:`EncodingFromLambda`", "Encoding from an encoding function and a decoding function." ":py:class:`ParentSelectionFromLambda`", "Parent selection from a function." ":py:class:`SurvivorSelectionFromLambda`", "Survivor selection from a function." ":py:class:`OperatorFromLambda`", "Operator from a function." ":py:class:`SearchStrategyFromLambda`", "Full step of the algorithm defined componentwise by functions." For a complete walk‑through showing how to use these classes and the registration functions, see :doc:`Custom Components `. Extended Encoding Classes -------------------------- When the genotype vector encodes more information than just the solution – such as a speed vector for PSO or adaptive algorithm parameters – you need these interfaces to handle the extra data. Note that concrete implementations for specific algorithms (e.g. PSO) already exist. .. csv-table:: :header: "Module name", "Description" ":py:class:`~metaheuristic_designer.encodings.parameter_extending_encoding.ParameterExtendingEncoding`", "Encoding that splits the vector into a solution and a dictionary with the necessary extra data." ":py:class:`~metaheuristic_designer.constraint_handlers.extended_constraint.ExtendedConstraintHandler`", "Constraint handler that treats the solution and the extra data separately." ":py:class:`~metaheuristic_designer.initializers.extended_initializer.ExtendedInitializer`", "Initializer that handles the solution and extra data with different distributions." ":py:class:`~metaheuristic_designer.operators.extended_operator.ExtendedOperator`", "Operator that applies different operations to the solution and the extra data." Parameter Schedules -------------------- Many numerical parameters can be made schedulable by passing a :py:class:`~metaheuristic_designer.SchedulableParameter` subclass instead of a constant. The available schedules are: .. csv-table:: :header: "Module name", "Description" ":py:class:`parameter_schedules.LinearSchedule`", "Changes the value linearly between two values." ":py:class:`parameter_schedules.LogisticSchedule`", "Sigmoid-shaped transition between two values." ":py:class:`parameter_schedules.ThresholdSchedule`", "Keeps the initial value until progress crosses a threshold, then switches to the final value." ":py:class:`parameter_schedules.StepSchedule`", "Discrete steps defined by a list of (progress, value) pairs." ":py:class:`parameter_schedules.RandomSchedule`", "Randomly picks a value between two bounds at each step." All schedules depend on the algorithm's **progress**, a number between 0 and 1, to decide parameter values. Initializers ------------ Implemented population initializers: .. csv-table:: :header: "Module name", "Description" ":py:class:`initializers.UniformInitializer`", "Initializer that uses a uniform distribution." ":py:class:`initializers.GaussianInitializer`", "Initializer that uses a Gaussian distribution." ":py:class:`initializers.ExponentialInitializer`", "Initializer that uses an exponential distribution." ":py:class:`initializers.DirectInitializer`", "Initializer with a predefined population of individuals." ":py:class:`initializers.SeedDetermInitializer`", "Initializer that inserts a fixed number of seeded solutions." ":py:class:`initializers.SeedProbInitializer`", "Initializer that randomly inserts seeded solutions with a given probability." ":py:class:`initializers.PermInitializer`", "Initializer that produces random permutations of n elements." Encodings --------- Implemented encodings that transform between the internal genotype and the phenotype evaluated by the objective function: .. csv-table:: :header: "Module name", "Description" ":py:class:`encodings.DefaultEncoding`", "No change (identity encoding)." ":py:class:`encodings.TypeCastEncoding`", "Changes the datatype (e.g. float ↔ int ↔ boolean)." ":py:class:`encodings.MatrixEncoding`", "Reshapes a vector to a tensor of a different shape." ":py:class:`encodings.ImageEncoding`", "Reshapes a vector to an N×M×C image representation (channels last)." ":py:class:`encodings.SigmoidEncoding`", "Maps real numbers to probabilities via a sigmoid, enabling continuous operators on binary problems." ":py:class:`encodings.CompositeEncoding`", "Applies a sequence of other encodings in order." ":py:class:`encodings.PSOEncoding`", "Extended encoding that stores a speed vector for PSO." ":py:class:`encodings.SelfAdaptingESEncoding`", "Extended encoding that stores mutation strength(s) for self-adaptive evolution strategies." Selection Methods ----------------- Parent and survivor selection are created with dedicated **factory functions**: * :py:func:`~metaheuristic_designer.create_parent_selection` - returns a :py:class:`~metaheuristic_designer.ParentSelection` instance. * :py:func:`~metaheuristic_designer.create_survivor_selection` - returns a :py:class:`~metaheuristic_designer.SurvivorSelection` instance. To skip a selection step entirely, use :py:class:`~metaheuristic_designer.NullParentSelection` / :py:class:`~metaheuristic_designer.NullSurvivorSelection`. The complete catalogue of available methods, their parameters, and instructions for registering custom ones are given on the :doc:`API reference - Implemented Operators & Selection ` page (see :ref:`selection-methods`). To learn how to create custom parent or survivor selection methods and register them, consult the :doc:`Custom Components ` page. Operators --------- Operators modify the genotype of individuals. They are created through the **factory function** :py:func:`~metaheuristic_designer.create_operator`, which accepts a string key in the format ``"category.method"`` (e.g. ``"mutation.gaussian_mutation"``) and optional keyword parameters. .. code-block:: python from metaheuristic_designer.operators import create_operator op = create_operator("mutation.gaussian_mutation", F=0.2, random_state=42) A few built-in operators do **not** follow the factory pattern: .. csv-table:: :header: "Class", "Description" ":py:class:`opeartors.NullOperator`", "Identity operator (no changes)." ":py:class:`operators.CompositeOperator`", "Combines multiple operators sequentially." ":py:class:`operators.MaskedOperator`", "Applies different operators to different sets of components of the genotype vectors." ":py:class:`operators.BranchOperator`", "Randomly selects one operator from a list each time it is applied." ":py:class:`operators.ExtendedOperator`", "Base class for operators that handle extra per-individual parameters (e.g. self-adaptation)." ":py:class:`operators.BOOperator`", "Gaussian process regression operator for Bayesian Optimisation." **IMPORTANT**: For the full catalogue of factory-available operators (mutation, crossover, permutation, DE, swarm, …) and the probability distributions they support, see the :doc:`Operator Methods ` page. To see all available operators at runtime, call :func:`~metaheuristic_designer.operators.list_operators`. For writing and registering your own operators, refer to the :doc:`Custom Components ` guide. Search Strategies ----------------- A **search strategy** defines how one iteration of the optimisation loop is performed: it chooses parents, applies operators, and selects survivors. In practice it acts as a container for an initializer, an operator, and optional parent/survivor selection. You can use one of the ready‑made strategies: .. code-block:: python from metaheuristic_designer.strategies import GA strategy = GA( initializer=UniformInitializer(...), mutation_op=create_operator("mutation.gaussian_mutation", F=0.1), crossover_op=create_operator("crossover.uniform"), parent_sel=create_parent_selection("tournament", amount=50), survivor_sel=create_survivor_selection("elitism", amount=25), ) or build your own by directly combining components with the general :py:class:`~metaheuristic_designer.search_strategy.SearchStrategy` class: .. code-block:: python strategy = SearchStrategy( initializer=..., operator=..., parent_sel=..., survivor_sel=..., ) Both approaches result in an object that can be passed to :py:class:`~metaheuristic_designer.algorithm.Algorithm`. The following pre‑built strategies are available: .. csv-table:: :header: "Module name", "Description" ":py:class:`strategies.NoSearch`", "No‑op strategy (does nothing)." ":py:class:`strategies.RandomSearch`", "Random search." ":py:class:`strategies.StaticPopulation`", "Fixed‑size population based evolution." ":py:class:`strategies.VariablePopulation`", "Variable‑size population based evolution." ":py:class:`strategies.HillClimb`", "Greedy hill climbing." ":py:class:`strategies.LocalSearch`", "Local search with a configurable number of iterations." ":py:class:`strategies.SA`", "Simulated annealing." ":py:class:`strategies.GA`", "Genetic Algorithm." ":py:class:`strategies.ES`", "Evolution Strategy." ":py:class:`strategies.DE`", "Differential Evolution." ":py:class:`strategies.PSO`", "Particle Swarm Optimisation." ":py:class:`strategies.BernoulliPBIL`", "Bernoulli Population‑Based Incremental Learning (EDA)." ":py:class:`strategies.BernoulliUMDA`", "Bernoulli Univariate Marginal Distribution Algorithm (EDA)." ":py:class:`strategies.BinomialPBIL`", "Binomial PBIL." ":py:class:`strategies.BinomialUMDA`", "Binomial UMDA." ":py:class:`strategies.BayesianOptimization`", "Bayesian Optimisation with Gaussian processes." ":py:class:`strategies.CMA_ES`", "Covariance Matrix Adaptation Evolution Strategy." Algorithms ---------- The :py:class:`~metaheuristic_designer.algorithm.Algorithm` class runs the optimisation loop. You pass it an objective function, a search strategy, and optionally a stopping condition, reporter, history tracker and checkpointer (see :doc:`Algorithm Configuration `). .. code-block:: python algo = Algorithm(objfunc, strategy) population = algo.optimize() best_solution, best_obj = population.best_solution() Built‑in algorithm variants: .. csv-table:: :header: "Module name", "Description" ":py:class:`algorithms.Algorithm`", "Default algorithm with the classic parent → perturb → evaluate → survivor loop." ":py:class:`algorithms.MemeticAlgorithm`", "Algorithm that embeds a local search step inside the main loop." ":py:class:`algorithms.AlgorithmSelection`", "Benchmarks a set of algorithms." ":py:class:`algorithms.StrategySelection`", "Benchmarks a set of search strategies." Stopping conditions can be defined as strings combining the following tokens with ``and``, ``or`` and parentheses. See the :doc:`Algorithm Configuration ` page for how to set them. .. csv-table:: :widths: 30 70 :header: "Token", "Description" ``"max_evaluations"``, "Maximum number of objective function evaluations." ``"max_iterations"``, "Maximum number of iterations (generations)." ``"real_time_limit"``, "Wall‑clock time limit in seconds." ``"cpu_time_limit"``, "CPU time limit in seconds." ``"objective_target"``, "Target value for the raw objective; stops when ``best_objective <= objective_target`` (minimisation) or ``best_objective >= objective_target`` (maximisation)." ``"convergence"``, "Stops after ``max_patience`` consecutive iterations without improvement." Example: ``max_iterations or real_time_limit`` will halt when the maximum number of iterations is reached or we have exceeded the maximum time. .. _parameter-schedules: Parameter schedules ------------------- There are a number of already available schedules for parameters. Each of then calculate the parameter value from a progress value in the range [0, 1]. To simplyfy the math, the progress value is :math:`p` and :math:`v` is the parameter value, so that :math:`v(0)` is the initial value and :math:`v(1)` is. the last value. .. list-table:: :header-rows: 1 * - Schedule class - Description - Parameters * - :py:class:`parameter_schedules.LinearSchedule` - | Lineraly interpolates the parameter between two values as: | :math:`v(p) = (1-p)v(0) + p\,v(1)` - | - init_value | - final_value * - :py:class:`parameter_schedules.LogisticSchedule` - | Uses a logistic curve to calculate the parameter: | :math:`v(p) = v(0) - \frac{v(1) - v(0)}{1 - e^{k(p - 0.5)}}` - | - init_value | - final_value | - k (10) * - :py:class:`parameter_schedules.ExponentialDecaySchedule` - | Uses a negative exponential curve to model the parameter, when iterative, ignores the final value: | when iterative is ``False``: :math:`v(p) = v(0) + (v(1) - v(0)) e^{-\alpha p}` | when iterative is ``True``: :math:`v_i = v(0) + (v_{i-1} - v(0)) \alpha` - | - init_value | - final_value (0) | - alpha (0.9) | - iterative (False) * - :py:class:`parameter_schedules.RandomSchedule` - Completely randomizes the parameter value within a range of values. Follows an uniform distribution: - | - init_value | - final_value * - :py:class:`parameter_schedules.ThresholdSchedule` - Chooses a value to assign for progress values below the threshold and another for values above it. - | - init_value | - final_value | - threshold (0.5) * - :py:class:`parameter_schedules.StepSchedule` - | Splits the range of 0 to 1 into :math:`N` steps indicated by a dictionary of the form: | ``{0.1: 34, 0.2: 4, 0.3: 1, ...}`` - | - steps Prepackaged Algorithms ---------------------- For ready‑to‑run algorithm wrappers, see the :doc:`Simple API ` page.