CMA-ES, Covariance Matrix Adaptation Evolution Strategy for non-linear numerical optimization in Python
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Comprehensive configuration management for CMA-ES through the CMAOptions class. This covers all available options for fine-tuning CMA-ES behavior across different problem types and requirements.
The central class for managing all CMA-ES configuration options with defaults, validation, and search capabilities.
# Major CMA-ES option categories with examples
# Population and sampling options
'popsize' # Population size (default: 4 + int(3*log(N)))
'popsize_factor' # Population size multiplier
'CMA_mu' # Parent population size
'CMA_mirrors' # Use mirrored sampling
'CMA_mirrormethod' # Mirroring method selection
# Termination criteria
'maxiter' # Maximum iterations
'maxfevals' # Maximum function evaluations
'ftarget' # Target function value
'tolfun' # Tolerance in function value
'tolfunhist' # Tolerance in function value history
'tolfunrel' # Relative tolerance in function value
'tolx' # Tolerance in parameter changes
'tolstagnation' # Tolerance for stagnation detection
'timeout' # Wall-clock time limit
# Step-size control
'CSA_dampfac' # Step-size damping factor
'CSA_damp_mueff_exponent' # Damping exponent
'CSA_disregard_length' # Disregard length of step
'CMA_dampsvec' # Individual step-size damping
# Covariance matrix adaptation
'CMA_active' # Use active covariance matrix update
'CMA_cmean' # Learning rate for mean update
'CMA_on' # Enable/disable covariance matrix adaptation
'CMA_rankmu' # Use rank-mu update
'CMA_rankone' # Use rank-one update
'CMA_recombination_weights' # Recombination weights method
# Boundaries and constraints
'bounds' # Box constraints [lower, upper]
'fixed_variables' # Fix certain variables
'scaling_of_variables' # Variable scaling factors
'typical_x' # Typical variable values
# Display and logging
'verb_disp' # Display verbosity level (0=none, 1=some, 2=much)
'verb_log' # Logging verbosity
'verb_plot' # Plotting verbosity
'verb_time' # Time display verbosity
'verb_append' # Append to existing log files
'output_filename' # Base filename for output files
# Advanced algorithmic options
'AdaptSigma' # Step-size adaptation method
'CMA_elitist' # Use elitist selection
'CMA_sampler' # Sampling method selection
'BoundaryHandler' # Boundary handling strategy
'ConditioningOfC' # Conditioning of covariance matrix
'MaxConditionNumber' # Maximum condition number
'NoEffectAxis' # Handle ineffective coordinate axes
'NoEffectCoord' # Handle ineffective coordinates
# Restart and multistart
'restarts' # Number of restarts
'restart_from_best' # Restart from best solution
'incpopsize' # Population size increment factor
'bipop' # Use bi-population strategy
# Noise handling
'noise_handling' # Enable noise handling
'noise_change_sigma_exponent' # Noise-dependent step-size change
'noise_evaluations_as_reward' # Treat noise evaluations as rewardclass CMAOptions(dict):
"""
Dictionary of available CMA-ES options with defaults and documentation.
Inherits from dict and provides additional functionality for option
management, validation, and searching. Contains all available options
with their default values and descriptions.
"""
def __init__(self, s='', **kwargs):
"""
Initialize options dictionary.
Parameters:
-----------
s : str or dict, optional
Search string to filter options, or dict of options to set.
If string, returns options matching the substring in name,
value, or description.
**kwargs : dict
Direct option assignments as keyword arguments.
Examples:
---------
>>> import cma
>>>
>>> # All default options
>>> opts = cma.CMAOptions()
>>> len(opts) > 50 # Many options available
True
>>>
>>> # Search for tolerance options
>>> tol_opts = cma.CMAOptions('tol')
>>> print(list(tol_opts.keys()))
['tolfun', 'tolfunhist', 'tolfunrel', 'tolstagnation', 'tolx', ...]
>>>
>>> # Search for verbosity options
>>> verb_opts = cma.CMAOptions('verb')
>>> 'verb_disp' in verb_opts
True
>>>
>>> # Initialize with specific options
>>> opts = cma.CMAOptions({'popsize': 20, 'maxiter': 1000})
>>>
>>> # Using keyword arguments
>>> opts = cma.CMAOptions(popsize=20, maxiter=1000, ftarget=1e-8)
"""
pass
def init(self, dict_or_str, val=None, warn=True):
"""
Initialize one or several options.
Parameters:
-----------
dict_or_str : dict or str
Dictionary of options if val is None, otherwise option key.
val : any, optional
Option value if dict_or_str is a key.
warn : bool, optional
Whether to warn about unknown options (default True).
Examples:
---------
>>> opts = cma.CMAOptions()
>>> opts.init('popsize', 50)
>>> opts.init({'maxiter': 2000, 'ftarget': 1e-10})
"""
pass
def set(self, dic, val=None, force=False):
"""
Set versatile options that can be changed during optimization.
Parameters:
-----------
dic : dict or str
Dictionary of options or single option key.
val : any, optional
Option value if dic is a key.
force : bool, optional
Force setting of non-versatile options (default False).
Examples:
---------
>>> import cma
>>> es = cma.CMAEvolutionStrategy([0, 0], 0.5)
>>>
>>> # Change options during optimization
>>> es.opts.set('verb_disp', 50) # Change display frequency
>>> es.opts.set({'ftarget': 1e-6, 'maxfevals': 2000})
"""
pass
def match(self, s=''):
"""
Return options that match search string.
Parameters:
-----------
s : str
Search string to match in option names, values, or descriptions.
Returns:
--------
dict
Dictionary of matching options.
Examples:
---------
>>> opts = cma.CMAOptions()
>>>
>>> # Find all termination options
>>> term_opts = opts.match('termination')
>>>
>>> # Find population size related options
>>> pop_opts = opts.match('popsize')
>>>
>>> # Find boundary related options
>>> bound_opts = opts.match('bound')
"""
pass
@staticmethod
def defaults():
"""
Return dictionary of all default options.
Returns:
--------
dict
All available options with their default values.
"""
pass
def versatile_options(self):
"""
Return list of versatile options that can be changed during optimization.
Returns:
--------
list
List of option keys that can be modified after initialization.
"""
passOptions controlling when optimization stops.
# Termination options and their usage
termination_options = {
'ftarget': '-inf', # Target function value (minimization)
'maxfevals': 'inf', # Maximum function evaluations
'maxiter': '100 + 150 * (N+3)**2 // popsize**0.5', # Maximum iterations
'timeout': 'inf', # Maximum time in seconds
'tolfun': '1e-11', # Function value tolerance
'tolfunhist': '1e-12', # Function value history tolerance
'tolfunrel': '0', # Relative function value tolerance
'tolx': '1e-11', # Solution tolerance
'tolstagnation': 'int(100 + 100 * N**1.5 / popsize)', # Stagnation tolerance
'tolconditioncov': '1e14', # Covariance matrix condition tolerance
'tolfacupx': '1e3', # Step-size increase tolerance
'tolupsigma': '1e20', # Sigma increase tolerance
'tolflatfitness': '1' # Flat fitness tolerance iterations
}
# Examples of termination configuration
examples = {
# Quick convergence for testing
'fast_convergence': {
'ftarget': 1e-6,
'maxfevals': 1000,
'tolfun': 1e-8
},
# Thorough optimization
'thorough': {
'maxfevals': 100000,
'ftarget': 1e-12,
'tolfun': 1e-15,
'tolx': 1e-12
},
# Time-limited optimization
'time_limited': {
'timeout': 3600, # 1 hour
'maxiter': float('inf'),
'maxfevals': float('inf')
},
# High-precision optimization
'high_precision': {
'ftarget': 1e-15,
'tolfun': 1e-18,
'tolx': 1e-15,
'tolconditioncov': 1e16
}
}Options controlling population size and selection mechanisms.
# Population and selection options
population_options = {
'popsize': '4 + 3 * math.log(N)', # Population size (lambda)
'popsize_factor': '1', # Multiplier for default popsize
'CMA_mu': 'None', # Parent selection parameter (mu)
'CMA_recombination_weights': 'None', # Custom recombination weights
'CMA_elitist': 'False', # Elitist selection
'CMA_mirrors': 'popsize < 6', # Mirrored sampling
'CMA_mirrormethod': '2' # Mirror method (0,1,2)
}
# Population configuration examples
population_examples = {
# Small population for fast convergence
'small_population': {
'popsize': 10,
'CMA_mu': 5
},
# Large population for difficult problems
'large_population': {
'popsize_factor': 3, # 3x default size
'CMA_mu': None # Will be popsize // 2
},
# Custom recombination weights
'custom_weights': {
'CMA_recombination_weights': [0.5, 0.3, 0.2], # Manual weights
'popsize': 10 # Must match weights length
},
# Mirrored sampling for small populations
'mirrored_sampling': {
'popsize': 8,
'CMA_mirrors': True, # Enable mirroring
'CMA_mirrormethod': 2 # Selective with delay
},
# Elitist strategy (use with caution)
'elitist': {
'CMA_elitist': 'initial', # Keep initial solution
'popsize': 20
}
}Options controlling step-size and covariance matrix adaptation.
# Adaptation options
adaptation_options = {
'AdaptSigma': 'True', # Enable step-size adaptation
'CSA_dampfac': '1', # Step-size damping factor
'CSA_disregard_length': 'False', # Disregard path length
'CSA_squared': 'False', # Use squared length
'CMA_on': '1', # Covariance matrix update multiplier
'CMA_rankone': '1.0', # Rank-one update multiplier
'CMA_rankmu': '1.0', # Rank-mu update multiplier
'CMA_active': 'True', # Active covariance matrix update
'CMA_diagonal': '0*100*N/popsize**0.5', # Diagonal-only iterations
'updatecovwait': 'None' # Iterations without cov update
}
# Adaptation configuration examples
adaptation_examples = {
# Conservative adaptation
'conservative': {
'CSA_dampfac': 2.0, # Slower step-size adaptation
'CMA_rankone': 0.5, # Reduced rank-one update
'CMA_rankmu': 0.5 # Reduced rank-mu update
},
# Aggressive adaptation
'aggressive': {
'CSA_dampfac': 0.5, # Faster step-size adaptation
'CMA_rankone': 2.0, # Increased rank-one update
'CMA_active': True # Enable active update
},
# Diagonal-only for high dimensions
'diagonal_phase': {
'CMA_diagonal': '100', # 100 iterations diagonal-only
'CMA_rankmu': 0.0 # Disable rank-mu initially
},
# No covariance matrix adaptation
'no_covariance': {
'CMA_on': 0, # Disable all covariance updates
'AdaptSigma': True # Keep step-size adaptation
},
# Custom sigma adaptation
'custom_sigma': {
'AdaptSigma': 'cma.sigma_adaptation.CMAAdaptSigmaTPA',
'CSA_dampfac': 1.5
}
}Options for handling box constraints and boundaries.
# Boundary and constraint options
boundary_options = {
'bounds': '[None, None]', # [lower, upper] boundaries
'BoundaryHandler': 'BoundTransform', # Boundary handling method
'fixed_variables': 'None', # Fixed variable indices
'integer_variables': '[]', # Integer variable indices
'is_feasible': 'is_feasible', # Feasibility function
'minstd': '0', # Minimal standard deviation
'maxstd': 'None', # Maximal standard deviation
'maxstd_boundrange': '1/3' # Max std relative to bounds
}
# Boundary configuration examples
boundary_examples = {
# Simple box constraints
'box_constraints': {
'bounds': [[-5, -5, -5], [5, 5, 5]], # 3D box [-5,5]^3
'BoundaryHandler': 'BoundTransform'
},
# Mixed bounds (some unbounded)
'mixed_bounds': {
'bounds': [[0, None, -10], [10, None, 10]], # [0,10] x R x [-10,10]
'BoundaryHandler': 'BoundTransform'
},
# Penalty-based bounds
'penalty_bounds': {
'bounds': [[-1, -1], [1, 1]],
'BoundaryHandler': 'BoundPenalty'
},
# Fixed variables
'fixed_variables': {
'fixed_variables': {0: 1.5, 2: 0.0}, # Fix x[0]=1.5, x[2]=0.0
'bounds': [[-5, -5, -5, -5], [5, 5, 5, 5]]
},
# Integer variables
'integer_optimization': {
'integer_variables': [0, 2], # x[0] and x[2] are integers
'bounds': [[0, -5, 0], [10, 5, 10]] # Appropriate bounds
},
# Standard deviation constraints
'std_constraints': {
'minstd': 0.01, # Minimum std per coordinate
'maxstd': 2.0, # Maximum std per coordinate
'bounds': [[-10, -10], [10, 10]]
}
}Options controlling output, logging, and visualization.
# Verbosity and logging options
verbosity_options = {
'verbose': '3', # General verbosity level
'verb_disp': '100', # Console display frequency
'verb_log': '1', # File logging frequency
'verb_plot': '0', # Plotting frequency (fmin2 only)
'verb_time': 'True', # Show timing information
'verb_append': '0', # Append to existing files
'verb_filenameprefix': 'outcmaes', # Output filename prefix
'verb_log_expensive': 'N * (N <= 50)' # Expensive logging frequency
}
# Verbosity configuration examples
verbosity_examples = {
# Silent optimization
'silent': {
'verbose': -9, # Maximally quiet
'verb_disp': 0, # No console output
'verb_log': 0, # No file logging
'verb_time': False # No timing
},
# Detailed monitoring
'detailed': {
'verbose': 3, # Standard verbosity
'verb_disp': 10, # Display every 10 iterations
'verb_log': 1, # Log every iteration
'verb_plot': 50, # Plot every 50 iterations
'verb_time': True # Show timing
},
# Production logging
'production': {
'verbose': 1, # Minimal console output
'verb_disp': 100, # Rare display updates
'verb_log': 10, # Log every 10 iterations
'verb_filenameprefix': 'results/run_001', # Custom prefix
'verb_append': 0 # Overwrite files
},
# Debugging mode
'debug': {
'verbose': 3,
'verb_disp': 1, # Display every iteration
'verb_log': 1, # Log everything
'verb_log_expensive': 1 # Expensive operations too
}
}Advanced options for specialized use cases and experimental features.
# Advanced and experimental options
advanced_options = {
'seed': 'time', # Random number seed
'randn': 'np.random.randn', # Random number generator
'CMA_eigenmethod': 'np.linalg.eigh', # Eigendecomposition method
'CMA_sampler': 'None', # Custom sampler class
'CMA_sampler_options': '{}', # Sampler options
'mean_shift_line_samples': 'False', # Line samples along mean shift
'pc_line_samples': 'False', # Line samples along evolution path
'signals_filename': 'cma_signals.in', # External signals file
'termination_callback': '[]', # Custom termination callbacks
'callback': 'None', # Iteration callbacks
'transformation': 'None', # Coordinate transformation
'CMA_stds': 'None' # Coordinate-wise standard deviations
}
# Advanced configuration examples
advanced_examples = {
# Reproducible results
'reproducible': {
'seed': 42, # Fixed seed
'randn': 'np.random.randn' # Standard generator
},
# Custom sampling
'custom_sampling': {
'CMA_sampler': 'cma.sampler.GaussFullSampler',
'CMA_sampler_options': {'eigenmethod': 'np.linalg.eigh'}
},
# Coordinate scaling
'coordinate_scaling': {
'CMA_stds': [1.0, 10.0, 0.1], # Different scales per coordinate
'bounds': [[-1, -10, -0.1], [1, 10, 0.1]]
},
# External control
'external_control': {
'signals_filename': 'optimization_control.in',
'termination_callback': [lambda es: es.countiter > 1000]
},
# Line sampling experiments
'line_sampling': {
'mean_shift_line_samples': True, # Sample along mean shift
'pc_line_samples': True, # Sample along evolution path
'popsize_factor': 1.5 # Larger population for extra samples
}
}import cma
# Pattern 1: Using options dictionary
def basic_configuration():
"""Basic option configuration examples."""
# Simple configuration
options = {
'popsize': 20,
'maxfevals': 5000,
'ftarget': 1e-8,
'verb_disp': 50
}
x, es = cma.fmin2(cma.ff.sphere, [0, 0, 0], 0.5, options=options)
return x, es
# Pattern 2: Using CMAOptions for exploration
def explore_options():
"""Explore and configure options systematically."""
# Find all tolerance options
tol_opts = cma.CMAOptions('tol')
print("Tolerance options:")
for key, value in tol_opts.items():
print(f" {key}: {value}")
# Find verbosity options
verb_opts = cma.CMAOptions('verb')
print("\nVerbosity options:")
for key in sorted(verb_opts.keys()):
print(f" {key}: {verb_opts[key]}")
# Create custom configuration
custom_opts = cma.CMAOptions({
'maxfevals': 2000,
'popsize': 15,
'verb_disp': 25
})
return custom_opts
# Pattern 3: Runtime option changes
def runtime_configuration():
"""Change options during optimization."""
def objective(x):
return sum(x**2)
es = cma.CMAEvolutionStrategy([1, 2, 3], 0.5)
iteration = 0
while not es.stop():
solutions = es.ask()
fitness_values = [objective(x) for x in solutions]
es.tell(solutions, fitness_values)
iteration += 1
# Change verbosity after 100 iterations
if iteration == 100:
es.opts.set('verb_disp', 10) # More frequent display
# Change target after 200 iterations
if iteration == 200:
es.opts.set('ftarget', 1e-10) # Stricter target
# Add timeout after 500 iterations
if iteration == 500:
es.opts.set('timeout', 60) # 1 minute timeout
return es.result
basic_configuration()
explore_options()
runtime_configuration()import cma
import numpy as np
# Configuration for different problem types
def problem_specific_configs():
"""Configurations tailored to specific problem characteristics."""
# High-dimensional problems (N > 100)
high_dim_config = {
'CMA_diagonal': '50 + N//2', # Longer diagonal phase
'popsize_factor': 0.5, # Smaller population
'verb_log_expensive': 0, # Disable expensive logging
'maxiter': 1000, # Reasonable iteration limit
'tolstagnation': 200 # More patience for stagnation
}
# Noisy functions
noisy_config = {
'popsize_factor': 2, # Larger population
'tolflatfitness': 10, # More tolerance for flat fitness
'CSA_dampfac': 2, # Conservative step-size adaptation
'CMA_active': False, # Disable active update
'verb_disp': 20 # More frequent monitoring
}
# Multi-modal functions
multimodal_config = {
'popsize_factor': 2, # Larger population for exploration
'CMA_elitist': False, # Avoid premature convergence
'tolstagnation': 500, # Long stagnation tolerance
'tolfacupx': 1e5, # Allow large step increases
'maxfevals': 100000 # Large evaluation budget
}
# Fast functions (cheap to evaluate)
fast_function_config = {
'verb_log': 1, # Log every iteration
'verb_disp': 100, # Regular display
'verb_log_expensive': 10, # Allow expensive logging
'maxfevals': 1000000, # Large budget allowed
'popsize_factor': 1.5 # Slightly larger population
}
# Expensive functions (costly to evaluate)
expensive_function_config = {
'maxfevals': 1000, # Strict evaluation limit
'verb_log': 10, # Reduce logging frequency
'verb_log_expensive': 0, # No expensive operations
'popsize_factor': 0.5, # Smaller population
'tolfun': 1e-6, # Relaxed tolerance
'tolx': 1e-6 # Relaxed tolerance
}
return {
'high_dimensional': high_dim_config,
'noisy': noisy_config,
'multimodal': multimodal_config,
'fast': fast_function_config,
'expensive': expensive_function_config
}
configs = problem_specific_configs()
# Example usage with different problem types
def sphere_high_dim():
"""100D sphere function."""
def objective(x):
return sum(x**2)
x, es = cma.fmin2(
objective,
100 * [0.1],
0.3,
options=configs['high_dimensional']
)
return x, es
def noisy_rosenbrock():
"""Noisy Rosenbrock function."""
def objective(x):
true_val = sum(100*(x[1:] - x[:-1]**2)**2 + (1 - x[:-1])**2)
noise = 0.1 * np.random.randn()
return true_val + noise
x, es = cma.fmin2(
objective,
5 * [0.1],
0.5,
options=configs['noisy']
)
return x, esimport cma
def validate_and_debug_config():
"""Validate configuration and debug option issues."""
def validate_options(options):
"""Validate option dictionary."""
# Create CMAOptions instance to check validity
try:
opts = cma.CMAOptions(options)
print("✓ All options are valid")
return True
except Exception as e:
print(f"✗ Invalid options: {e}")
return False
def debug_option_conflicts():
"""Check for common option conflicts."""
# Test conflicting options
conflicting_options = {
'popsize': 10,
'CMA_mu': 8, # mu should be <= popsize//2
'CMA_mirrors': True # Conflicts with small popsize
}
print("Testing conflicting options...")
validate_options(conflicting_options)
# Corrected options
corrected_options = {
'popsize': 20, # Larger population
'CMA_mu': 10, # popsize//2
'CMA_mirrors': True # Now compatible
}
print("Testing corrected options...")
validate_options(corrected_options)
def find_option_info(search_term):
"""Find and display information about options."""
opts = cma.CMAOptions(search_term)
print(f"Options matching '{search_term}':")
for key, value in opts.items():
print(f" {key}: {value}")
return opts
# Run validation tests
debug_option_conflicts()
# Search for specific options
find_option_info('timeout')
find_option_info('bound')
find_option_info('sigma')
# Comprehensive option listing
all_opts = cma.CMAOptions()
versatile_opts = [k for k, v in all_opts.items() if ' #v ' in str(v)]
print(f"\nTotal options: {len(all_opts)}")
print(f"Versatile options (can be changed during optimization): {len(versatile_opts)}")
print("Sample versatile options:", versatile_opts[:10])
validate_and_debug_config()Install with Tessl CLI
npx tessl i tessl/pypi-cma