SddpOptions struct
#include <gtopt/sddp_options.hpp>
SDDP-specific solver configuration parameters.
Groups all SDDP-related options into a single sub-object for clearer JSON organization. Field names omit the sddp_ prefix since they already live inside the sddp_options namespace.
All fields are optional — defaults are applied via PlanningOptionsLP.
Public functions
- auto merge(SddpOptions&& opts) -> void
Public variables
- OptReal alpha_max
- Upper bound for future cost variable α (default: 1e12)
- OptReal alpha_min
- Lower bound for future cost variable α (default: 0.0)
- OptName aperture_directory
- Directory for aperture-specific scenario data.
- OptReal aperture_timeout
- Timeout in seconds for individual aperture LP solves in the SDDP backward pass.
- std::optional<Array<Uid>> apertures
- Aperture UIDs for the backward pass.
- OptBool api_enabled
- Enable the SDDP monitoring API (writes JSON status file each iteration; default: true)
- OptInt backward_max_fallbacks
- Maximum algorithm fallback attempts for backward-pass and aperture solves.
- std::optional<SolverOptions> backward_solver_options
- Optional LP solver configuration for SDDP backward pass.
- OptName boundary_cuts_file
- CSV file with boundary (future-cost) cuts for the last phase.
- std::optional<BoundaryCutsMode> boundary_cuts_mode
- How boundary cuts are loaded: noload, separated (default), or combined.
- OptInt boundary_max_iterations
- Maximum number of SDDP iterations to load from the boundary cuts file. Only cuts from the last N iterations (by
iterationcolumn, i.e. PLP's IPDNumIte) are loaded. 0 = load all (default). - OptReal convergence_confidence
- Confidence level for statistical convergence criterion (0-1).
- std::optional<ConvergenceMode> convergence_mode
- Convergence criterion mode selection.
- OptReal convergence_tol
- Relative gap tolerance for convergence (default: 1e-4)
- OptReal cut_coeff_eps
- Absolute tolerance for filtering numerically tiny Benders cut coefficients.
- OptReal cut_coeff_max
- Maximum allowed absolute coefficient in a Benders cut row.
- std::optional<CutCoeffMode> cut_coeff_mode
- How Benders cut coefficients are extracted from solved subproblems.
- OptName cut_directory
- Directory for Benders cut files (default:
"cuts") - OptInt cut_prune_interval
- Iterations between cut pruning passes. Default: 10.
- std::optional<HotStartMode> cut_recovery_mode
- Cut persistence mode: none (default), keep, append, or replace. Controls whether to load cuts from a previous run and how to handle the combined output file on completion.
- std::optional<CutSharingMode> cut_sharing_mode
- Cut sharing mode: none (default), expected, accumulate, or max.
- OptName cuts_input_file
- File path for loading initial cuts (hot-start; empty = cold start)
- std::optional<ElasticFilterMode> elastic_mode
- Elastic filter mode: single_cut (default, alias "cut") or multi_cut or backpropagate.
- OptReal elastic_penalty
- Penalty for elastic slack variables in feasibility (default: 1e6)
- OptInt forward_max_fallbacks
- Maximum algorithm fallback attempts for forward-pass solves.
- std::optional<SolverOptions> forward_solver_options
- Optional LP solver configuration for SDDP forward pass.
- OptInt max_cuts_per_phase
- Maximum retained cuts per (scene, phase) LP. 0 = unlimited (default).
- OptInt max_iterations
- Maximum number of forward/backward iterations (default: 100)
- OptInt max_stored_cuts
- Maximum total stored cuts per scene (0 = unlimited). Default: 0.
- OptInt min_iterations
- Minimum iterations before declaring convergence (default: 2)
- std::optional<MissingCutVarMode> missing_cut_var_mode
- How to handle cuts referencing state variables not in the model.
- OptInt multi_cut_threshold
- Forward-pass infeasibility count threshold for switching from single_cut to multi_cut (default: 10; 0 = never auto-switch)
- OptName named_cuts_file
- CSV file with named-variable cuts for hot-start across all phases.
- OptReal prune_dual_threshold
- Dual threshold for inactive cut detection. Default: 1e-8.
- std::optional<RecoveryMode> recovery_mode
- Recovery mode: none (0), cuts (1), or full (2). Controls what is recovered from a previous run:
- OptBool save_aperture_lp
- Save LP files for infeasible apertures to the log directory.
- OptBool save_per_iteration
- Save cuts to CSV after each iteration (default: true). When false, cuts are only saved at the end of the solve or on stop.
- OptReal scale_alpha
- Scale divisor for future cost variable α (default: 1000).
- OptName sentinel_file
- Path to a sentinel file; if it exists, the solver stops gracefully after the current iteration (analogous to PLP's userstop)
- OptBool simulation_mode
- OptBool single_cut_storage
- Use single cut storage: store in per-scene vectors only. Default: false.
- std::optional<StateVariableLookupMode> state_variable_lookup_mode
- How update_lp elements obtain reservoir/battery volume between phases.
- OptReal stationary_tol
- Tolerance for stationary-gap convergence criterion.
- OptInt stationary_window
- Number of iterations to look back when checking for a stationary gap. Used by both the standalone stationary criterion and the statistical+stationary criterion. Default: 10.
- OptInt update_lp_skip
- Iterations to skip between update_lp dispatches. 0 = update every iteration (default). Applies to all volume-dependent LP element updates (seepage, discharge limit, production factor).
- OptBool use_clone_pool
- Reuse cached LP clones for aperture solves. Default: true.
- OptBool warm_start
- Enable warm-start for SDDP resolves. When true, previous forward-pass primal/dual solutions are loaded into clone LPs before resolving (backward pass, elastic filter, apertures). Combined with solver_options.reuse_basis, this enables efficient incremental re-solves. Default when unset: true.
Variable documentation
OptName gtopt:: SddpOptions:: aperture_directory
Directory for aperture-specific scenario data.
When present, scenarios referenced by Aperture::source_scenario are first looked up in this directory. If not found there, they fall back to the regular input_directory. This allows backward-pass apertures to use different affluent data than the forward-pass scenarios.
OptReal gtopt:: SddpOptions:: aperture_timeout
Timeout in seconds for individual aperture LP solves in the SDDP backward pass.
When an aperture LP exceeds this time, it is treated as infeasible (skipped), a WARNING is logged, and the solver continues with the remaining apertures. Default 15 seconds. 0 = no timeout.
OptInt gtopt:: SddpOptions:: backward_max_fallbacks
Maximum algorithm fallback attempts for backward-pass and aperture solves.
Controls how many alternative algorithms the solver tries when a backward-pass or aperture LP returns non-optimal. Default: 0 (no fallback — fail immediately).
std::optional<SolverOptions> gtopt:: SddpOptions:: backward_solver_options
Optional LP solver configuration for SDDP backward pass.
When set, these options are merged with the global PlanningOptions::solver_options. Backward-pass-specific options take precedence over the global ones.
Typical use: use dual simplex with reuse_basis for the backward pass (warm-started resolves after adding cuts).
OptName gtopt:: SddpOptions:: boundary_cuts_file
CSV file with boundary (future-cost) cuts for the last phase.
These are analogous to PLP's "planos de embalse" — external optimality cuts that approximate the expected future cost beyond the planning horizon. Each cut is of the form:
α ≥ rhs + Σ_i coeff_i · state_var_i
The CSV header row names the state variables (reservoir / battery); subsequent rows provide the cut name, iteration, scene UID, RHS, and gradient coefficients.
Format:
name,iteration,scene,rhs,Reservoir1,Reservoir2,... cut_001,1,1,-5000.0,0.25,0.75,...
The scene column contains the scene UID (matching the uid field in gtopt's scene_array). The solver maps column headers to the LP state-variable columns in the last phase and adds each cut as a lower-bound constraint on the future cost variable α. If empty, no boundary cuts are loaded.
std::optional<BoundaryCutsMode> gtopt:: SddpOptions:: boundary_cuts_mode
How boundary cuts are loaded: noload, separated (default), or combined.
- noload — do not load boundary cuts even if a file is given.
- separated — load cuts per scene (scene UID matching; default).
- combined — load all cuts into all scenes (broadcast).
OptReal gtopt:: SddpOptions:: convergence_confidence
Confidence level for statistical convergence criterion (0-1).
When > 0 and multiple scenes exist, convergence is checked via PLP-style confidence interval: UB - LB <= z_{α/2} * σ. Combined with stationary_tol, also handles the non-zero-gap case where the gap stabilises above the CI threshold.
Default: 0.95 (95% CI). Set to 0.0 to disable.
std::optional<ConvergenceMode> gtopt:: SddpOptions:: convergence_mode
Convergence criterion mode selection.
gap_only: deterministic gap test only.gap_stationary: gap + stationary gap detection.statistical: gap + stationary + CI (default, PLP-style).
The statistical mode degrades gracefully to gap_stationary when only one scene is present (no apertures / pure Benders).
OptReal gtopt:: SddpOptions:: cut_coeff_eps
Absolute tolerance for filtering numerically tiny Benders cut coefficients.
When constructing an optimality cut, any state-variable coefficient (reduced cost or row dual) whose absolute value is below this threshold is dropped — both the coefficient and its corresponding RHS adjustment are skipped. This removes solver numerical noise that would otherwise produce ill-conditioned cuts.
Inspired by PLP's OptiEPS mechanism (default 1e-8 there).
Default: 0.0 (no filtering — all coefficients are kept). Typical useful values: 1e-12 to 1e-8.
OptReal gtopt:: SddpOptions:: cut_coeff_max
Maximum allowed absolute coefficient in a Benders cut row.
When the largest state-variable coefficient in a newly built cut exceeds this threshold, the entire row (all coefficients, the α weight, and the RHS) is uniformly divided by max_coeff / cut_coeff_max. This preserves the constraint's feasible set while improving numerical conditioning.
A warning is logged each time a cut is rescaled.
Default: 0.0 (disabled — no rescaling). Typical useful values: 1e6 to 1e8.
std::optional<CutCoeffMode> gtopt:: SddpOptions:: cut_coeff_mode
How Benders cut coefficients are extracted from solved subproblems.
reduced_cost(default): uses reduced costs of fixed dependent columns.row_dual: adds explicit coupling constraint rows and reads their duals (PLP-style).
Both are mathematically equivalent; row_dual may be preferred for cross-validation with PLP or when LP solver presolve affects reduced-cost reporting for fixed variables.
OptInt gtopt:: SddpOptions:: forward_max_fallbacks
Maximum algorithm fallback attempts for forward-pass solves.
Controls how many alternative algorithms the solver tries when a forward-pass LP returns non-optimal. Default: 2 (full cycle).
std::optional<SolverOptions> gtopt:: SddpOptions:: forward_solver_options
Optional LP solver configuration for SDDP forward pass.
When set, these options are merged with the global PlanningOptions::solver_options. Forward-pass-specific options take precedence over the global ones.
Typical use: use barrier for the forward pass (fresh solves) while using dual simplex for the backward pass (warm-started resolves).
std::optional<MissingCutVarMode> gtopt:: SddpOptions:: missing_cut_var_mode
How to handle cuts referencing state variables not in the model.
skip_coeff(default): drop the missing coefficient, load the cut.skip_cut: skip the entire cut if any missing variable has a non-zero coefficient.
OptName gtopt:: SddpOptions:: named_cuts_file
CSV file with named-variable cuts for hot-start across all phases.
Unlike boundary cuts (which apply only to the last phase), these cuts include a phase column indicating which phase they belong to. The solver resolves named state-variable headers (reservoir / battery / junction) to LP column indices in the specified phase, then adds each cut as:
α_phase ≥ rhs + Σ_i coeff_i · state_var_i[phase]
Format:
name,iteration,scene,phase,rhs,Reservoir1,Reservoir2,... hs_1_1_3,1,1,3,-5000.0,0.25,0.75,...
If empty, no named hot-start cuts are loaded.
std::optional<RecoveryMode> gtopt:: SddpOptions:: recovery_mode
Recovery mode: none (0), cuts (1), or full (2). Controls what is recovered from a previous run:
- none: no recovery (cold start).
- cuts: recover only Benders cuts.
- full: recover cuts + state variable solutions (default).
OptBool gtopt:: SddpOptions:: save_aperture_lp
Save LP files for infeasible apertures to the log directory.
When true, each infeasible aperture clone is written as error_aperture_sc_<scene>_ph_<phase>_ap_<uid>.lp in the log directory. Useful for debugging but expensive in large cases. Default: false (disabled).
OptReal gtopt:: SddpOptions:: scale_alpha
Scale divisor for future cost variable α (default: 1000).
The LP alpha variable is α_lp = α / scale_alpha, with an objective coefficient of scale_alpha so that the physical contribution is preserved. Analogous to PLP's varphi scale — improves numerical conditioning when α values are orders of magnitude larger than other LP variables.
OptBool gtopt:: SddpOptions:: simulation_mode
Run in simulation mode: no training iterations (max_iterations=0), forward-only evaluation of the policy from loaded cuts. No cuts are saved. Default: false.
std::optional<StateVariableLookupMode> gtopt:: SddpOptions:: state_variable_lookup_mode
How update_lp elements obtain reservoir/battery volume between phases.
Controls the fallback in StorageLP::physical_eini for nonlinear LP coefficient updates (seepage, production factor, discharge limit). Does NOT affect SDDP state-variable chaining or cut generation.
warm_start(default): volume from warm-start solution, recovered state file, or vini. No cross-phase lookup.cross_phase: volume from the previous phase's efin within the same forward pass.
OptReal gtopt:: SddpOptions:: stationary_tol
Tolerance for stationary-gap convergence criterion.
When the relative change in the convergence gap over the last stationary_window iterations falls below this value, the gap is considered stationary (no longer improving). This triggers convergence in two situations:
- Standalone: gap is stationary → declare convergence even if gap > convergence_tol (non-zero gap accepted).
- Combined with convergence_confidence: when the CI test fails (gap > z*σ) but the gap is stationary → declare convergence (the non-zero gap has stabilised and further iterations won't help).
Formula (after min_iterations and stationary_window completed): gap_change = |gap[i] − gap[i − window]| / max(1e-10, gap[i − window]) if gap_change < stationary_tol → gap is stationary
Default: 0.01 (1%). Set to 0.0 to disable.