CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-cma

CMA-ES, Covariance Matrix Adaptation Evolution Strategy for non-linear numerical optimization in Python

Pending

Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

Overview
Eval results
Files

fitness-functions.mddocs/

Fitness Functions and Testing

Comprehensive collection of test functions, benchmark problems, and fitness transformations for algorithm testing, validation, and performance evaluation.

Test Function Collection (ff module)

The ff module provides a rich collection of test functions commonly used in optimization research and algorithm benchmarking. All functions are accessible via cma.ff.<function_name>.

Complete Function List

# Complete list of available test functions in cma.ff module
import cma

# Basic quadratic functions
cma.ff.sphere        # Sphere function: sum(x**2)
cma.ff.elli          # Ellipsoid function with conditioning
cma.ff.cigar         # Cigar function: x[0]**2 + 1e6*sum(x[1:]**2)
cma.ff.tablet        # Tablet function: 1e6*x[0]**2 + sum(x[1:]**2)
cma.ff.twoaxes       # Two-axes function with group separability
cma.ff.ellirot       # Rotated ellipsoid function

# Multi-modal functions
cma.ff.rosen         # Rosenbrock function
cma.ff.diffpowell    # Different powers function
cma.ff.rastrigin     # Rastrigin function with many local minima
cma.ff.schwefel      # Schwefel function
cma.ff.griewank      # Griewank function
cma.ff.ackley        # Ackley function

# Noise and randomness
cma.ff.noise         # Add Gaussian noise to any function
cma.ff.noisysphere   # Noisy sphere function
cma.ff.spherenoise   # Sphere with added noise

# Step functions and plateaus
cma.ff.step          # Step function
cma.ff.parab         # Parabolic ridge function

# Composition functions
cma.ff.composed      # Composition of multiple functions

# Special test cases
cma.ff.optprob       # Optimization problem wrapper
cma.ff.warped        # Warped/transformed function space

Basic Test Functions

# Access test functions through cma.ff
import cma

# Basic quadratic functions
def sphere(x):
    """
    Sphere function - simplest quadratic test function.
    
    Global minimum: f(0, ..., 0) = 0
    Properties: Unimodal, separable, quadratic
    """
    return sum(x**2)

def elli(x, cond=1e6):
    """
    Ellipsoid function - ill-conditioned quadratic.
    
    Parameters:
    -----------
    x : array-like
        Input vector.
    cond : float, optional
        Condition number (default 1e6).
        
    Global minimum: f(0, ..., 0) = 0
    Properties: Unimodal, separable, ill-conditioned
    """
    N = len(x)
    return sum(cond**(np.arange(N) / (N - 1 + 1e-9)) * np.asarray(x)**2)

# Usage examples
>>> import cma
>>> 
>>> # Sphere function
>>> f_val = cma.ff.sphere([1, 2, 3])  # Returns 14.0
>>> 
>>> # Ellipsoid with different condition numbers
>>> f_val = cma.ff.elli([1, 1, 1])  # Default condition 1e6
>>> f_val = cma.ff.elli([1, 1, 1], cond=100)  # Condition number 100
>>> 
>>> # Use in optimization
>>> x, es = cma.fmin2(cma.ff.sphere, [1, 2, 3], 0.5)
>>> x, es = cma.fmin2(cma.ff.elli, [1, 2, 3], 0.5)

Non-Separable Test Functions

# Non-separable functions available through cma.ff
import cma

# Cigar function - one dominant direction
>>> def cigar_example():
...     """Cigar function: x[0]^2 + cond * sum(x[1:]^2)"""
...     x, es = cma.fmin2(cma.ff.cigar, [1, 2, 3, 4], 0.5)
...     print(f"Cigar result: {x}")
...     return x, es

# Tablet function - one weak direction  
>>> def tablet_example():
...     """Tablet function: cond * x[0]^2 + sum(x[1:]^2)"""
...     x, es = cma.fmin2(cma.ff.tablet, [1, 2, 3, 4], 0.5) 
...     print(f"Tablet result: {x}")
...     return x, es

# Two-axes function - group separability
>>> def twoaxes_example():
...     """Two-axes function with different conditioning"""
...     x, es = cma.fmin2(cma.ff.twoaxes, 6 * [0.5], 0.3)
...     print(f"Two-axes result: {x}")
...     return x, es

