API Reference

Complete API documentation for PyRADE.

Core Classes

Main Differential Evolution algorithm implementation.

This module provides the core DifferentialEvolution class with fully vectorized operations for high performance.

class pyrade.core.algorithm.DifferentialEvolution(objective_func: Callable[[ndarray], float], bounds: Tuple[float, float] | ndarray, mutation: Any | None = None, crossover: Any | None = None, selection: Any | None = None, pop_size: int = 50, max_iter: int = 1000, seed: int | None = None, verbose: bool = False, show_progress: bool = False, callback: Callable | None = None)[source]

Bases: object

Main Differential Evolution optimizer with vectorized operations.

This implementation uses aggressive vectorization to process entire populations at once, achieving significant performance improvements over monolithic implementations.

Features: - Fully vectorized (processes entire population at once) - Strategy pattern for operators (easy to extend) - Professional API (fit/predict style) - Progress tracking and callbacks - Progress bar support (tqdm integration) - Comprehensive logging support

Parameters:
  • objective_func (callable) – Function to minimize: f(x) -> float

  • bounds (tuple or array) – (lower_bound, upper_bound) or [(lb1, ub1), (lb2, ub2), …]

  • mutation (MutationStrategy, optional) – Mutation strategy (default: DE/rand/1 with F=0.8)

  • crossover (CrossoverStrategy, optional) – Crossover strategy (default: Binomial with CR=0.9)

  • selection (SelectionStrategy, optional) – Selection strategy (default: Greedy)

  • pop_size (int, default=50) – Population size (must be >= 4)

  • max_iter (int, default=1000) – Maximum iterations (must be >= 1)

  • seed (int, optional) – Random seed for reproducibility

  • verbose (bool, default=False) – Print progress information

  • show_progress (bool, default=False) – Show progress bar (requires tqdm)

  • callback (callable, optional) – Called after each iteration: callback(iteration, best_fitness, best_solution)

best_solution_

Best solution found

Type:

ndarray

best_fitness_

Best fitness value

Type:

float

history_

Optimization history (fitness, time, etc.)

Type:

dict

optimize() : dict

Run optimization and return results

Examples

>>> def sphere(x):
...     return sum(x**2)
>>>
>>> optimizer = DifferentialEvolution(
...     objective_func=sphere,
...     bounds=(-100, 100),
...     pop_size=50,
...     max_iter=1000
... )
>>> result = optimizer.optimize()
>>> print(f"Best fitness: {result['best_fitness']}")
__init__(objective_func: Callable[[ndarray], float], bounds: Tuple[float, float] | ndarray, mutation: Any | None = None, crossover: Any | None = None, selection: Any | None = None, pop_size: int = 50, max_iter: int = 1000, seed: int | None = None, verbose: bool = False, show_progress: bool = False, callback: Callable | None = None)[source]

Initialize Differential Evolution optimizer.

optimize() Dict[str, Any][source]

Run the optimization.

Returns:

‘best_solution’: Best solution found ‘best_fitness’: Best fitness value ‘n_iterations’: Number of iterations run ‘history’: Optimization history ‘success’: Whether optimization succeeded ‘time’: Total optimization time

Return type:

dict with keys

Population management for Differential Evolution.

This module provides efficient vectorized population operations.

class pyrade.core.population.Population(pop_size: int, dim: int, bounds: Tuple[float, float] | ndarray, seed: int | None = None)[source]

Bases: object

Manages the population of candidate solutions.

This class handles population initialization, storage, and provides vectorized operations for efficient population management.

Parameters:
  • pop_size (int) – Size of the population

  • dim (int) – Dimensionality of the search space

  • bounds (tuple or array-like) – Search space bounds (lb, ub) or [(lb1, ub1), …]

  • seed (int, optional) – Random seed for reproducibility

vectors

Population vectors

Type:

ndarray, shape (pop_size, dim)

fitness

Fitness values for each individual

Type:

ndarray, shape (pop_size,)

best_idx

Index of the best individual

Type:

int

best_vector

Best solution vector

Type:

ndarray, shape (dim,)

best_fitness

