Configuration
Este conteúdo não está disponível em sua língua ainda.
All runtime parameters for cobre run are controlled by config.json in the
case directory. This page documents every section and field.
Minimal Config
Section titled “Minimal Config”{ "training": { "forward_passes": 50, "stopping_rules": [{ "type": "iteration_limit", "limit": 100 }] }}All other sections are optional with defaults documented below.
training
Section titled “training”Controls the SDDP training phase.
Mandatory Fields
Section titled “Mandatory Fields”| Field | Type | Description |
|---|---|---|
forward_passes | integer | Number of scenario trajectories per iteration. Larger values reduce variance in each iteration’s cut but increase cost per iteration. |
stopping_rules | array | At least one stopping rule (see below). The rule set must contain at least one iteration_limit rule. |
Optional Fields
Section titled “Optional Fields”| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | true | Set to false to skip training and proceed directly to simulation (requires a pre-trained policy). |
tree_seed | integer | null | Random seed for the opening scenario tree. When null, a default seed of 42 is used (deterministic but arbitrary). See Stochastic Modeling for the dual-seed architecture. |
stopping_mode | "any" or "all" | "any" | How multiple stopping rules combine: "any" stops when the first rule is satisfied; "all" requires all rules to be satisfied simultaneously. |
For the per-class scenario_source configuration, see the
scenario_source sub-section below and
Stochastic Modeling.
scenario_source
Section titled “scenario_source”Controls where the forward-pass noise comes from for each entity class during
training. When absent, all classes default to in_sample (reusing the
pre-generated opening tree).
| Field | Type | Default | Description |
|---|---|---|---|
seed | integer or null | null | Shared forward-pass seed for out_of_sample, historical, and external schemes. |
inflow | object | in_sample | Sampling scheme for hydro inflow. Object with "scheme" key. |
load | object | in_sample | Sampling scheme for bus load. Object with "scheme" key. |
ncs | object | in_sample | Sampling scheme for NCS availability. Object with "scheme" key. |
historical_years | array or object | auto-discover | Restrict the pool of historical windows. List ([1940, 1953]) or range ({"from": 1940, "to": 2010}). |
Valid values for "scheme": "in_sample", "out_of_sample", "historical", "external".
Example — out-of-sample inflow with in-sample load and NCS:
{ "training": { "tree_seed": 42, "forward_passes": 50, "stopping_rules": [{ "type": "iteration_limit", "limit": 200 }], "scenario_source": { "seed": 99, "inflow": { "scheme": "out_of_sample" }, "load": { "scheme": "in_sample" }, "ncs": { "scheme": "in_sample" } } }}See Stochastic Modeling — Sampling Schemes for a full description of
each scheme and the historical_years field.
Stopping Rules
Section titled “Stopping Rules”Each entry in stopping_rules is a JSON object with a "type" discriminator.
iteration_limit
Section titled “iteration_limit”Stop after a fixed number of training iterations.
{ "type": "iteration_limit", "limit": 200 }| Field | Type | Description |
|---|---|---|
limit | integer | Maximum number of SDDP iterations to run. |
time_limit
Section titled “time_limit”Stop after a wall-clock time budget is exhausted.
{ "type": "time_limit", "seconds": 3600.0 }| Field | Type | Description |
|---|---|---|
seconds | float | Maximum training time in seconds. |
bound_stalling
Section titled “bound_stalling”Stop when the relative improvement in the lower bound falls below a threshold.
{ "type": "bound_stalling", "iterations": 20, "tolerance": 0.0001 }| Field | Type | Description |
|---|---|---|
iterations | integer | Window size: the number of past iterations over which to compute the relative improvement. |
tolerance | float | Relative improvement threshold. Training stops when the improvement over the window is below this value. |
simulation
Section titled “simulation”Stop when both the lower bound and a Monte Carlo policy cost estimate have stabilized. Periodically runs a batch of forward simulations and compares the result against previous evaluations.
{ "type": "simulation", "replications": 100, "period": 10, "bound_window": 5, "distance_tol": 0.01, "bound_tol": 0.0001}| Field | Type | Description |
|---|---|---|
replications | integer | Number of Monte Carlo forward simulations per check. |
period | integer | Iterations between simulation checks. |
bound_window | integer | Number of past iterations for bound stability check. |
distance_tol | float | Normalized distance threshold between consecutive simulation results. |
bound_tol | float | Relative tolerance for bound stability. |
stopping_mode
Section titled “stopping_mode”When multiple stopping rules are listed, stopping_mode controls how they
combine:
"any"(default): stop when any one rule is satisfied."all": stop only when every rule is satisfied simultaneously.
{ "training": { "forward_passes": 50, "stopping_mode": "all", "stopping_rules": [ { "type": "iteration_limit", "limit": 500 }, { "type": "bound_stalling", "iterations": 20, "tolerance": 0.0001 } ] }}simulation
Section titled “simulation”Controls the optional post-training simulation phase.
| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Enable the simulation phase after training. |
num_scenarios | integer | 2000 | Number of independent Monte Carlo simulation scenarios to evaluate. |
When simulation.enabled is false or num_scenarios is 0, the simulation
phase is skipped entirely.
Example:
{ "simulation": { "enabled": true, "num_scenarios": 1000 }}scenario_source
Section titled “scenario_source”Controls where the forward-pass noise comes from during the simulation phase.
When absent, simulation falls back to the scheme configured under
training.scenario_source. This allows you to train with in-sample noise and
simulate with a different scheme (for example, out-of-sample or historical)
without modifying the training configuration.
The fields are identical to training.scenario_source:
| Field | Type | Default | Description |
|---|---|---|---|
seed | integer or null | null | Shared forward-pass seed for out_of_sample, historical, and external schemes. |
inflow | object | in_sample | Sampling scheme for hydro inflow. Object with "scheme" key. |
load | object | in_sample | Sampling scheme for bus load. Object with "scheme" key. |
ncs | object | in_sample | Sampling scheme for NCS availability. Object with "scheme" key. |
historical_years | array or object | auto-discover | Restrict the pool of historical windows. List ([1940, 1953]) or range ({"from": 1940, "to": 2010}). |
Example — simulate with out-of-sample inflow while training uses in-sample:
{ "training": { "forward_passes": 50, "stopping_rules": [{ "type": "iteration_limit", "limit": 200 }] }, "simulation": { "enabled": true, "num_scenarios": 2000, "scenario_source": { "seed": 77, "inflow": { "scheme": "out_of_sample" }, "load": { "scheme": "in_sample" }, "ncs": { "scheme": "in_sample" } } }}modeling
Section titled “modeling”Controls physical modeling options.
| Field | Type | Default | Description |
|---|---|---|---|
inflow_non_negativity | object | see below | Strategy for handling negative PAR model inflow draws. |
inflow_non_negativity
Section titled “inflow_non_negativity”| Field | Type | Default | Description |
|---|---|---|---|
method | string | "penalty" | One of "none", "penalty", "truncation", or "truncation_with_penalty". |
"none"— no treatment; negative inflows are passed through to the LP."penalty"— adds a slack variable to the LP that absorbs negative inflow realisations. The slack carries a per-hydro objective cost frompenalties.json::hydro.inflow_nonnegativity_cost."truncation"— clamps negative PAR model draws to zero before applying noise."truncation_with_penalty"— combines both: clamps the inflow to zero and adds a bounded slack variable penalised bypenalties.json::hydro.inflow_nonnegativity_cost, providing a smooth backstop for extreme tail realisations.
Example:
{ "modeling": { "inflow_non_negativity": { "method": "penalty" } }}cut_selection
Section titled “cut_selection”Controls the row management pipeline for managing row pool growth. The pipeline has up to two stages: strategy-based selection and budget enforcement. Row management periodically scans the row pool and deactivates rows that are unlikely to improve the policy, reducing LP size without sacrificing convergence quality. For a detailed explanation of each stage, see Performance Accelerators.
The block has two always-on knobs at the top level plus a selection
sub-object that chooses the method and carries only that method’s parameters.
Omitting selection (or setting it to null) disables row selection — that is
the default.
Always-on fields
Section titled “Always-on fields”| Field | Type | Default | Description |
|---|---|---|---|
row_activity_tolerance | float | 0.0 | Minimum dual-multiplier magnitude for a constraint row to count as binding at a solution point. Rows whose dual falls below this are treated as inactive in tracking. |
max_active_per_stage | integer | null | Hard cap on active rows per stage LP, enforced after the selection method runs. null = no cap. |
selection | object | null | The active selection method and its parameters (see below). null (the default) disables row selection. |
The selection object
Section titled “The selection object”selection.method is the discriminator; each method exposes only its own
parameters. Supplying a parameter that belongs to a different method is a config
load error, and a misspelled method is rejected with the list of valid methods.
-
"level1"— evaluates all populated rows at every visited state and retains any row whose value is withintie_toleranceof the per-state maximum at some state. Least aggressive; preserves the convergence guarantee.Field Type Default Description tie_tolerancefloat 1e-10A row is active at a state when within this of the best row value there. check_frequencyinteger 5Iterations between periodic pruning checks. Must be > 0. -
"lml1"— at each visited state, retains only the oldest eligible row withintie_toleranceof the per-state maximum; the selected set is the union of those per-state survivors. More aggressive than"level1". Same fields as"level1"(tie_tolerance,check_frequency). -
"domination"— removes rows dominated at all visited states.Field Type Default Description domination_tolerancefloat — A row survives if within this of the maximum at any visited state. Required. check_frequencyinteger 5Iterations between periodic pruning checks. Must be > 0. -
"dynamic"— a per-solve lazy loop that loads only a small resident subset of rows per solve while retaining the full pool. The resident set is seeded from the most recent iterations, and each lazy-solve round adds the most-violated candidate rows.Field Type Default Description start_iterationinteger 2First 1-based iteration at which the lazy loop becomes active. Must be >= 1.seed_windowinteger 5Number of most-recent iterations whose rows seed the initial resident set. 0is valid (seeds only the current iteration).candidate_recencyinteger nullOnly rows generated within the last candidate_recencyiterations are scored.null(the default) is unbounded — every pool row is a candidate, which preserves exactness.Some(n)(must be>= 1) makes the loop deliberately inexact: rows older than the window are never added.max_added_per_roundinteger 10Maximum rows added per lazy-solve round. Must be >= 1.violation_tolerancefloat 1e-10Violation tolerance for accepting a candidate row. Must be > 0.
The dynamic method is mutually exclusive with the periodic-pruning methods by
construction — choosing it from the tagged selection block means none of
level1 / lml1 / domination can run.
Example with the dynamic method:
{ "training": { "cut_selection": { "row_activity_tolerance": 1e-6, "max_active_per_stage": 4000, "selection": { "method": "dynamic", "start_iteration": 2, "seed_window": 5, "max_added_per_round": 10, "violation_tolerance": 1e-10 } } }}Example with the level1 method and a per-stage budget:
{ "training": { "cut_selection": { "row_activity_tolerance": 1e-6, "max_active_per_stage": 500, "selection": { "method": "level1", "tie_tolerance": 1e-10, "check_frequency": 5 } } }}estimation
Section titled “estimation”Controls the PAR(p) model estimation pipeline. When the case provides
inflow_history.parquet, Cobre can automatically estimate AR coefficients
instead of requiring pre-computed inflow_ar_coefficients.parquet.
| Field | Type | Default | Description |
|---|---|---|---|
max_order | integer | 6 | Maximum lag order considered during autoregressive model fitting. |
order_selection | string | "pacf" | Order selection criterion: "pacf" (PACF-based) or "pacf_annual" (PACF with annual component). |
min_observations_per_season | integer | 30 | Minimum observations per (entity, season) group to proceed with estimation. |
max_coefficient_magnitude | float | null | Safety net: reduce to order 0 if any coefficient exceeds this magnitude. |
Example:
{ "estimation": { "max_order": 6, "order_selection": "pacf", "min_observations_per_season": 30 }}Setting "order_selection": "pacf_annual" activates the annual component extension. When
enabled, the estimation pipeline performs four additional steps beyond the classical PAR
path: (1) the Yule-Walker system is extended to include a cross-correlation term between
the current-season inflow and the rolling 12-month average; (2) per-season sample
statistics (mean and standard deviation) of that rolling average are computed for each
hydro plant; (3) the coefficient, mean, and standard deviation are written to
inflow_annual_component.parquet in the output directory; and (4) the lag stride used
when building the LP noise columns is widened to accommodate the extra annual term. Use
this option when your inflow series shows persistence that extends beyond the
standard seasonal lag window.
policy
Section titled “policy”Controls policy persistence (checkpoint saving and warm-start loading).
| Field | Type | Default | Description |
|---|---|---|---|
path | string | "./policy" | Directory where policy data (cuts, states) is stored. |
mode | "fresh", "warm_start", or "resume" | "fresh" | Initialization mode. "fresh" starts from scratch; "warm_start" loads cuts from a previous run; "resume" continues an interrupted run. |
boundary | object or null | null | Terminal boundary cut configuration for coupling with an outer model’s FCF. See below. |
checkpointing
Section titled “checkpointing”| Field | Type | Default | Description |
|---|---|---|---|
enabled | boolean | false | Enable periodic checkpointing during training. |
initial_iteration | integer | null | First iteration to write a checkpoint. |
interval_iterations | integer | null | Iterations between checkpoints. |
store_basis | boolean | false | Include LP basis in checkpoints for warm-start. |
compress | boolean | false | Compress checkpoint files. |
boundary
Section titled “boundary”Optional configuration for loading terminal-stage boundary cuts from a different Cobre policy checkpoint. When present, the solver loads cuts from the source checkpoint and injects them as fixed boundary conditions at the terminal stage of the current study. The imported cuts are not updated by training — they remain fixed throughout.
This enables Cobre-to-Cobre model coupling: a monthly study produces a policy checkpoint, and a weekly+monthly coupled study loads that checkpoint’s cuts as its terminal-stage future cost function.
| Field | Type | Description |
|---|---|---|
path | string | Path to the source policy checkpoint directory. |
source_stage | integer | 0-based stage index in the source checkpoint to load cuts from. |
Example — load stage 2’s cuts from a monthly policy as terminal boundary:
{ "policy": { "mode": "fresh", "boundary": { "path": "../monthly_study/policy", "source_stage": 2 } }}See Policy Management — Boundary Cuts for a full explanation of the coupling workflow.
Temporal Resolution
Section titled “Temporal Resolution”Cobre does not have dedicated config.json fields for temporal resolution. The
resolution of each stage is determined entirely by the date boundaries in
stages.json. However, when stages.json defines stages at different temporal
resolutions — for example, four weekly stages within a month followed by monthly
stages, or monthly stages transitioning to quarterly stages — three mechanisms
activate automatically that users should understand.
Noise Group Sharing
Section titled “Noise Group Sharing”When multiple SDDP stages share the same season_id within the same calendar
period (for example, four weekly stages all assigned season_id: 0 for
January), they receive identical PAR noise draws. This ensures that sub-monthly
stages present an inflow trajectory consistent with the monthly PAR model they
were fitted from, rather than fabricating independent weekly variability that
the historical record does not support.
Observation Aggregation
Section titled “Observation Aggregation”When the study includes stages at different resolutions (for example, monthly
and quarterly), Cobre automatically aggregates fine-grained historical
observations into coarser season buckets before PAR fitting. A user supplying
monthly inflow_history.parquet for a study that includes quarterly stages does
not need to pre-aggregate the data; Cobre derives one observation per
(entity, season, year) at the appropriate coarser resolution. Aggregating in the
opposite direction (disaggregating coarser observations to a finer resolution)
is not supported and will produce a validation error at case load time.
Lag Resolution Transition
Section titled “Lag Resolution Transition”For studies that transition from monthly to quarterly stages, the PAR lag state changes resolution at the boundary. During the monthly phase, each monthly inflow is accumulated into a ring buffer indexed by the downstream (quarterly) lag. When the first quarterly stage is reached, the ring buffer contains a complete set of duration-weighted monthly contributions, and the lag state is rebuilt automatically. This transition is transparent to the LP and the cut representation; it introduces no additional LP variables.
Example: Weekly Stages Within a Month
Section titled “Example: Weekly Stages Within a Month”The following stages.json excerpt shows four weekly stages within January
(stages 0-3, all with season_id: 0) followed by a normal monthly stage for
February (season_id: 1). Stages 0-3 share the same season_id and will
therefore receive identical PAR noise draws during training:
[ { "id": 0, "start_date": "2024-01-01", "end_date": "2024-01-08", "season_id": 0, "num_scenarios": 50 }, { "id": 1, "start_date": "2024-01-08", "end_date": "2024-01-15", "season_id": 0, "num_scenarios": 50 }, { "id": 2, "start_date": "2024-01-15", "end_date": "2024-01-22", "season_id": 0, "num_scenarios": 50 }, { "id": 3, "start_date": "2024-01-22", "end_date": "2024-02-01", "season_id": 0, "num_scenarios": 50 }, { "id": 4, "start_date": "2024-02-01", "end_date": "2024-03-01", "season_id": 1, "num_scenarios": 50 }]Recommended Alternative: Weekly Blocks Within a Monthly Stage
Section titled “Recommended Alternative: Weekly Blocks Within a Monthly Stage”When weekly dispatch granularity is needed but true weekly-resolution noise
data is unavailable, the recommended approach is to use a single monthly SDDP
stage with chronological blocks rather than four separate weekly SDDP stages.
This provides weekly LP granularity while keeping one noise realization per
month — consistent with the data resolution — and avoids the lag-accumulation
complications that arise with multiple independent weekly stages. See
Stochastic Modeling — Temporal Resolution and PAR for the full
explanation and a stages.json example of the block pattern.
See Also (Temporal Resolution)
Section titled “See Also (Temporal Resolution)”- Stochastic Modeling — Multi-Resolution Studies — detailed mechanism descriptions including the noise group precomputation algorithm, observation aggregation internals, and lag ring buffer design
- Stochastic Modeling — Temporal Resolution and PAR — the honest representation principle, the recommended weekly-block pattern, and validation rules 27-31
exports
Section titled “exports”Controls which outputs are written to the results directory.
| Field | Type | Default | Description |
|---|---|---|---|
states | boolean | false | Write visited forward-pass trial points to the policy checkpoint (FlatBuffers). |
stochastic | boolean | false | Export stochastic preprocessing artifacts to output/stochastic/. |
fpha_deviation_points | boolean | false | Export the per-grid-point computed-FPHA fit-deviation table to output/hydro_models/fpha_deviation_points.parquet. Opt-in because it emits one row per (hydro, stage, V, Q) sample point at spillage = 0. |
Full Example
Section titled “Full Example”{ "$schema": "https://docs.cobre-rs.dev/schemas/config.schema.json", "training": { "tree_seed": 42, "forward_passes": 50, "stopping_rules": [ { "type": "iteration_limit", "limit": 200 }, { "type": "bound_stalling", "iterations": 20, "tolerance": 0.0001 } ], "stopping_mode": "any", "scenario_source": { "seed": 99, "inflow": { "scheme": "out_of_sample" }, "load": { "scheme": "in_sample" }, "ncs": { "scheme": "in_sample" } }, "cut_selection": { "row_activity_tolerance": 1e-6, "max_active_per_stage": null, "selection": { "method": "level1", "tie_tolerance": 1e-10, "check_frequency": 5 } } }, "modeling": { "inflow_non_negativity": { "method": "penalty" } }, "simulation": { "enabled": true, "num_scenarios": 2000 }, "policy": { "path": "./policy", "mode": "fresh" }, "exports": { "states": false, "stochastic": false }}Advanced Fields
Section titled “Advanced Fields”The Config struct supports additional sections not documented on this page.
These fields are deserialized from config.json when present but are intended
for advanced use cases and may change between releases:
| Section | Purpose |
|---|---|
upper_bound_evaluation | Inner approximation upper-bound evaluation settings |
training.solver | LP solver options (see Solver Safeguards for details) |
simulation.io_channel_capacity | Async I/O channel buffer size for simulation output writing |
All fields have defaults and can be omitted. Every JSON input file rejects
unknown keys, so misspelled fields raise a parse error rather than being
silently ignored. For the complete list of fields and their types, see the
Config struct in the cobre-io API docs.
See Also
Section titled “See Also”- Case Directory Format — full schema for all input files
- Running Studies — end-to-end workflow guide
- Error Codes — validation errors including
SchemaErrorfor config fields - Stochastic Modeling — Temporal Resolution — how stage resolution affects PAR noise sharing and validation rules