SCE-UA is a lightweight Python package implementing the Shuffled Complex Evolution (SCE-UA) algorithm for global optimization. Designed primarily for hydrological model calibration, it leverages NumPy and SciPy for efficient computation and seamless integration into Python workflows.
Full documentation is available at sceua.readthedocs.io.
This implementation of the SCE-UA algorithm incorporates several major improvements from the literature over the original 1994 version. These enhancements include:
- Adaptive smoothing parameter (ΞΈ) that adjusts based on problem scale, improving numerical stability and convergence.
- Latin Hypercube Sampling (LHS) for initial population generation, ensuring better parameter space coverage compared to uniform random sampling.
- PCA-based recovery mechanism to detect and restore lost dimensions in the population.
- Best solution inclusion in every complex to accelerate convergence.
- Optimized complex evolution strategy with enhanced reflection, contraction, and mutation operations.
- Automatic parameter determination with sensible defaults based on problem dimensionality.
- Comprehensive convergence criteria, including function value tolerance, parameter tolerance, and maximum iterations.
Additionally, the package offers:
- Multithreading support for parallel objective function evaluations using threading.
- Detailed results object providing in-depth insights into the optimization process suitable for further analysis and visualization.
- Type hinting and modern Python implementation, ensuring maintainability and adherence to best coding practices.
Choose your preferred installation method:
pip install sceua
micromamba install -c conda-forge sceua
Alternatively, you can use conda
or mamba
.
The SCE-UA package has one main function called minimize
, which is used to optimize a
given objective function. The API follows a similar pattern to scipy.optimize.minimize
for easy adoption.
The most important tuning parameters are n_complexes
and n_points_complex
for all cases, while pca_freq
and pca_tol
are particularly relevant for
problems with highly correlated parameters and/or high dimensionality. Default values
are set to reasonable standards, but you can adjust them as needed for your specific
problem.
For more details, refer to the API reference.
The signature for the objective function can be either:
def objective(params: FloatArray) -> float:
"""Objective function to minimize."""
# Your implementation here
or
def objective(params: FloatArray, *args: Any) -> float:
"""Objective function to minimize."""
# Your implementation here
where params
is a NumPy array of parameters to optimize, and args
is a tuple of
additional arguments to pass to the objective function. The function should return a
single floating-point value representing the objective function value.
Here's a simple example of how to use the package:
from typing import Any
import numpy as np
from numpy.typing import NDArray
import sceua
FloatArray = NDArray[np.floating[Any]]
def objective(params: FloatArray, *args: Any) -> float:
"""Objective function to minimize."""
sim_arg1, sim_arg2, obs = args
sim = simulation_func(params, sim_arg1, sim_arg2)
return metric_func(sim, obs)
# Define parameter bounds as a sequence of (min, max) pairs
bounds = [(lower1, upper1), (lower2, upper2), ..., (lowerN, upperN)]
# Run optimization
result = sceua.minimize(objective, bounds, args=(sim_arg1, sim_arg2, obs), seed=42, max_workers=8)
# Access the optimization results
best_params = result.x
best_function_value = result.fun
num_iterations = result.nit
num_function_evaluations = result.nfev
The result
object contains the following attributes:
x
(numpy.ndarray
): Best parameters found.fun
(float
): Best function value corresponding to the best parameters.nit
(int
): Number of iterations.nfev
(int
): Number of function evaluations.message
(str
): Message describing the termination reason.success
(bool
): Whether the optimization was successful.xv
(numpy.ndarray
): All evaluated parameter sets.funv
(numpy.ndarray
): Function values for all evaluated parameter sets.
The result attributes can be used to create convergence plots and analyze optimization performance:
import matplotlib.pyplot as plt
_, ax1 = plt.subplots()
ax1.plot(np.minimum.accumulate(results.funv))
ax2 = ax1.twinx()
ax2.set_yscale("log")
ax2.plot(np.cumsum(results.funv - true_min), color="r")
Check the docs for more examples and API details.
This package is based on the following references:
- Duan, Q., Sorooshian, S., & Gupta, V. K. (1992). Effective and efficient global optimization for conceptual rainfall-runoff models. Water Resources Research, 28(4), 1015-1031. doi:10.1029/91WR02985
- Duan, Q., Gupta, V. K., & Sorooshian, S. (1994). Optimal use of the SCE-UA global optimization method for calibrating watershed models. Journal of Hydrology, 158(3-4), 265-284. doi:10.1016/0022-1694(94)90057-4
- Duan, Q., Sorooshian, S., & Gupta, V. K. (1994). A shuffled complex evolution approach for effective and efficient global minimization. Journal of optimization theory and applications, 76(3), 501-521. doi:10.1007/BF00939380
- Muttil, N., & Jayawardena, A. W. (2008). Shuffled Complex Evolution model calibrating algorithm: enhancing its robustness and efficiency. Hydrological Processes, 22(23), 4628-4638. Portico. doi:10.1002/hyp.7082
- Chu, W., Gao, X., & Sorooshian, S. (2010). Improving the shuffled complex evolution scheme for optimization of complex nonlinear hydrological systems: Application to the calibration of the Sacramento soil-moisture accounting model. Water Resources Research, 46(9). Portico. doi:10.1029/2010wr009224
Additionally, some ideas were inspired by UQPyL and SAMBO Python packages.
We welcome contributions! Please see the contributing section for guidelines and instructions.
This project is licensed under the MIT License - see the LICENSE file for details.