Planning Options Reference

Comprehensive reference for the gtopt option hierarchy, JSON interface, merge semantics, and solver configuration.

Option Class Hierarchy

MainOptions                    (CLI-only, not in JSON)
  |
  +-- PlanningOptions          (JSON key: "options")
        |
        +-- ModelOptions           (JSON key: "model_options")
        +-- MonolithicOptions      (JSON key: "monolithic_options")
        |     +-- SolverOptions        (JSON key: "solver_options")
        +-- SddpOptions            (JSON key: "sddp_options")
        |     +-- SolverOptions        (JSON key: "forward_solver_options")
        |     +-- SolverOptions        (JSON key: "backward_solver_options")
        +-- CascadeOptions         (JSON key: "cascade_options")
        +-- SolverOptions          (JSON key: "solver_options")
        +-- LpBuildOptions         (JSON key: "lp_build_options")
        +-- VariableScale[]        (JSON key: "variable_scales")

C++ headers:

ClassHeader
PlanningOptionsplanning_options.hpp
PlanningOptionsLPplanning_options_lp.hpp
MainOptionsmain_options.hpp
SolverOptionssolver_options.hpp
SddpOptionssddp_options.hpp
MonolithicOptionsmonolithic_options.hpp
CascadeOptionscascade_options.hpp
ModelOptionsmodel_options.hpp
VariableScalevariable_scale.hpp

Backward-compatibility aliases: Options = PlanningOptions, OptionsLP = PlanningOptionsLP. The JSON key "options" is unchanged.

PlanningOptions Fields

All fields are std::optional – absent fields inherit built-in defaults (see PlanningOptionsLP for resolved values).

Input/Output

FieldTypeDefaultDescription
input_directorystring"input"Root directory for external data files
input_formatstring"parquet"Input format: "parquet" or "csv"
output_directorystring"output"Root directory for result files
output_formatstring"parquet"Output format: "parquet" or "csv"
output_compressionstring"zstd"Compression codec for output files
use_uid_fnameboolfalseUse UIDs instead of names in filenames

Model Parameters (deprecated flat fields)

Deprecated: The flat model fields below are kept for backward compatibility but emit a deprecation warning when parsed from JSON. Use the model_options sub-object instead (see ModelOptions Fields).

FieldTypeDefaultDescription
demand_fail_costfloatDeprecated — use model_options.demand_fail_cost
reserve_fail_costfloatDeprecated — use model_options.reserve_fail_cost
hydro_fail_costfloat5.0Deprecated — use model_options.hydro_fail_cost
hydro_use_valuefloat1.0Deprecated — use model_options.hydro_use_value
use_line_lossesbooltrueDeprecated — use model_options.use_line_losses
loss_segmentsint1Deprecated — use model_options.loss_segments
use_kirchhoffboolfalseDeprecated — use model_options.use_kirchhoff
use_single_busboolfalseDeprecated — use model_options.use_single_bus
kirchhoff_thresholdfloat0.0Deprecated — use model_options.kirchhoff_threshold
scale_objectivefloat1000Deprecated — use model_options.scale_objective
scale_thetafloat1000Deprecated — use model_options.scale_theta

Note: annual_discount_rate belongs in the simulation section. For backward compatibility it is still accepted as a flat field in options, but emits a deprecation warning.

Solver Selection

FieldTypeDefaultDescription
methodstring"monolithic"Planning method: monolithic, sddp, cascade

Logging and Debug

FieldTypeDefaultDescription
log_directorystring"logs"Directory for log and trace files
lp_debugboolfalseSave LP debug files before solving
lp_compressionstringCompression codec for LP files
lp_buildboolfalseBuild LP matrices without solving

Grouped Sub-objects

FieldTypeDescription
model_optionsModelOptionsPower system model configuration (canonical location for model fields)
monolithic_optionsMonolithicOptionsMonolithic solver settings
sddp_optionsSddpOptionsSDDP solver settings
cascade_optionsCascadeOptionsCascade solver settings
solver_optionsSolverOptionsGlobal LP solver configuration
lp_build_optionsLpBuildOptionsLP assembly configuration
variable_scalesVariableScale[]Per-class/variable LP scale overrides

Migration: Model parameter fields (use_kirchhoff, use_single_bus, etc.) can appear either at the top level of options (deprecated, backward- compatible) or inside the model_options sub-object (preferred). When both are present, the top-level flat value takes precedence. Flat fields emit a deprecation warning when parsed from JSON.

ModelOptions Fields

The model_options sub-object is the canonical location for LP-construction parameters. It enables per-level overrides in cascade solver configurations.

FieldTypeDefaultDescription
use_single_busboolfalseCollapse network to single bus (copper-plate)
use_kirchhoffboolfalseApply DC Kirchhoff voltage-law constraints
use_line_lossesbooltrueModel resistive line losses
kirchhoff_thresholdfloat0.0Min bus voltage [kV] for Kirchhoff activation
loss_segmentsint1Piecewise-linear segments for quadratic losses
scale_objectivefloat1000Objective coefficient divisor
scale_thetafloat1000Voltage-angle variable scaling
demand_fail_costfloatPenalty $/MWh for unserved demand
reserve_fail_costfloatPenalty $/MWh for unserved reserve
hydro_fail_costfloat5.0Penalty $/m³ for unmet hydro rights
hydro_use_valuefloat1.0Benefit $/m³ for exercising hydro rights