Best fitness value

Type:

float

__init__(pop_size: int, dim: int, bounds: Tuple[float, float] | ndarray, seed: int | None = None)[source]

Initialize population.

initialize_random()[source]

Initialize population with random vectors within bounds.

Uses Latin Hypercube Sampling for better space coverage.

evaluate(objective_func: Callable[[ndarray], float]) ndarray[source]

Evaluate fitness for all individuals in population.

Parameters:

objective_func (callable) – Objective function to minimize

Returns:

fitness – Fitness values

Return type:

ndarray, shape (pop_size,)

evaluate_vectors(vectors: ndarray, objective_func: Callable[[ndarray], float]) ndarray[source]

Evaluate fitness for given vectors.

Parameters:
  • vectors (ndarray, shape (pop_size, dim)) – Vectors to evaluate

  • objective_func (callable) – Objective function to minimize

Returns:

fitness – Fitness values

Return type:

ndarray, shape (pop_size,)

update(new_vectors: ndarray, new_fitness: ndarray) None[source]

Update population with new vectors and fitness.

Parameters:
  • new_vectors (ndarray, shape (pop_size, dim)) – New population vectors

  • new_fitness (ndarray, shape (pop_size,)) – New fitness values

get_indices() ndarray[source]

Get array of population indices.

clip_to_bounds(vectors: ndarray) ndarray[source]

Clip vectors to bounds.

Parameters:

vectors (ndarray, shape (pop_size, dim)) – Vectors to clip

Returns:

clipped – Clipped vectors

Return type:

ndarray, shape (pop_size, dim)

Operators

Mutation Strategies

Mutation strategies for Differential Evolution.

This module provides various mutation strategies with fully vectorized implementations for high performance.

class pyrade.operators.mutation.MutationStrategy[source]

Bases: ABC

Abstract base class for mutation strategies.

All mutation strategies should inherit from this class and implement the apply() method.

abstractmethod apply(population, fitness, best_idx, target_indices)[source]

Apply mutation to generate mutant vectors.

Parameters:
  • population (ndarray, shape (pop_size, dim)) – Current population

  • fitness (ndarray, shape (pop_size,)) – Fitness values

  • best_idx (int) – Index of best individual

  • target_indices (ndarray, shape (pop_size,)) – Indices being mutated

Returns:

mutants – Mutant vectors

Return type:

ndarray, shape (pop_size, dim)

class pyrade.operators.mutation.DErand1(F=0.8)[source]

Bases: MutationStrategy

DE/rand/1: v = x_r1 + F * (x_r2 - x_r3)

Most common DE mutation strategy. Selects three random distinct individuals and creates mutant from their differences.

Parameters:

F (float, default=0.8) – Mutation factor (differential weight)

Notes

This is the most widely used mutation strategy, providing a good balance between exploration and exploitation.

__init__(F=0.8)[source]
apply(population, fitness, best_idx, target_indices)[source]

Apply DE/rand/1 mutation (fully vectorized).

class pyrade.operators.mutation.DEbest1(F=0.8)[source]

Bases: MutationStrategy

DE/best/1: v = x_best + F * (x_r1 - x_r2)

Exploitative strategy using best individual as base vector. Converges faster but may get stuck in local optima.

Parameters:

F (float, default=0.8) – Mutation factor (differential weight)

Notes

More exploitative than DE/rand/1. Good for unimodal functions but may converge prematurely on multimodal problems.

__init__(F=0.8)[source]
apply(population, fitness, best_idx, target_indices)[source]

Apply DE/best/1 mutation (fully vectorized).

class pyrade.operators.mutation.DEcurrentToBest1(F=0.8)[source]

Bases: MutationStrategy

DE/current-to-best/1: v = x_i + F * (x_best - x_i) + F * (x_r1 - x_r2)

Balances exploration and exploitation by combining current individual with best and random difference vectors.

Parameters:

F (float, default=0.8) – Mutation factor (differential weight)

Notes

This strategy provides a good balance between DE/rand/1 and DE/best/1, often performing well on a wide range of problems.