# Rotated ellipsoid - no separability
>>> def ellirot_example():
...     """Rotated ellipsoid - tests rotation invariance"""
...     x, es = cma.fmin2(cma.ff.ellirot, [1, 2, 3], 0.5)
...     print(f"Rotated ellipsoid result: {x}")
...     return x, es

Multi-Modal Test Functions

# Multi-modal and difficult functions
import cma
import numpy as np

# Rosenbrock function - classic benchmark
>>> def rosenbrock_example():
...     """Rosenbrock function - narrow curved valley"""
...     # The Rosenbrock function is available as cma.ff.rosen
...     x, es = cma.fmin2(cma.ff.rosen, 4 * [0], 0.5)
...     print(f"Rosenbrock result: {x}")  # Should be close to [1, 1, 1, 1]
...     return x, es

# Rastrigin function - many local minima
>>> def rastrigin_example():
...     """Rastrigin function - highly multi-modal"""
...     # Note: Rastrigin may be in BBOB collection
...     def rastrigin(x):
...         A = 10
...         n = len(x)
...         return A * n + sum(xi**2 - A * np.cos(2 * np.pi * xi) for xi in x)
...     
...     x, es = cma.fmin2(rastrigin, 5 * [2.0], 1.0, 
...                       options={'maxfevals': 10000})
...     print(f"Rastrigin result: {x}")
...     return x, es

# Ackley function - many local minima with global structure
>>> def ackley_example():
...     """Ackley function - exponential multi-modal"""
...     def ackley(x):
...         x = np.asarray(x)
...         n = len(x)
...         return (-20 * np.exp(-0.2 * np.sqrt(sum(x**2) / n)) - 
...                 np.exp(sum(np.cos(2 * np.pi * xi) for xi in x) / n) + 
...                 20 + np.e)
...     
...     x, es = cma.fmin2(ackley, 3 * [1.0], 0.5)
...     print(f"Ackley result: {x}")
...     return x, es

Constrained and Special Test Functions

# Special test functions with constraints or unusual properties
import cma
import numpy as np

# Functions with constraints built-in
>>> def constrained_sphere_example():
...     """Sphere function with constraint x[0] > 1"""
...     x, es = cma.fmin2(cma.ff.spherewithoneconstraint, [2, 1, 1], 0.3)
...     print(f"Constrained sphere result: {x}")
...     return x, es

# Asymmetric functions
>>> def sectorsphere_example():
...     """Asymmetric sphere - different scaling for negative values"""  
...     x, es = cma.fmin2(cma.ff.sectorsphere, [1, -1, 0], 0.5)
...     print(f"Sector sphere result: {x}")
...     return x, es

# Functions with corners/boundaries
>>> def cornersphere_example():
...     """Sphere function constrained to corner x >= 1"""
...     x, es = cma.fmin2(cma.ff.cornersphere, [1.5, 1.5, 1.5], 0.2)
...     print(f"Corner sphere result: {x}")
...     return x, es

# Noisy functions
>>> def noisy_sphere_example():
...     """Sphere function with multiplicative noise"""
...     x, es = cma.fmin2(cma.ff.noisysphere, [1, 1, 1], 0.5,
...                       noise_handler=cma.NoiseHandler(3))
...     print(f"Noisy sphere result: {x}")
...     return x, es

# Functions with different dimensions of influence
>>> def subspace_sphere_example():
...     """Sphere function in random subspace"""
...     x, es = cma.fmin2(cma.ff.subspace_sphere, 10 * [0.5], 0.3)
...     print(f"Subspace sphere result: {x}")
...     return x, es

Complete Test Function Reference

# Complete list of available test functions in cma.ff
import cma

