Benders Convergence Output
Contents
Overview | Columns | Configuration | Assumptions | Examples | See Also
Overview
File: benders_convergence.csv
Condition: Only written when SolutionAlgorithm = "Benders" in case_settings.json.
benders_convergence.csv records the convergence history of the Benders decomposition algorithm. It is written at the case root (alongside the results_period_N/ directories), not inside any individual period's results directory.
Benders decomposition is an iterative algorithm that alternates between a planning (investment) master problem and a set of operational subproblems. At each iteration, the algorithm computes a lower bound (LB) on the optimal cost (from the master problem) and an upper bound (UB) (from combining the master and subproblem solutions). Convergence is declared when the gap between LB and UB falls below the configured tolerance.
This file is primarily useful for diagnosing slow convergence or verifying that the algorithm converged properly.
benders_convergence.csv is written inside the outer results directory (e.g., results_001/benders_convergence.csv), alongside settings.json and the results_period_N/ subdirectories. It covers the full Benders solve across all periods.
Columns
| Column | Type | Description |
|---|---|---|
Iter | Int | Benders iteration number (1-based) |
CPU_Time | Float64 | Elapsed CPU time in seconds at the end of this iteration |
LB | Float64 | Lower bound on the optimal objective value at this iteration (from the master problem) |
UB | Float64 | Upper bound on the optimal objective value at this iteration (from the combined master + subproblem solution) |
Gap | Float64 | Optimality gap: (UB - LB) / abs(UB), as a fraction (e.g., 0.001 = 0.1% gap) |
Status | String | Solver termination status (written on the first row only); indicates why the algorithm stopped (e.g., "OPTIMAL", "NONE", "NEGATIVE GAP", "TIMELIMIT", "MAXITER") |
Configuration
| Setting | File | Default | Effect |
|---|---|---|---|
SolutionAlgorithm | case_settings.json | "Monolithic" | Set to "Benders" to use Benders decomposition; this is required for benders_convergence.csv to be written. |
ConvTol | benders_settings.json | 0.001 | Convergence tolerance (fraction gap). The algorithm stops when Gap ≤ ConvTol. |
MaxIter | benders_settings.json | 50 | Maximum number of Benders iterations. If reached, Status = "MAXITER". |
MaxCpuTime | benders_settings.json | 7200 | Maximum CPU time in seconds. If reached, Status = "TIMELIMIT". |
Assumptions
- Monotone bounds. The lower bound (LB) is non-decreasing across iterations; the upper bound (UB) is non-increasing (in theory). Violations of this monotonicity may indicate numerical issues (e.g., numerical tolerance problems in the LP solver).
- Gap calculation. The gap is computed as
(UB - LB) / abs(UB). AGapof0.001(0.1%) is the default convergence criterion. TheConvTolparameter inbenders_settings.jsoncontrols this threshold.
Examples
Example benders_convergence.csv
| Iter | CPU_Time | LB | UB | Gap | Status |
|---|---|---|---|---|---|
| 1 | 12.3 | 1.20e10 | 5.40e11 | 0.978 | OPTIMAL |
| 2 | 24.7 | 2.85e11 | 4.12e11 | 0.308 | |
| 3 | 36.1 | 3.40e11 | 3.85e11 | 0.117 | |
| 4 | 48.9 | 3.62e11 | 3.76e11 | 0.037 | |
| 5 | 61.2 | 3.70e11 | 3.73e11 | 0.008 | |
| 6 | 74.5 | 3.71e11 | 3.72e11 | 0.003 | |
| 7 | 88.1 | 3.715e11 | 3.718e11 | 0.0008 |
In this example, the algorithm converged in 7 iterations with a final gap below the default 0.1% tolerance. The Status = "OPTIMAL" appears in the first row.
Reading Convergence History
using CSV, DataFrames, Plots
convergence = CSV.read("benders_convergence.csv", DataFrame)
# Plot convergence
plot(convergence.Iter, convergence.Gap .* 100,
xlabel="Iteration", ylabel="Gap (%)",
title="Benders Convergence", yscale=:log10,
marker=:circle, legend=false)
hline!([0.1], linestyle=:dash, color=:red, label="Target (0.1%)")Diagnosing Convergence Issues
If Status = "MAXITER" or Status = "TIMELIMIT", the algorithm did not converge within the allowed budget. Consider:
- Increasing
MaxIterorMaxCpuTimeinbenders_settings.json - Relaxing
ConvTolif the final gap is acceptable for your use case - Checking for numerical issues in the subproblem solutions (large UB swings between iterations)
- Enabling Benders stabilization (
StabParam > 0) to accelerate convergence
See Also
- Outputs Overview — overview of all output files and settings
- Settings Output — the
settings.jsonfile that records Benders configuration