SolverOptions Fields

The solver_options sub-object (also embedded in monolithic_options, sddp_options.forward_solver_options, and sddp_options.backward_solver_options) configures the LP backend.

FieldTypeDefaultDescription
algorithmstring/int"barrier"LP algorithm: "default" (0), "primal" (1), "dual" (2), "barrier" (3)
threadsint2Number of parallel solver threads (0 = solver default)
presolvebooltrueApply LP presolve before solving
log_levelint0Solver output verbosity (0 = none)
reuse_basisboolfalseReuse basis from a previous solve (warm-start)
optimal_epsfloatOptimality tolerance (nullopt = solver default)
feasible_epsfloatFeasibility tolerance (nullopt = solver default)
barrier_epsfloatBarrier convergence tolerance (nullopt = solver default)
time_limitfloatPer-solve time limit in seconds (0 = no limit)

MonolithicOptions Fields

Note: boundary_cuts_file has moved to the simulation section. For backward compatibility, it is still accepted here.

FieldTypeDefaultDescription
solve_modestring"monolithic"Solve mode: "monolithic" or "sequential"
boundary_cuts_modestring"separated"How to load boundary cuts: "noload", "separated", "combined"
boundary_max_iterationsint0Max iterations to load from boundary cuts (0 = all)
solver_optionsSolverOptionsPer-method LP solver configuration

LpBuildOptions Fields

FieldTypeDefaultDescription
names_levelstring/int"minimal"LP naming level: "minimal" (0), "only_cols" (1), "cols_and_rows" (2)
lp_coeff_ratio_thresholdfloat1e7When global max/min coefficient ratio exceeds this, print a per-scene breakdown

SddpOptions Fields

See SDDP Method for full documentation with examples.

Iteration Control

FieldTypeDefaultDescription
max_iterationsint100Maximum forward/backward iterations
min_iterationsint2Minimum iterations before convergence is checked
convergence_tolfloat1e-4Relative gap tolerance for convergence

Convergence Criteria

FieldTypeDefaultDescription
convergence_modestring"statistical"Criterion mode: "gap_only", "gap_stationary", "statistical"
stationary_tolfloat0.01Tolerance for stationary-gap convergence (0 = disabled)
stationary_windowint10Look-back window for stationary-gap check
convergence_confidencefloat0.95Confidence level for PLP-style statistical convergence (0 = disabled)

Cuts and Recovery

FieldTypeDefaultDescription
cut_directorystring"cuts"Directory for Benders cut files
cut_sharing_modestring"none"Cut sharing: "none", "expected", "accumulate", "max"
cut_coeff_modestring"reduced_cost"Cut coefficient extraction: "reduced_cost" or "row_dual"
max_cuts_per_phaseint0Maximum stored cuts per (scene, phase) (0 = unlimited)
cut_prune_intervalint10Iterations between cut pruning passes
prune_dual_thresholdfloat1e-8Dual threshold for inactive cut detection
single_cut_storageboolfalseUse single-cut storage mode
max_stored_cutsint0Maximum total stored cuts per scene (0 = unlimited)
save_per_iterationbooltrueSave cuts after every iteration (not just at end)
cut_recovery_modestring"none"Cut persistence: "none", "keep", "append", "replace"
recovery_modestring"none"Recovery from previous run: "none", "cuts", "full"
cuts_input_filestringCSV file for hot-start cuts
named_cuts_filestringCSV file with named-variable cuts spanning all phases
boundary_cuts_modestring"separated"How to load boundary cuts: "noload", "separated", "combined"
boundary_max_iterationsint0Max iterations to load from boundary cuts (0 = all)
missing_cut_var_modestring"skip_coeff"Action when cut references unknown state variable: "skip_coeff" or "skip_cut"

Feasibility and Elastic Filter

FieldTypeDefaultDescription
elastic_penaltyfloat1e6Penalty for elastic slack variables in feasibility
elastic_modestring"single_cut"Elastic filter mode: "single_cut" (alias "cut"), "multi_cut", "backpropagate"
multi_cut_thresholdint10Infeasibility count threshold for switching to multi_cut (0 = never)

Apertures (Backward-Pass Sampling)

FieldTypeDefaultDescription
aperturesarray of UIDsAperture UIDs (absent = from Phase, [] = pure Benders)
aperture_directorystringAlternate data directory for aperture scenarios
aperture_timeoutfloat15.0Per-aperture LP solve timeout in seconds (0 = no limit)
save_aperture_lpboolfalseSave LP files for infeasible apertures to log directory

LP Updates and State Variables

FieldTypeDefaultDescription
update_lp_skipint0Iterations to skip between LP coefficient updates (0 = every iteration)
state_variable_lookup_modestring"warm_start"Volume lookup for LP updates: "warm_start" or "cross_phase"
warm_startbooltrueReuse previous solutions as warm-start for clone LP solves
use_clone_poolbooltrueReuse cached LP clones for aperture solves