# Get all available functions
ff_functions = {
    # Basic unimodal functions
    'sphere': cma.ff.sphere,           # sum(x^2)
    'elli': cma.ff.elli,              # Ellipsoid with condition number
    'cigar': cma.ff.cigar,            # One large eigenvalue
    'tablet': cma.ff.tablet,          # One small eigenvalue  
    'twoaxes': cma.ff.twoaxes,        # Two groups of eigenvalues
    'ellirot': cma.ff.ellirot,        # Rotated ellipsoid
    'hyperelli': cma.ff.hyperelli,    # Hyperellipsoid
    
    # Multi-modal functions  
    'rosen': cma.ff.rosen,            # Rosenbrock function
    
    # Functions with constraints/boundaries
    'spherewithoneconstraint': cma.ff.spherewithoneconstraint,
    'cornersphere': cma.ff.cornersphere,
    'cornerelli': cma.ff.cornerelli,
    'sectorsphere': cma.ff.sectorsphere,
    
    # Noisy functions
    'noisysphere': cma.ff.noisysphere,
    
    # Special/research functions
    'subspace_sphere': cma.ff.subspace_sphere,
    'partsphere': cma.ff.partsphere,
    'linear': cma.ff.linear,
    'rand': cma.ff.rand,
    
    # Gradient functions (for testing)
    'grad_sphere': cma.ff.grad_sphere,
    'grad_cigar': cma.ff.grad_cigar,
    'grad_tablet': cma.ff.grad_tablet,
}

# Usage pattern for testing multiple functions
def test_multiple_functions():
    """Test CMA-ES on multiple benchmark functions."""
    
    results = {}
    
    for name, func in ff_functions.items():
        if name.startswith('grad_'):  # Skip gradient functions
            continue
            
        try:
            print(f"Testing {name}...")
            x, es = cma.fmin2(func, 3 * [0.5], 0.3, 
                              options={'maxfevals': 1000, 'verbose': -9})
            
            results[name] = {
                'success': es.result.fbest < 1e-6,
                'evaluations': es.result.evaluations,
                'final_value': es.result.fbest,
                'solution': es.result.xbest
            }
            
        except Exception as e:
            results[name] = {'error': str(e)}
            
    return results

# Run comprehensive test
results = test_multiple_functions()
for func_name, result in results.items():
    if 'error' not in result:
        print(f"{func_name}: {'✓' if result['success'] else '✗'} "
              f"({result['evaluations']} evals, f = {result['final_value']:.2e})")

BBOB Benchmark Functions

The Black-Box Optimization Benchmarking (BBOB) test suite provides standardized benchmark problems.

BBOB Function Access

import cma

# Access BBOB functions
bbob = cma.ff.BBOB  # or cma.bbobbenchmarks

# BBOB provides 24 test functions in various problem dimensions
# Functions are grouped by properties:

# Group 1: Separable functions (f1-f5)
separable_functions = {
    1: "Sphere",
    2: "Ellipsoid separable", 
    3: "Rastrigin separable",
    4: "Skew Rastrigin-Bueche separable",
    5: "Linear slope"
}

# Group 2: Functions with low or moderate conditioning (f6-f9) 
moderate_functions = {
    6: "Attractive sector",
    7: "Step-ellipsoid", 
    8: "Rosenbrock original",
    9: "Rosenbrock rotated"
}

# Group 3: Functions with high conditioning and unimodal (f10-f14)
unimodal_functions = {
    10: "Ellipsoid",
    11: "Discus", 
    12: "Bent cigar",
    13: "Sharp ridge", 
    14: "Different powers"
}

# Group 4: Multi-modal functions with adequate global structure (f15-f19)
multimodal_adequate = {
    15: "Rastrigin",
    16: "Weierstrass",
    17: "Schaffers F7, condition 10",
    18: "Schaffers F7, condition 1000", 
    19: "Griewank-Rosenbrock F8F2"
}

# Group 5: Multi-modal functions with weak global structure (f20-f24)
multimodal_weak = {
    20: "Schwefel",
    21: "Gallagher 101 peaks",
    22: "Gallagher 21 peaks", 
    23: "Katsuuras",
    24: "Lunacek bi-Rastrigin"
}

# Example usage
def bbob_function_example():
    """Example using BBOB benchmark functions."""
    
    try:
        # Test multiple BBOB functions
        for func_id in [1, 8, 15, 20]:  # Representative from each group
            
            # Create function instance
            f = bbob.F(func_id, instance=1, dimension=5)
            
            print(f"Testing F{func_id} ({separable_functions.get(func_id, 'Other')})")
            
            # Optimize with CMA-ES
            x, es = cma.fmin2(f, 5 * [0], 0.5, 
                              options={'maxfevals': 2000, 'verbose': -9})
                              
            print(f"  Result: f = {es.result.fbest:.2e} in {es.result.evaluations} evals")
            
    except ImportError:
        print("BBOB benchmarks not available. Install with: pip install cma[bbob]")
    
    return

bbob_function_example()

BBOB Usage Patterns

