Source code for cann.optim.differential_evolution

from typing import Callable, Tuple, Dict, Any, List
import numpy as np
from scipy.optimize import differential_evolution
from cann.engine.calibration_config import CalibrationConfig


[docs] def minimize_global( objective_fn: Callable[[np.ndarray], np.ndarray], bounds: List[Tuple[float, float]], config: CalibrationConfig, verbose: bool = False, ) -> Dict[str, Any]: """ Global minimization using Differential Evolution. Args: objective_fn: Vectorized objective function. SciPy will call this with an array of shape ``(n_params, n_candidates)`` and expects a 1D array of shape ``(n_candidates,)``. bounds: List of ``(min, max)`` pairs for each parameter. config: Calibration configuration. verbose: Whether to print optimization progress. Returns: Dict[str, Any]: Optimization results compatible with :class:`~cann.engine.calibration_config.CalibrationResult`. Raises: ValueError: If SciPy rejects the provided configuration. """ vectorized_objective_evaluations = 0 candidate_function_evaluations = 0 def _counted_objective_fn(x: np.ndarray) -> np.ndarray: nonlocal vectorized_objective_evaluations, candidate_function_evaluations x_arr = np.asarray(x) vectorized_objective_evaluations += 1 candidate_function_evaluations += 1 if x_arr.ndim <= 1 else int(x_arr.shape[1]) return objective_fn(x) def _de_callback_func(xk, convergence): nonlocal iteration_counter iteration_counter += 1 if iteration_counter % 10 == 0: print( f"Iteration {iteration_counter}, best value: {objective_fn(xk.reshape(-1,1)).min()}, Current parameters: {xk}, Convergence: {convergence}" ) iteration_counter = 0 result = differential_evolution( func=_counted_objective_fn, bounds=bounds, strategy=config.strategy, maxiter=config.max_iter, popsize=config.pop_size, tol=config.tol, mutation=config.mutation, recombination=config.recombination, rng=np.random.default_rng(config.seed if config.seed is not None else 42), polish=config.polish, vectorized=True, updating="deferred", init=config.init, disp=False, callback=_de_callback_func if verbose else None, ) return { "x": result.x, "fun": result.fun, "nfev": result.nfev, "vectorized_nfev": vectorized_objective_evaluations, "candidate_nfev": candidate_function_evaluations, "nit": result.nit, "success": result.success, "message": result.message, }