__init__(F=0.8)[source]
apply(population, fitness, best_idx, target_indices)[source]

Apply DE/current-to-best/1 mutation (fully vectorized).

class pyrade.operators.mutation.DErand2(F=0.8)[source]

Bases: MutationStrategy

DE/rand/2: v = x_r1 + F * (x_r2 - x_r3) + F * (x_r4 - x_r5)

More exploratory strategy using two difference vectors. Provides greater diversity but may converge slower.

Parameters:

F (float, default=0.8) – Mutation factor (differential weight)

Notes

Uses more difference vectors for increased exploration. Good for highly multimodal problems but requires larger populations.

__init__(F=0.8)[source]
apply(population, fitness, best_idx, target_indices)[source]

Apply DE/rand/2 mutation (fully vectorized).

class pyrade.operators.mutation.DEbest2(F=0.8)[source]

Bases: MutationStrategy

DE/best/2: v = x_best + F * (x_r1 - x_r2) + F * (x_r3 - x_r4)

Highly exploitative strategy using best individual as base with two difference vectors. Fast convergence but risk of premature convergence.

Parameters:

F (float, default=0.8) – Mutation factor (differential weight)

Notes

More aggressive than DE/best/1. Good for unimodal functions but requires careful parameter tuning for multimodal problems.

__init__(F=0.8)[source]
apply(population, fitness, best_idx, target_indices)[source]

Apply DE/best/2 mutation (fully vectorized).

class pyrade.operators.mutation.DEcurrentToRand1(F=0.8, K=0.5)[source]

Bases: MutationStrategy

DE/current-to-rand/1: v = x_i + K * (x_r1 - x_i) + F * (x_r2 - x_r3)

Combines current vector with random vector plus difference vector. More exploratory than current-to-best.

Parameters:
  • F (float, default=0.8) – Mutation factor for difference vector

  • K (float, default=0.5) – Weight for current-to-random direction

Notes

Provides diversity through random direction. Good balance between exploration and maintaining population structure.

__init__(F=0.8, K=0.5)[source]
apply(population, fitness, best_idx, target_indices)[source]

Apply DE/current-to-rand/1 mutation (fully vectorized).

class pyrade.operators.mutation.DERandToBest1(F=0.8)[source]

Bases: MutationStrategy

DE/rand-to-best/1: v = x_r1 + F * (x_best - x_r1) + F * (x_r2 - x_r3)

Direction from random vector toward best, plus random difference. Balances exploration from random base with exploitation toward best.

Parameters:

F (float, default=0.8) – Mutation factor (differential weight)

Notes

Less greedy than DE/best/1 but still directed toward best solution. Good for problems where premature convergence is a concern.

__init__(F=0.8)[source]
apply(population, fitness, best_idx, target_indices)[source]

Apply DE/rand-to-best/1 mutation (fully vectorized).

class pyrade.operators.mutation.DErand1EitherOr(F=0.8, p_F=0.5)[source]

Bases: MutationStrategy

DE/rand/1/either-or: v = x_r1 + F_i * (x_r2 - x_r3)

Uses probabilistic choice of scaling factor F_i which is either F or 0.5*F based on probability p_F (typically 0.5).

Reference:

Price, K. V., Storn, R. M., & Lampinen, J. A. (2006). Differential Evolution: A Practical Approach to Global Optimization. Springer Science & Business Media.

Parameters:
  • F (float, default=0.8) – Mutation factor (differential weight)

  • p_F (float, default=0.5) – Probability of using full F (vs 0.5*F)

Notes

This strategy adds randomness in the scaling factor which can help maintain diversity. Each difference vector independently chooses between F and 0.5*F.

__init__(F=0.8, p_F=0.5)[source]
apply(population, fitness, best_idx, target_indices)[source]

Apply DE/rand/1/either-or mutation (fully vectorized).

class pyrade.operators.mutation.LevyFlightMutation(beta=1.5, scale=0.01)[source]

Bases: MutationStrategy

Lévy flight-based mutation: DE/rand/1 with Lévy flight step sizes.