import cma

def bbob_systematic_testing():
    """Systematic testing on BBOB benchmark suite."""
    
    try:
        bbob = cma.bbobbenchmarks
        
        # Test configuration
        dimensions = [2, 5, 10]
        function_ids = range(1, 25)  # All BBOB functions
        instances = [1, 2, 3]        # Multiple instances per function
        
        results = {}
        
        for dim in dimensions:
            results[dim] = {}
            
            for fid in function_ids:
                results[dim][fid] = {}
                
                for inst in instances:
                    # Create BBOB function
                    f = bbob.F(fid, instance=inst, dimension=dim)
                    
                    # Optimize with CMA-ES
                    x, es = cma.fmin2(
                        f, dim * [0], 0.5,
                        options={
                            'maxfevals': 100 * dim**2,  # Budget scales with dimension
                            'ftarget': 1e-8,
                            'verbose': -9
                        }
                    )
                    
                    # Record result
                    results[dim][fid][inst] = {
                        'fbest': es.result.fbest,
                        'evaluations': es.result.evaluations,
                        'success': es.result.fbest < 1e-8
                    }
                    
                    print(f"F{fid:2d} D{dim:2d} I{inst}: "
                          f"{'✓' if results[dim][fid][inst]['success'] else '✗'} "
                          f"({results[dim][fid][inst]['evaluations']} evals)")
        
        return results
        
    except ImportError:
        print("BBOB not available. Use: pip install cma[bbob]")
        return None

# Run systematic test (comment out for large-scale testing)
# results = bbob_systematic_testing()

Fitness Transformations

Tools for modifying and composing objective functions to create more challenging or realistic optimization problems.

ScaleCoordinates - Coordinate Scaling

class ScaleCoordinates:
    """
    Scale and shift coordinate systems for fitness functions.
    
    Allows transformation of variables to create ill-conditioned problems
    or to adapt functions to specific domains.
    """
    
    def __init__(self, function, multipliers=None, zero=None, 
                 upper=None, lower=None):
        """
        Create coordinate-scaled function wrapper.
        
        Parameters:
        -----------
        function : callable
            Original fitness function to transform.
            
        multipliers : array-like, optional
            Scaling factors per coordinate. If shorter than input dimension,
            last value is recycled.
            
        zero : array-like, optional  
            Offset in original coordinate system (preimage space).
            
        upper, lower : array-like, optional
            Domain bounds. Creates scaling: f(lower + (upper-lower) * x).
            
        Examples:
        ---------
        >>> import cma
        >>> from cma.fitness_transformations import ScaleCoordinates
        >>> 
        >>> # Scale coordinates with different factors
        >>> scaled_sphere = ScaleCoordinates(
        ...     cma.ff.sphere, 
        ...     multipliers=[1, 10, 100]  # Different scales per coordinate
        ... )
        >>> 
        >>> # Result: f([x0, x1, x2]) = x0^2 + (10*x1)^2 + (100*x2)^2
        >>> result = scaled_sphere([1, 1, 1])  # = 1 + 100 + 10000 = 10101
        >>> 
        >>> # Domain transformation [0,1]^n -> [lower, upper]^n
        >>> domain_sphere = ScaleCoordinates(
        ...     cma.ff.sphere,
        ...     lower=[-5, -10], 
        ...     upper=[5, 10]
        ... )
        >>> 
        >>> # Now x in [0,1] maps to [-5,5] x [-10,10] domain
        >>> x, es = cma.fmin2(domain_sphere, [0.5, 0.5], 0.2)
        >>> 
        >>> # Ill-conditioned problem creation
        >>> ill_conditioned = ScaleCoordinates(
        ...     cma.ff.sphere,
        ...     multipliers=[1, 1e3, 1e6]  # Condition number 1e12
        ... )
        >>> 
        >>> x, es = cma.fmin2(ill_conditioned, [1, 1, 1], 0.1)
        """
        pass

