Source code for sparsehydro.calibration.solvers.base

"""Abstract solver interface."""

from __future__ import annotations

from abc import ABC, abstractmethod
from typing import TYPE_CHECKING

from ..result import CalibrationResult

if TYPE_CHECKING:
    from ..problem import CalibrationProblem


[docs] class ISolver(ABC): """Abstract calibration solver. All solvers accept a :class:`~sparsehydro.calibration.problem.CalibrationProblem` and return a :class:`~sparsehydro.calibration.result.CalibrationResult`. ``solve()`` accepts ``**kwargs`` that override constructor-level settings for that call only — the solver instance is not mutated. This lets the same solver be reused for both quick exploratory runs and full production runs:: solver = NSGAIISolver(pop_size=100, n_gen=200) quick = solver.solve(problem, n_gen=5) # fast sanity check full = solver.solve(problem) # original settings Minimal implementation:: class MySolver(ISolver): def solve(self, problem: CalibrationProblem, **kwargs) -> CalibrationResult: x_best = ... # your optimisation logic F_best = problem.evaluate(x_best).reshape(1, -1) return CalibrationResult( history=[], pareto_X=x_best.reshape(1, -1), pareto_F=F_best, param_names=problem.param_names, objective_names=problem.objective_names, minimize_flags=problem.minimize_flags, ) """
[docs] @abstractmethod def solve(self, problem: "CalibrationProblem", **kwargs) -> CalibrationResult: """Run the solver and return results. :param problem: Calibration problem wrapping model + data + objectives. :type problem: CalibrationProblem :param kwargs: Per-call overrides for solver settings (e.g. ``n_gen=10``). Each solver documents which keys are recognised. :returns: Calibration result with Pareto front and generation history. :rtype: CalibrationResult """