Uses Lévy flight random walk for generating step sizes, which provides heavy-tailed distribution beneficial for exploration. Lévy flights consist of many small steps with occasional large jumps, mimicking optimal foraging patterns found in nature.

Formula: v = x_r1 + L(β) * (x_r2 - x_r3) where L(β) is a Lévy flight step size with stability parameter β

Parameters:
  • beta (float, default=1.5) – Lévy flight stability parameter (0 < β <= 2) β=1.0: Cauchy distribution (very heavy tails) β=1.5: stable distribution (recommended) β=2.0: Gaussian distribution (light tails)

  • scale (float, default=0.01) – Scale factor for Lévy flight step sizes

Notes

Lévy flight mutation is useful for: - Escaping local optima through large jumps - Maintaining good local search through small steps - Multimodal optimization problems - Exploration-exploitation balance

The Mantegna method is used to generate Lévy flight samples efficiently.

References

Yang, X. S., & Deb, S. (2009). Cuckoo search via Lévy flights. In 2009 World congress on nature & biologically inspired computing.

Examples

>>> mutation = LevyFlightMutation(beta=1.5, scale=0.01)
>>> mutation = LevyFlightMutation(beta=1.0)  # Cauchy-like
__init__(beta=1.5, scale=0.01)[source]
apply(population, fitness, best_idx, target_indices)[source]

Apply Lévy flight mutation (fully vectorized).

Crossover Strategies

Crossover strategies for Differential Evolution.

This module provides crossover strategies with fully vectorized implementations for high performance.

class pyrade.operators.crossover.CrossoverStrategy[source]

Bases: ABC

Abstract base class for crossover strategies.

All crossover strategies should inherit from this class and implement the apply() method.

abstractmethod apply(population, mutants)[source]

Apply crossover between population and mutants.

Parameters:
  • population (ndarray, shape (pop_size, dim)) – Target vectors

  • mutants (ndarray, shape (pop_size, dim)) – Mutant vectors

Returns:

trials – Trial vectors

Return type:

ndarray, shape (pop_size, dim)

class pyrade.operators.crossover.BinomialCrossover(CR=0.9)[source]

Bases: CrossoverStrategy

Binomial crossover: u_ij = v_ij if rand() <= CR or j == j_rand, else x_ij

Most common crossover in DE. Each dimension is independently crossed with probability CR.

Parameters:

CR (float, default=0.9) – Crossover probability (0 <= CR <= 1)

Notes

Higher CR values lead to more exploitation (more from mutant), lower CR values lead to more exploration (more from parent). At least one dimension is always crossed over to ensure the trial differs from the target.

__init__(CR=0.9)[source]
apply(population, mutants)[source]

Apply binomial crossover (fully vectorized).

class pyrade.operators.crossover.ExponentialCrossover(CR=0.9)[source]

Bases: CrossoverStrategy

Exponential crossover: copies contiguous segment from mutant.

Alternative to binomial crossover. Copies a contiguous segment of dimensions from the mutant vector.

Parameters:

CR (float, default=0.9) – Crossover probability (0 <= CR <= 1)

Notes

Exponential crossover tends to preserve building blocks better than binomial crossover. The length of the copied segment follows a geometric distribution with parameter CR.

__init__(CR=0.9)[source]
apply(population, mutants)[source]

Apply exponential crossover (fully vectorized).

class pyrade.operators.crossover.UniformCrossover[source]

Bases: CrossoverStrategy

Uniform crossover: each dimension independently with probability 0.5.

A simple crossover strategy where each dimension has equal probability of coming from either parent or mutant.

Notes

This is a special case of binomial crossover with CR=0.5, but ensures at least one dimension crosses over.

__init__()[source]
apply(population, mutants)[source]

Apply uniform crossover (fully vectorized).

class pyrade.operators.crossover.ArithmeticCrossover(alpha=0.5, adaptive=False)[source]

Bases: CrossoverStrategy

Arithmetic crossover: weighted linear combination of parent and mutant.

Creates trial vectors as a weighted average: trial = alpha * mutant + (1-alpha) * parent This creates offspring that lie on a line between parent and mutant vectors.