# Usage examples
def scaling_examples():
    """Examples of coordinate scaling transformations."""
    
    from cma.fitness_transformations import ScaleCoordinates
    import cma
    
    # Example 1: Create ill-conditioned sphere
    def ill_conditioned_example():
        """Create highly ill-conditioned optimization problem."""
        
        # Original sphere function
        def sphere(x):
            return sum(x**2)
        
        # Scale with exponentially increasing factors
        scales = [10**(i/2) for i in range(5)]  # [1, ~3.16, 10, ~31.6, 100]
        
        scaled_sphere = ScaleCoordinates(sphere, multipliers=scales)
        
        print(f"Scales: {scales}")
        
        # Optimize scaled version
        x, es = cma.fmin2(scaled_sphere, 5 * [1], 0.3,
                          options={'maxfevals': 3000})
        
        print(f"Scaled sphere result: {x}")
        print(f"Condition number effect visible in solution scaling")
        
        return x, es
    
    # Example 2: Domain mapping
    def domain_mapping_example():
        """Map optimization to specific domain."""
        
        # Want to optimize in domain x1 ∈ [-10, 10], x2 ∈ [0, 100]
        domain_sphere = ScaleCoordinates(
            cma.ff.sphere,
            lower=[-10, 0],
            upper=[10, 100]
        )
        
        # Optimize in [0,1]^2 space
        x_unit, es = cma.fmin2(domain_sphere, [0.5, 0.5], 0.2)
        
        # Transform back to original domain
        x_original = [-10 + 20*x_unit[0], 0 + 100*x_unit[1]]
        
        print(f"Unit domain result: {x_unit}")
        print(f"Original domain result: {x_original}")
        
        return x_unit, x_original
    
    # Example 3: Different scales per coordinate group
    def grouped_scaling_example():
        """Scale different groups of coordinates differently."""
        
        # 6D problem: scale first 2 coordinates x1, last 4 coordinates x1000  
        scales = [1, 1, 1000, 1000, 1000, 1000]
        
        grouped_sphere = ScaleCoordinates(cma.ff.sphere, multipliers=scales)
        
        x, es = cma.fmin2(grouped_sphere, 6 * [0.1], 0.3)
        
        print(f"Grouped scaling result: {x}")
        print(f"Notice different scales in solution components")
        
        return x, es
    
    ill_conditioned_example()
    domain_mapping_example()  
    grouped_scaling_example()

scaling_examples()

GlueArguments - Function Argument Binding

class GlueArguments:
    """
    DEPRECATED: Use functools.partial instead.
    
    Bind additional arguments to fitness functions.
    """
    
    def __init__(self, fitness_function, *args, **kwargs):
        """
        Create function with bound arguments.
        
        Parameters:
        -----------
        fitness_function : callable
            Function to wrap.
        *args : tuple
            Positional arguments to append.
        **kwargs : dict  
            Keyword arguments to bind.
            
        Examples:
        ---------
        >>> import cma
        >>> from cma.fitness_transformations import GlueArguments
        >>> 
        >>> # Create ellipsoid with specific condition number
        >>> elli_1e4 = GlueArguments(cma.ff.elli, cond=1e4)
        >>> result = elli_1e4([1, 1, 1])  # Uses cond=1e4
        >>> 
        >>> # Better: use functools.partial (recommended)
        >>> import functools  
        >>> elli_1e4_better = functools.partial(cma.ff.elli, cond=1e4)
        >>> result = elli_1e4_better([1, 1, 1])
        """
        pass

