Evolutionary Operators for Continuous Black-Box Optimization

Selection, crossover, mutation, or the evolutionary loop are redesigned to lower final best fitness and improve convergence on continuous benchmark functions.

Optimization & Theorydeap
optimization-evolution-strategy

Description

Evolutionary Optimization Strategy Design

Research Question

Design a novel combination of selection, crossover, and mutation operators (and/or a novel evolutionary loop) for continuous black-box optimization that outperforms standard approaches across multiple benchmark functions.

Background

Evolutionary algorithms (EAs) are population-based metaheuristics for black-box optimization. The three core operators — selection, crossover, and mutation — together with the overall evolutionary loop design, determine an EA's performance. Standard approaches include:

  • Genetic Algorithms (GA) with Tournament selection + Simulated Binary Crossover (SBX) + Polynomial Mutation (Deb and Agrawal, 1995).
  • CMA-ES — Covariance Matrix Adaptation Evolution Strategy (Hansen and Ostermeier, "Completely Derandomized Self-Adaptation in Evolution Strategies", Evolutionary Computation 9(2), 2001).
  • Differential Evolution (DE) — uses vector differences between population members for mutation (Storn and Price, "Differential Evolution", J. Global Optim. 11, 1997).
  • L-SHADE — Success-History based Adaptive DE with Linear population reduction (Tanabe and Fukunaga, "Improving the Search Performance of SHADE Using Linear Population Size Reduction", IEEE CEC 2014; CEC 2014 winner).

Each has strengths on different function landscapes (multimodal, ill-conditioned, high-dimensional), but no single strategy dominates all.

Task

Modify the editable section of custom_evolution.py to implement a novel or improved evolutionary strategy. You may modify:

  • custom_select(population, k, toolbox) — selection operator.
  • custom_crossover(ind1, ind2) — crossover/recombination operator.
  • custom_mutate(individual, lo, hi) — mutation operator.
  • run_evolution(...) — the full evolutionary loop (you can restructure the algorithm entirely).

The DEAP library (deap.base, deap.creator, deap.tools) is available. You may also use numpy, scipy, math, and random.

Interface

  • Individuals: lists of floats, each with a .fitness.values attribute (tuple of one float for minimization).
  • run_evolution must return (best_individual, fitness_history) where fitness_history is a list of best fitness per generation.
  • TRAIN_METRICS: print TRAIN_METRICS gen=G best_fitness=F avg_fitness=A periodically (every 50 generations).
  • Respect the function signature and return types — the evaluation harness below the editable section is fixed.

Evaluation

Strategies are evaluated on benchmarks (all minimization, lower is better):

BenchmarkFunctionDimensionsDomainGlobal Minimum
rastrigin-30dRastrigin30[-5.12, 5.12]0
rosenbrock-30dRosenbrock30[-5, 10]0
ackley-30dAckley30[-32.768, 32.768]0
rastrigin-100dRastrigin100[-5.12, 5.12]0

Metrics: best_fitness (final best value, lower is better) and convergence_gen (generation reaching near-final fitness).

Baselines (paper-cited reference implementations)

  • ga_sbx — Genetic Algorithm with Simulated Binary Crossover and Polynomial Mutation (Deb and Agrawal, 1995); paper-default eta_c = eta_m = 20, mutation probability 1/n.
  • de — Classical DE/rand/1/bin (Storn and Price, 1997); paper-default F = 0.5, CR = 0.9.
  • lshade — L-SHADE (Tanabe and Fukunaga, IEEE CEC 2014); paper-default initial population 18 * n, archive size 2.6 * pop, history memory H = 6, linear population reduction to N_min = 4.

Code

custom_evolution.py
EditableRead-only
1#!/usr/bin/env python3
2"""Evolutionary Optimization Strategy Benchmark.
3
4This script benchmarks an evolutionary optimization strategy on standard
5continuous optimization test functions (Rastrigin, Rosenbrock, Ackley).
6The goal is to minimize each function by designing effective selection,
7crossover, and mutation operators.
8
9Usage:
10 python deap/custom_evolution.py --function rastrigin --dim 30 --seed 42
11"""
12
13import argparse
14import math
15import random

Method Summary

Auto-summarized from each method's code by an LLM reviewer — not the model's original output. Browse via the picker below; the Code section is independent.
Baselines
Agents
Claude Opus 4.6·Pseudocodehigh

ERC-LSHADE (Eigenvector-Rotated)

L-SHADE current-to-pbest with bounce-back boundaries plus a condition-number-driven probability of doing the binomial crossover in eigenvector space.

1. init L-SHADE: H=6 history, M_F[]=0.5, M_CR[]=0.8, archive A, N_init=pop_size, N_min=4
2. every 25 gens: PCA on top-N/3 of pop -> eigenbasis B, prot=clip(log10(λmax/λmin)/3,0,0.8)p_{\text{rot}} = \mathrm{clip}(\log_{10}(\lambda_{\max}/\lambda_{\min})/3, 0, 0.8)
3. for each i: sample FCauchy(MF[r],0.1)F\sim\mathrm{Cauchy}(M_F[r], 0.1), CRN(MCR[r],0.1)CR\sim\mathcal{N}(M_{CR}[r], 0.1); current-to-pbest mutation vv
4. with prob protp_{\text{rot}}: trial=B(maskBv+(1mask)Bxi)\text{trial} = B(\mathrm{mask}\odot B^{\top}v + (1-\mathrm{mask})\odot B^{\top}x_i); else standard binomial
5. bounce-back: xj(bound+xi,j)/2x_j \leftarrow (\text{bound}+x_{i,j})/2 if outside
6. greedy select; on improvement push parent to archive
7. weighted Lehmer mean update for MFM_F, weighted arith for MCRM_{CR}
8. linear pop reduction Nt=Ninit+(NminNinit)t/TN_t = N_{\text{init}} + (N_{\min}-N_{\text{init}})\,t/T; on stagnation(40 gens) replace worst 1/5 with random
Δ vs. baselineAugments lshade baseline with: PCA eigenvector basis recomputed every 25 generations; binomial crossover applied in eigenbasis with probability scaling with log10(cond); bounce-back boundary handling; explicit stagnation-driven random restart of worst 20%.
H (history)=6NminN_min=4protformulap_rot formula=clip(log10(cond)/3, 0, 0.8)rotation refresh=every 25 gensstagnation patience=40 gensMCRinitM_CR init=0.8Recovers L-SHADE baseline when condition number is low (p_rot=0)

Results