Parameters:
  • alpha (float, default=0.5) – Weighting factor (0 <= alpha <= 1) alpha=0.5 means equal weight to both alpha=1.0 means take mutant entirely alpha=0.0 means take parent entirely

  • adaptive (bool, default=False) – If True, alpha is randomly sampled for each individual

Notes

Arithmetic crossover is useful for: - Real-valued optimization (continuous domains) - Maintaining feasibility when parents are feasible - Smoother exploration of search space - Better preservation of numerical properties

Examples

>>> crossover = ArithmeticCrossover(alpha=0.5)  # Equal blending
>>> crossover = ArithmeticCrossover(alpha=0.7, adaptive=True)  # Adaptive
__init__(alpha=0.5, adaptive=False)[source]
apply(population, mutants)[source]

Apply arithmetic crossover (fully vectorized).

class pyrade.operators.crossover.ThreePointCrossover[source]

Bases: CrossoverStrategy

Three-point crossover: exchanges three segments between parent and mutant.

Randomly selects three crossover points and alternates between parent and mutant vectors. This creates more diverse offspring than single-point crossover.

Process: 1. Select three random positions 2. Segment: [0:p1] from one, [p1:p2] from other, [p2:p3] from first, [p3:] from other

Parameters:

None

Notes

Three-point crossover is useful for: - Maintaining building blocks of intermediate size - More diversity than two-point crossover - Better mixing of parent and mutant characteristics - Discrete optimization problems

The crossover ensures good mixing while preserving some contiguous segments from both parents.

Examples

>>> crossover = ThreePointCrossover()
>>> trials = crossover.apply(population, mutants)
__init__()[source]
apply(population, mutants)[source]

Apply three-point crossover.

Selection Strategies

Selection strategies for Differential Evolution.

This module provides selection strategies with fully vectorized implementations for high performance.

class pyrade.operators.selection.SelectionStrategy[source]

Bases: ABC

Abstract base class for selection strategies.

All selection strategies should inherit from this class and implement the apply() method.

abstractmethod apply(population, fitness, trials, trial_fitness)[source]

Select survivors for next generation.

Parameters:
  • population (ndarray, shape (pop_size, dim)) – Current population

  • fitness (ndarray, shape (pop_size,)) – Current fitness

  • trials (ndarray, shape (pop_size, dim)) – Trial vectors

  • trial_fitness (ndarray, shape (pop_size,)) – Trial fitness

Returns:

  • new_population (ndarray, shape (pop_size, dim)) – Selected population

  • new_fitness (ndarray, shape (pop_size,)) – Selected fitness

class pyrade.operators.selection.GreedySelection[source]

Bases: SelectionStrategy

Greedy selection: keep trial if better, else keep target.

Standard DE selection. For minimization problems, selects the individual with lower fitness value.

Notes

This is the most common selection strategy in DE, ensuring the population never degrades (monotonic improvement).

apply(population, fitness, trials, trial_fitness)[source]

Apply greedy selection (fully vectorized).

class pyrade.operators.selection.TournamentSelection(tournament_size=2)[source]

Bases: SelectionStrategy

Tournament selection: select winner from random tournament.

Selects the best individual from a random subset of the population. Can add diversity compared to greedy selection.

Parameters:

tournament_size (int, default=2) – Number of individuals in each tournament

Notes

Larger tournament sizes increase selection pressure. Tournament size of 2 is most common.

__init__(tournament_size=2)[source]
apply(population, fitness, trials, trial_fitness)[source]

Apply tournament selection.

class pyrade.operators.selection.ElitistSelection(elite_size=1)[source]

Bases: SelectionStrategy

Elitist selection: always preserve best individuals.

Combines greedy selection with elitism to ensure the absolute best individuals are never lost.

Parameters:

elite_size (int, default=1) – Number of elite individuals to preserve

Notes

Elite individuals are guaranteed to survive to the next generation, regardless of their trial performance.

__init__(elite_size=1)[source]
apply(population, fitness, trials, trial_fitness)[source]

Apply elitist selection.

Utilities

Boundary Handlers

Termination Criteria

Benchmark Functions