# Modern alternative using functools.partial
def function_binding_examples():
    """Examples of binding arguments to fitness functions."""
    
    import functools
    import cma
    
    # Example 1: Create specialized test functions
    def specialized_functions():
        """Create specialized versions of test functions."""
        
        # Ellipsoids with different condition numbers
        elli_easy = functools.partial(cma.ff.elli, cond=100)
        elli_hard = functools.partial(cma.ff.elli, cond=1e8)
        
        # Test both versions
        x1, es1 = cma.fmin2(elli_easy, [1, 1, 1], 0.5, 
                           options={'maxfevals': 1000, 'verbose': -9})
        
        x2, es2 = cma.fmin2(elli_hard, [1, 1, 1], 0.5,
                           options={'maxfevals': 1000, 'verbose': -9})
        
        print(f"Easy ellipsoid (cond=100): {es1.result.evaluations} evals")
        print(f"Hard ellipsoid (cond=1e8): {es2.result.evaluations} evals")
        
        return (x1, es1), (x2, es2)
    
    # Example 2: Parametric function families
    def parametric_functions():
        """Create parametric function families."""
        
        # Generalized sphere function: sum((x - center)^p)
        def generalized_sphere(x, center=None, p=2):
            x = np.asarray(x)
            if center is not None:
                x = x - np.asarray(center)
            return sum(np.abs(x)**p)
        
        # Create family of functions
        functions = {
            'sphere_origin_L2': functools.partial(generalized_sphere, center=[0, 0], p=2),
            'sphere_shifted_L2': functools.partial(generalized_sphere, center=[1, 1], p=2), 
            'sphere_origin_L1': functools.partial(generalized_sphere, center=[0, 0], p=1),
            'sphere_origin_L4': functools.partial(generalized_sphere, center=[0, 0], p=4),
        }
        
        # Test all variants
        results = {}
        for name, func in functions.items():
            x, es = cma.fmin2(func, [2, 2], 0.5, 
                              options={'maxfevals': 1500, 'verbose': -9})
            results[name] = (x, es.result.fbest, es.result.evaluations)
            print(f"{name}: x={x}, f={es.result.fbest:.2e}, evals={es.result.evaluations}")
        
        return results
    
    # Example 3: Noisy function variants
    def noisy_function_variants():
        """Create functions with different noise characteristics."""
        
        def noisy_sphere(x, noise_std=0.1, noise_type='additive'):
            base_value = sum(x**2)
            
            if noise_type == 'additive':
                return base_value + noise_std * np.random.randn()
            elif noise_type == 'multiplicative':
                return base_value * (1 + noise_std * np.random.randn())
            else:
                return base_value
        
        # Create noise variants
        noise_variants = {
            'clean': functools.partial(noisy_sphere, noise_std=0),
            'low_noise': functools.partial(noisy_sphere, noise_std=0.01),
            'high_noise': functools.partial(noisy_sphere, noise_std=0.1), 
            'multiplicative': functools.partial(noisy_sphere, noise_std=0.05, 
                                              noise_type='multiplicative')
        }
        
        # Test with noise handling
        for name, func in noise_variants.items():
            noise_handler = cma.NoiseHandler(3, maxevals=[1, 2, 10]) if 'noise' in name else None
            
            x, es = cma.fmin2(func, [1, 1, 1], 0.3,
                              noise_handler=noise_handler,
                              options={'maxfevals': 2000, 'verbose': -9})
            
            print(f"{name}: final f = {es.result.fbest:.2e}")
    
    specialized_functions()
    parametric_functions()
    noisy_function_variants()

function_binding_examples()

Function Composition and Advanced Transformations

# Advanced function transformations and compositions
import cma
import numpy as np
from cma.fitness_transformations import ScaleCoordinates
import functools