Monitoring and Control

FieldTypeDefaultDescription
api_enabledbooltrueWrite JSON status file each iteration (for monitoring tools)
sentinel_filestringFile path; if it exists, solver stops gracefully after current iteration
simulation_modeboolfalseSkip training (max_iterations=0), run forward-only policy evaluation
alpha_minfloat0.0Lower bound for future cost variable α
alpha_maxfloat1e12Upper bound for future cost variable α

Per-Pass Solver Options

FieldTypeDescription
forward_solver_optionsSolverOptionsLP solver overrides for SDDP forward pass
backward_solver_optionsSolverOptionsLP solver overrides for SDDP backward pass

Solver Options Precedence

Each planning method can specify per-pass solver options that override the global solver_options. The merge chain (highest priority first):

MethodMerge chain
Monolithicmonolithic_options.solver_options -> solver_options
SDDP forwardsddp_options.forward_solver_options -> solver_options
SDDP backwardsddp_options.backward_solver_options -> solver_options

For each field in SolverOptions, the per-pass value is used if set; otherwise the global solver_options value applies.

JSON Example

{
  "options": {
    "solver_options": {
      "algorithm": 3,
      "threads": 4,
      "optimal_eps": 1e-8
    },
    "sddp_options": {
      "forward_solver_options": {
        "algorithm": 1
      },
      "backward_solver_options": {
        "threads": 1
      }
    }
  }
}

In this example, the forward pass uses algorithm 1 (primal) with 4 threads and 1e-8 tolerance (from global), while the backward pass uses algorithm 3 (barrier) with 1 thread and 1e-8 tolerance.

Variable Scales Precedence

Variable scaling factors are resolved in this order (highest priority first):

  1. Per-element fields (e.g., Battery::energy_scale, Reservoir::energy_scale)
  2. Global options (scale_theta for bus voltage angles)
  3. variable_scales entries matching by (class_name, variable, uid)
  4. variable_scales entries matching by (class_name, variable, uid=-1) (wildcard)
  5. Default scale = 1.0

JSON Example

{
  "options": {
    "model_options": {
      "scale_theta": 0.001
    },
    "variable_scales": [
      {"class_name": "Reservoir", "variable": "energy", "uid": -1, "scale": 1000.0},
      {"class_name": "Battery", "variable": "energy", "uid": 1, "scale": 10.0}
    ]
  }
}

Merge Semantics

When multiple JSON files are passed to gtopt, their "options" sections are merged left to right. For each field:

  • Scalars: the first file's value wins (later files fill in missing fields)
  • Sub-objects: merged recursively (same rule per field)
  • **variable_scales**: appended (later files add entries, earlier entries take precedence for the same key)

Precedence layers

  1. CLI flags (--solver highs, --set use_single_bus=true)
  2. Config file (~/.gtopt.conf [gtopt] section)
  3. JSON files (first file wins for each field)
  4. Built-in defaults (PlanningOptionsLP compile-time defaults)

MainOptions (CLI-only)

MainOptions is used only by the standalone binary and is not part of the JSON interface. It carries all CLI-parsed values plus the list of planning files.

FieldCLI flagDescription
planning_filespositional / -sSystem JSON file paths
solver--solverLP solver backend
method--methodPlanning method
demand_fail_cost--demand-fail-costUnserved demand penalty
scale_objective--scale-objectiveObjective scaling factor
*(any option)*--set key=valueSet any planning option (see below)

**--set key=value**: all other options are now set via --set. Examples: --set use_single_bus=true, --set output_directory=results/, --set solver_options.algorithm=barrier, --set sddp_options.max_iterations=300.

Deprecated aliases (still work, emit a warning): -b, -k, -D, -F, -d, -f, -C, --algorithm, --threads, --sddp-max-iterations, --sddp-min-iterations, --sddp-convergence-tol, --lp-debug, --log-directory, --cut-directory, --lp-compression, --lp-coeff-ratio.

Full JSON Example

{
  "options": {
    "input_directory": "system_data",
    "input_format": "parquet",
    "output_directory": "output",
    "output_format": "parquet",
    "output_compression": "zstd",
    "method": "sddp",
    "lp_debug": false,
    "model_options": {
      "demand_fail_cost": 1000,
      "use_kirchhoff": true,
      "use_single_bus": false,
      "use_line_losses": true,
      "scale_objective": 1000
    },
    "solver_options": {
      "algorithm": 3,
      "threads": 4,
      "optimal_eps": 1e-8,
      "feasible_eps": 1e-8
    },
    "sddp_options": {
      "max_iterations": 200,
      "convergence_tol": 1e-4,
      "forward_solver_options": {
        "algorithm": 1
      }
    },
    "lp_build_options": {
      "names_level": "only_cols"
    },
    "variable_scales": [
      {"class_name": "Reservoir", "variable": "energy", "uid": -1, "scale": 1000.0}
    ]
  },
  "simulation": {
    "annual_discount_rate": 0.1,
    "boundary_cuts_file": "boundary_cuts.csv",
    "boundary_cuts_valuation": "end_of_horizon"
  }
}

See Also