def advanced_transformations():
    """Advanced fitness function transformations and compositions."""
    
    # Example 1: Rotation + Scaling composition
    def rotation_scaling_composition():
        """Combine rotation and scaling transformations."""
        
        from cma.transformations import Rotation
        
        # Create rotated and scaled function
        def rotated_scaled_sphere(x, rotation_matrix=None, scales=None):
            x = np.asarray(x)
            
            # Apply rotation
            if rotation_matrix is not None:
                x = rotation_matrix @ x
            
            # Apply scaling  
            if scales is not None:
                x = x * np.asarray(scales)
                
            return sum(x**2)
        
        # Create rotation matrix
        np.random.seed(42)  # For reproducibility
        rotation = Rotation()
        R = rotation(len=3)  # 3D rotation matrix
        
        # Create composed function
        composed_func = functools.partial(
            rotated_scaled_sphere,
            rotation_matrix=R,
            scales=[1, 10, 100]
        )
        
        # Optimize
        x, es = cma.fmin2(composed_func, [1, 1, 1], 0.5)
        
        print(f"Rotation+scaling result: {x}")
        return x, es
    
    # Example 2: Multi-objective to single-objective
    def multiobjective_scalarization():
        """Convert multi-objective to single-objective via scalarization."""
        
        def multiobjective_function(x):
            """Example multi-objective function returning [f1, f2]."""
            f1 = sum(x**2)                    # Minimize distance from origin
            f2 = sum((x - 1)**2)             # Minimize distance from [1,1,...]
            return [f1, f2]
        
        # Weighted sum scalarization
        def weighted_sum_scalarization(x, weights=[0.5, 0.5]):
            objectives = multiobjective_function(x)
            return sum(w * f for w, f in zip(weights, objectives))
        
        # Different weight combinations
        weight_sets = [
            [1.0, 0.0],    # Focus on f1
            [0.0, 1.0],    # Focus on f2  
            [0.5, 0.5],    # Equal weights
            [0.8, 0.2],    # Prefer f1
        ]
        
        results = {}
        for i, weights in enumerate(weight_sets):
            scalarized = functools.partial(weighted_sum_scalarization, weights=weights)
            
            x, es = cma.fmin2(scalarized, [0.5, 0.5, 0.5], 0.3,
                              options={'maxfevals': 1000, 'verbose': -9})
            
            # Evaluate both objectives at solution
            objectives = multiobjective_function(x)
            results[f"weights_{weights}"] = {
                'solution': x,
                'f1': objectives[0], 
                'f2': objectives[1],
                'weighted_sum': scalarized(x)
            }
            
            print(f"Weights {weights}: x={x}, f1={objectives[0]:.3f}, f2={objectives[1]:.3f}")
        
        return results
    
    # Example 3: Time-varying fitness landscape
    def time_varying_function():
        """Create time-varying fitness function."""
        
        evaluation_counter = [0]  # Mutable counter
        
        def dynamic_sphere(x, period=100, amplitude=1.0):
            """Sphere function with moving optimum."""
            evaluation_counter[0] += 1
            
            # Moving optimum based on evaluation count
            t = evaluation_counter[0] / period
            optimum = amplitude * np.array([np.sin(t), np.cos(t), 0])
            
            return sum((x - optimum)**2)
        
        # Optimize dynamic function
        x, es = cma.fmin2(dynamic_sphere, [0, 0, 0], 0.5,
                          options={'maxfevals': 2000, 'verb_disp': 100})
        
        print(f"Dynamic function result: {x}")
        print(f"Total evaluations: {evaluation_counter[0]}")
        
        return x, es
    
    # Example 4: Constraint violation penalty
    def penalty_method_transformation():
        """Transform constrained to unconstrained via penalty method."""
        
        def constrained_objective(x):
            """Original objective: minimize x^2."""
            return sum(x**2)
        
        def constraints(x):
            """Constraints: g(x) <= 0."""
            return [
                x[0] + x[1] - 1,      # x[0] + x[1] <= 1
                x[0]**2 + x[1]**2 - 4  # x[0]^2 + x[1]^2 <= 4
            ]
        
        def penalty_function(x, penalty_factor=1000):
            """Unconstrained function with penalty for violations."""
            obj_val = constrained_objective(x)
            
            # Add penalty for constraint violations
            g_vals = constraints(x)
            penalty = sum(max(0, g)**2 for g in g_vals)
            
            return obj_val + penalty_factor * penalty
        
        # Optimize with different penalty factors
        penalty_factors = [10, 100, 1000, 10000]
        
        for pf in penalty_factors:
            penalized = functools.partial(penalty_function, penalty_factor=pf)
            
            x, es = cma.fmin2(penalized, [0.5, 0.5], 0.3,
                              options={'maxfevals': 2000, 'verbose': -9})
            
            # Check constraint satisfaction
            g_vals = constraints(x)
            feasible = all(g <= 1e-6 for g in g_vals)
            
            print(f"Penalty {pf}: x={x}, feasible={feasible}, "
                  f"obj={constrained_objective(x):.4f}")
    
    rotation_scaling_composition()
    multiobjective_scalarization()
    time_varying_function()
    penalty_method_transformation()

advanced_transformations()

Testing and Validation Utilities

Tools for systematic testing and algorithm validation.

import cma
import numpy as np
import time

def algorithm_testing_suite():
    """Comprehensive testing suite for CMA-ES validation."""
    
    class OptimizationTester:
        """Systematic testing framework for optimization algorithms."""
        
        def __init__(self):
            self.results = {}
            
        def test_function_suite(self, algorithm_func, test_functions, 
                              dimensions=[2, 5, 10], repetitions=5):
            """Test algorithm on suite of functions."""
            
            for func_name, func in test_functions.items():
                self.results[func_name] = {}
                
                for dim in dimensions:
                    self.results[func_name][dim] = {
                        'successes': 0,
                        'evaluations': [],
                        'final_values': [],
                        'times': []
                    }
                    
                    for rep in range(repetitions):
                        start_time = time.time()
                        
                        try:
                            # Run optimization
                            x, es = algorithm_func(func, dim * [0.5], 0.3)
                            
                            elapsed = time.time() - start_time
                            
                            # Record results
                            success = es.result.fbest < 1e-6
                            if success:
                                self.results[func_name][dim]['successes'] += 1
                                
                            self.results[func_name][dim]['evaluations'].append(
                                es.result.evaluations)
                            self.results[func_name][dim]['final_values'].append(
                                es.result.fbest)
                            self.results[func_name][dim]['times'].append(elapsed)
                            
                        except Exception as e:
                            print(f"Error on {func_name} D{dim} rep{rep}: {e}")
                            
        def print_summary(self):
            """Print summary of test results."""
            
            print("\nOptimization Test Summary")
            print("=" * 50)
            
            for func_name in self.results:
                print(f"\nFunction: {func_name}")
                
                for dim in sorted(self.results[func_name].keys()):
                    result = self.results[func_name][dim]
                    
                    success_rate = result['successes'] / len(result['evaluations'])
                    avg_evals = np.mean(result['evaluations']) if result['evaluations'] else 0
                    avg_time = np.mean(result['times']) if result['times'] else 0
                    
                    print(f"  D{dim:2d}: {success_rate:4.1%} success, "
                          f"{avg_evals:6.0f} evals, {avg_time:5.2f}s")
    
    # Define test function suite
    test_functions = {
        'sphere': cma.ff.sphere,
        'elli': cma.ff.elli, 
        'cigar': cma.ff.cigar,
        'tablet': cma.ff.tablet,
        'rosen': cma.ff.rosen,
        'ellirot': cma.ff.ellirot
    }
    
    # Test CMA-ES with different configurations
    def test_cmaes_basic(func, x0, sigma0):
        """Basic CMA-ES test."""
        return cma.fmin2(func, x0, sigma0, 
                        options={'maxfevals': 1000 * len(x0)**2, 'verbose': -9})
    
    def test_cmaes_large_pop(func, x0, sigma0):
        """CMA-ES with large population."""
        return cma.fmin2(func, x0, sigma0,
                        options={'maxfevals': 1000 * len(x0)**2, 
                                'popsize_factor': 2, 'verbose': -9})
    
    # Run tests
    tester = OptimizationTester()
    
    print("Testing basic CMA-ES...")
    tester.test_function_suite(test_cmaes_basic, test_functions, 
                              dimensions=[2, 5], repetitions=3)
    
    tester.print_summary()
    
    return tester

def performance_profiling():
    """Profile performance characteristics of different functions."""
    
    import time
    
    functions_to_profile = {
        'sphere': cma.ff.sphere,
        'elli': functools.partial(cma.ff.elli, cond=1e6),
        'rosen': cma.ff.rosen,
        'noisy_sphere': functools.partial(cma.ff.noisysphere, noise=0.01)
    }
    
    dimensions = [2, 5, 10, 20]
    
    print("Performance Profiling Results")
    print("=" * 40)
    
    for func_name, func in functions_to_profile.items():
        print(f"\nFunction: {func_name}")
        
        for dim in dimensions:
            # Time single evaluation
            x = np.random.randn(dim)
            
            start_time = time.time()
            for _ in range(1000):  # 1000 evaluations
                _ = func(x)
            elapsed = time.time() - start_time
            
            evals_per_sec = 1000 / elapsed
            
            print(f"  D{dim:2d}: {evals_per_sec:8.0f} evals/sec")

# Run testing suite (comment out for large-scale testing)
# tester = algorithm_testing_suite()
performance_profiling()

This comprehensive fitness functions documentation covers:

  1. Basic Test Functions - Fundamental functions like sphere, ellipsoid, and cigar
  2. Multi-Modal Functions - Rosenbrock, Rastrigin, Ackley for challenging optimization
  3. BBOB Benchmark Suite - Standardized benchmark functions for algorithm comparison
  4. Fitness Transformations - ScaleCoordinates, GlueArguments for function modification
  5. Advanced Transformations - Complex compositions and multi-objective handling
  6. Testing Utilities - Systematic testing and validation frameworks

The documentation provides complete API references with practical usage examples for algorithm testing, benchmarking, and validation.

Install with Tessl CLI

npx tessl i tessl/pypi-cma

docs

advanced-optimization.md

configuration.md

constraints-boundaries.md

core-optimization.md

fitness-functions.md

index.md

logging-analysis.md

samplers-adaptation.md

tile.json