Skip to content

Upper Bound Evaluation

This chapter defines Novomodelo’s upper-bound mechanisms: an overview of the bounds of a training iteration (section 1), the exact deterministic upper bound of an enumerated forward pass and its nested form under a uniform CVaR (section 2), the gap computation that compares the iteration’s upper bound against the lower bound from cuts (section 3), and the estimators of the sampled forward schemes and of the post-training sampled and census simulation, with what each estimates (section 4). The appendix describes the reserved vertex-based inner approximation (SIDP) design. It complements the outer approximation (cuts) described in SDDP Algorithm by providing the convergence-certificate half of the bound pair.

For notation conventions (index sets, parameters, decision variables, dual variables), see Notation Conventions.

Standard SDDP produces only a lower bound z‾\underline{z} on the optimal cost, through the outer (cut) approximation. A convergence certificate additionally requires an upper bound zˉ\bar{z} that closes the optimality gap between the two bounds.

Novomodelo computes this per-iteration upper bound via one of two forward-pass mechanisms, selected by the forward pass’s sampling mode:

  • Statistical Monte-Carlo upper bound. Under a sampled forward pass, the sample mean of the scenario costs gathered that iteration, together with a 95% confidence-interval half-width, estimates the expected cost under the policy. This is a statistical estimate: it carries genuine sampling error that narrows only as more scenarios are drawn. Section 4 states what it estimates under each forward scheme.
  • Exact deterministic upper bound. Under an enumerated forward pass, the probability-weighted expectation over every enumerated leaf path is the exact expected cost under the policy, with no sampling error at all. See section 2.

Section 3 computes the gap between that upper bound and the lower bound from the cuts at every iteration.

After training, the post-training simulation reruns the trained policy on scenarios drawn under each class’s simulation scheme, in a sampled and a census variant (section 4.5). That estimator is a diagnostic on the finished policy — it is not part of the per-iteration training loop the mechanisms above feed, and it is not consumed by any stopping rule.

The appendix describes a reserved design that Novomodelo does not compute, a vertex-based inner approximation of the cost-to-go function (SIDP).

Under an enumerated forward pass — one that visits every node of the policy graph deterministically rather than sampling it — the forward pass evaluates every leaf path ℓ\ell of the scenario tree exactly once. Let P(ℓ)P(\ell) be that leaf path’s probability and

C(ℓ)=∑t=1Td1→t⋅ct(ℓ)C(\ell) = \sum_{t=1}^{T} d_{1 \to t} \cdot c_t(\ell)

its realized total discounted cost (see Discount Rate Formulation). The exact upper bound is the probability-weighted expectation over the full enumeration:

zˉexact=∑ℓP(ℓ) C(ℓ)\bar{z}_{\text{exact}} = \sum_{\ell} P(\ell)\, C(\ell)

Because the enumeration is exhaustive rather than sampled, zˉexact\bar{z}_{\text{exact}} is the exact expectation of total cost under the current policy — not an estimate of it. Its standard deviation and 95% confidence-interval half-width are consequently identically zero: a deduplicated enumeration carries no sampling distribution to estimate a spread over.

With an imported terminal boundary (Post-Study Boundary & Chained Studies), the last stage’s cost cT(ℓ)c_T(\ell) keeps the discounted boundary value of that stage’s outgoing state, so the upper bound contains the same terminal function as the lower bound.

The bound zˉexact=∑ℓP(ℓ) C(ℓ)\bar{z}_{\text{exact}} = \sum_{\ell} P(\ell)\, C(\ell) above is the exact upper bound under an expectation objective. Under a CVaR measure held uniform across every stage, the same exhaustive enumeration yields an exact bound of a different shape — a nested risk recursion — developed in section 2.1; see Risk Measures for the risk-measure background.

Under a stage-varying measure — one whose risk-aversion weight or tail fraction differs across stages, a stage with zero risk-aversion weight counting as the expectation — Novomodelo computes no bound on the risk-averse objective: the enumerated pass reports the probability-weighted path sum ∑ℓP(ℓ) C(ℓ)\sum_{\ell} P(\ell)\, C(\ell) above, the policy’s expected cost, and a gap rule is not supported (it is rejected at setup).

Contrast with the statistical mechanism (section 1): a sampled forward pass computes the same weighted-sum form — sample weight 1/M1/M per scenario — but that sum is a Monte Carlo estimator of the expectation, carrying genuine sampling error. Only the enumerated forward pass’s weights (the true leaf-path probabilities) make the sum exact rather than an estimate.

This is the training-phase, per-iteration mechanism: it is evaluated once per training iteration and feeds the gap computation (section 3). It is distinct from the post-training simulation’s census variant (section 4.5.4), which computes the same probability-weighted-sum form under the final policy, evaluated once after training completes.

2.1 Nested Risk-Adjusted Exact Bound (uniform CVaR)

Section titled “2.1 Nested Risk-Adjusted Exact Bound (uniform CVaR)”

When every stage applies the same CVaR measure ρ=(1−λ) E+λ CVaRα\rho = (1-\lambda)\,\mathbb{E} + \lambda\,\mathrm{CVaR}_\alpha, the probability-weighted path sum of section 2 is no longer the quantity the policy optimizes. SDDP minimizes a nested, time-consistent risk functional,

ρ[ c1+ρ[ c2+⋯+ρ[ cT ] ] ],\rho\big[\,c_1 + \rho[\,c_2 + \cdots + \rho[\,c_T\,]\,]\,\big],

in which the measure is applied stage by stage, not once to whole-path totals. The exact upper bound must be evaluated in that same nested form. Over the enumerated scenario tree, let node nn carry immediate cost c(n)c(n) at stage stage(n)\mathrm{stage}(n), with children ch(n)\mathrm{ch}(n) reached under conditional probabilities qn→n′q_{n \to n'}. Define, from the leaves up,

V~(n)=d1→stage(n) c(n)  +  ρ n′∈ch(n) ⁣[ V~(n′) ],V~(ℓ)=d1→T c(ℓ)  at a leaf,\tilde{V}(n) = d_{1 \to \mathrm{stage}(n)}\, c(n) \;+\; \rho_{\,n' \in \mathrm{ch}(n)}\!\big[\,\tilde{V}(n')\,\big], \qquad \tilde{V}(\ell) = d_{1 \to T}\, c(\ell)\ \ \text{at a leaf},

where ρ n′∈ch(n)[⋅]\rho_{\,n' \in \mathrm{ch}(n)}[\cdot] applies the stage measure to the children’s values weighted by qn→n′q_{n \to n'} — the same risk aggregation the cut construction applies in the backward pass. The exact upper bound is the value at the root:

zˉexact=V~(root).\bar{z}_{\text{exact}} = \tilde{V}(\text{root}).

It is exact for the same reason the expectation form is — the recursion visits every node of the deduplicated enumeration exactly once, so it carries no sampling distribution, and its standard deviation and confidence-interval half-width are identically zero.

Why the nested form, not the path-total form. Applying ρ\rho once to the distribution of whole-path totals C(ℓ)C(\ell) gives the end-of-horizon value ρend-of-horizon\rho_{\text{end-of-horizon}} of the path totals, a different functional from the nested objective ρnested\rho_{\text{nested}}: it is not an upper bound on the nested objective, and it can fall below the lower bound z‾\underline{z} of the risk-averse objective. Fed to the gap rule, it would then produce a negative gap that the rule would read as a lower/upper crossover, halting training before the policy has converged. The nested V~(root)\tilde{V}(\text{root}) instead satisfies V~(root)≥V⋆≥z‾\tilde{V}(\text{root}) \ge V^\star \ge \underline{z} at every iteration, so the gap stays non-negative and closes only at true convergence.

Under expectation — or a CVaR with λ=0\lambda = 0, which is expectation-equivalent — the measure is linear, the nesting telescopes, and V~(root)\tilde{V}(\text{root}) collapses exactly to the probability-weighted path sum ∑ℓP(ℓ) C(ℓ)\sum_{\ell} P(\ell)\, C(\ell) of section 2; the two forms coincide.

At each training iteration kk, the gap compares the lower bound from the cuts with the upper bound of the active forward-pass mechanism; both refer to the study started from its initial state x0x_0, with the stages numbered by the 1-based math convention.

The lower bound at iteration kk applies the first stage’s risk measure to the optimal values of the first stage over its openings:

z‾k=ρ1[ Q1k(x0,ω)  ∣  ω∈Ω1]\underline{z}^k = \rho_1\Big[\, Q_1^k(x_0, \omega) \;\Big|\; \omega \in \Omega_1 \Big]

where Q1k(x0,ω)Q_1^k(x_0, \omega) is the optimal value of the first-stage problem at the initial state x0x_0 under opening ω\omega, its immediate cost plus the discounted future cost that the iteration-kk cuts bound from below, with the opening’s full realization applied: inflow, load and non-controllable availability. Ω1\Omega_1 is the first stage’s opening set, its generated openings or a single supplied realization, and its openings are weighted uniformly. ρ1\rho_1 is the first stage’s risk measure, the expectation when risk-neutral; it aggregates the first stage’s own openings as well as those of the next stage (Risk Measures §6). The bound is stated in original cost units, with the cost scaling of the stage problems undone. It does not decrease in kk, because the problem it is evaluated on keeps every cut once added (Cut Management §5), and it is a valid lower bound under the hypotheses of Tier 1.

The upper bound is that of whichever forward-pass mechanism is active (section 1): under a sampled forward pass, zˉk\bar{z}^k is the statistical estimator’s sample mean; under an enumerated forward pass, zˉk=zˉexact\bar{z}^k = \bar{z}_{\text{exact}} (section 2).

The optimality gap gapk\text{gap}^k is the distance between these two bounds, also stated in percent of the lower bound.

Under the exact mechanism the compared bound is zˉk=zˉexact\bar{z}^k = \bar{z}_{\text{exact}}. The inequality zˉk≥z‾k\bar{z}^k \ge \underline{z}^k holds for the exact upper bound on the same tree under the same measure when Tier 1 holds (Tier 3), while an in-sample, out-of-sample, historical or external estimate can fall below z‾k\underline{z}^k.

For stopping rules that use the gap, see Stopping Rules, section 5.

As k→∞k \to \infty, gapk→0\text{gap}^k \to 0 for convex problems with finitely many scenarios, provided the upper bound is exact. Under a sampled forward pass, zˉk\bar{z}^k carries sampling error, so a small reported gap reflects that noise as well as genuine convergence.

A sampled forward pass draws each stochastic class (inflow, load and non-controllable sources) under that class’s forward scheme, and the post-training simulation of section 4.5 draws under a scheme of its own for each class; Scenario Generation §3.2 defines how each scheme samples. The sample mean of the discounted path costs estimates the policy’s expected cost under the law the scheme samples from, stated below per scheme. Under a risk-averse measure it estimates the expected cost, not the risk-adjusted value (section 1).

The in-sample scheme draws, at each stage, one opening of the fixed opening tree that the backward pass also uses. Its sample mean estimates the policy’s expected cost under the opening-tree law, the law of the model the cuts are built on. It is a statistical estimate that certifies nothing (Tier 3): its sampling error lets it fall below z‾k\underline{z}^k. An enumerated pass over the same tree is the exact bound of section 2, not an estimate.

The out-of-sample scheme draws fresh noise from the class’s applied stochastic model, from a seed independent of the opening tree’s. Its sample mean estimates the policy’s expected cost under the noise model’s law, with draws independent of the tree, rather than under the tree that discretizes that law for the backward pass. It is a statistical estimate that certifies nothing (Tier 3): it evaluates a law other than the opening tree’s, and it can fall below z‾k\underline{z}^k.

The external scheme replays one scenario of a supplied scenario set over all the stages of a trajectory. Its sample mean estimates the policy’s expected cost under the supplied scenarios’ law, the empirical law of that set. It is a statistical estimate that certifies nothing (Tier 3): it evaluates a law other than the opening tree’s, and it can fall below z‾k\underline{z}^k.

The historical scheme replays one window of the historical window pool over all the stages of a trajectory. Its sample mean estimates the policy’s expected cost under the replayed history, the empirical law of the windows in the pool. It is a statistical estimate that certifies nothing (Tier 3): it evaluates a law other than the opening tree’s, and it can fall below z‾k\underline{z}^k.

Novomodelo can also estimate an upper bound on expected total cost by running the trained policy on scenarios drawn independently of the training forward passes — a separate, post-training procedure distinct from the per-iteration training-phase mechanisms in sections 1–2. It supports two variants: a sampled estimator (Monte Carlo; sections 4.5.2–4.5.3) over an independently drawn scenario sample, and a census estimator (section 4.5.4) over an exhaustively enumerated population of scenarios.

The core methodological guarantee is that the noise used for the simulation forward pass is drawn independently of the noise used during training. Training forward passes sample under each class’s forward scheme (see Scenario Generation) to generate the trial states at which cuts are built; any cost computed by re-running the policy on those same training scenarios would produce a biased estimator — the cuts were shaped to be tight at those states. The simulation avoids this by drawing its NN scenarios under each class’s simulation scheme (§4.1–§4.4; the training scheme unless the simulation declares its own) with a seed derivation that no training iteration uses. Because cuts have no dependence on these independent draws, the resulting cost sample is an unbiased estimator of the policy’s expected cost under its scheme’s law.

The sampled variant executes a complete forward pass for each of the NN independently drawn scenarios, recording the total discounted cost CmC_m for scenario mm:

Cm=∑t=1Td1→t⋅ct(m)C_m = \sum_{t=1}^{T} d_{1 \to t} \cdot c_t^{(m)}

where ct(m)c_t^{(m)} is the immediate cost at stage tt of scenario mm, and d1→td_{1 \to t} is the cumulative discount factor from stage 1 to stage tt (see Discount Rate Formulation).

The sample mean is the Monte Carlo estimator of expected total cost:

Cˉ=1N∑m=1NCm\bar{C} = \frac{1}{N} \sum_{m=1}^{N} C_m

This estimator is unbiased under independent draws: E[Cˉ]=E[C]\mathbb{E}[\bar{C}] = \mathbb{E}[C]. The sample standard deviation is:

σC=1N−1∑m=1N(Cm−Cˉ)2\sigma_C = \sqrt{\frac{1}{N-1} \sum_{m=1}^{N} (C_m - \bar{C})^2}

the Bessel-corrected estimator appropriate to a drawn sample. For the census variant’s population-level counterpart, see section 4.5.4.

Under the normal approximation, the 95% confidence interval for E[C]\mathbb{E}[C] has half-width:

Δ95=1.96⋅σCN\Delta_{95} = 1.96 \cdot \frac{\sigma_C}{\sqrt{N}}

The approximation is reliable once NN is large enough for the central-limit-theorem regime to apply. The reported interval is [Cˉ−Δ95,  Cˉ+Δ95][\bar{C} - \Delta_{95},\; \bar{C} + \Delta_{95}].

Trade-off: every doubling of NN narrows the confidence interval by a factor of 2\sqrt{2}, but costs proportionally more LP solves — the per-check cost scales with NN times the horizon length. Because the half-width shrinks as σC/N\sigma_C / \sqrt{N}, a sufficiently large scenario count resolves the interval finely enough to distinguish a converged policy from one still improving.

This confidence interval applies to the sampled variant only. The census variant (section 4.5.4) reports the exact mean and population variance of an exhaustively enumerated population — there is no sampling error left to bound, so it carries no confidence interval.

When the simulation scenarios come from an exhaustive enumeration of the policy graph’s leaf paths rather than a sample — a declared census — the per-scenario weight wmw_m is that scenario’s leaf-path probability rather than a uniform sample weight, and the weights sum to one: ∑mwm=1\sum_m w_m = 1.

The census weighted mean replaces the sample mean:

Cˉ=∑mwm Cm\bar{C} = \sum_m w_m\, C_m

and the census weighted standard deviation is the true weighted population variance — no Bessel correction:

σC=∑mwm (Cm−Cˉ)2\sigma_C = \sqrt{\sum_m w_m\,(C_m - \bar{C})^2}

The population form omits the sampled variant’s N/(N−1)N/(N-1) correction because a census is exhaustive, not sampled: CmC_m ranges over the entire population of scenarios rather than a draw from it, so there is no downward bias in the naive variance to correct for.

Because the population is fully enumerated rather than estimated from a draw, the census estimator carries no confidence interval — Cˉ\bar{C} and σC\sigma_C are exact statistics of the enumerated population, not estimates of an unknown expectation.

The sole knob governing the simulation procedure — sampled or census — is the number of simulation scenarios NN. It controls the statistical resolution of the sampled estimator and the compute cost of the procedure simultaneously.

Raising NN narrows the sampled confidence interval as 1/N1/\sqrt{N}, while the compute cost — proportional to NN times the horizon length in LP solves — grows linearly in NN, so the scenario count trades statistical resolution directly against compute. Under the census variant, NN is instead fixed by the size of the declared enumeration rather than chosen for statistical resolution, since there is no confidence interval to narrow.

This simulation estimator is independent of the training loop: it is not consumed by any stopping rule and does not gate training termination. Training termination is governed by the gap-based stopping rule (see Stopping Rules, section 5), which compares the training-phase upper bound — the statistical or exact forward-pass estimator, sections 1–2 — against the lower bound at every iteration, using the training forward pass rather than the post-training simulation.

This section’s estimator instead reports the trained policy’s simulated cost distribution once training has finished: the sampled mean/standard-deviation/confidence-interval (sections 4.5.2–4.5.3), or the census weighted mean/population variance (section 4.5.4). See Convergence & Diagnostics for how this output is consumed operationally.

This appendix describes a reserved design that Novomodelo does not compute: a vertex-based inner approximation of the cost-to-go function (SIDP), which would evaluate the upper bound independently of the forward pass’s sampling mode.

The inner approximation Vˉt(x)\bar{V}_t(x) would be constructed from vertices (visited state-value pairs):

Vt={(x(1),vˉ(1)),(x(2),vˉ(2)),…,(x(It),vˉ(It))}\mathcal{V}_t = \{(x^{(1)}, \bar{v}^{(1)}), (x^{(2)}, \bar{v}^{(2)}), \ldots, (x^{(I_t)}, \bar{v}^{(I_t)})\}

where each vertex would store:

  • x(i)x^{(i)}: State vector entering stage tt, visited during forward passes
  • vˉ(i)\bar{v}^{(i)}: Upper bound on expected cost-to-go from that state (computed recursively)

At a state xx, the upper bound would be the cheapest convex combination of the vertex values, plus a Lipschitz penalty on the deviation of xx from the same convex combination of the vertex states:

Vˉt(x)=min⁡φ, u+, u−∑i∈Vtφi vˉ(i)+Lt⊤(u++u−)s.t.∑i∈Vtφi x(i)+u+−u−=x∑i∈Vtφi=1,φ, u+, u−≥0\begin{aligned} \bar{V}_t(x) = \min_{\varphi,\, u^+,\, u^-} \quad & \sum_{i \in \mathcal{V}_t} \varphi_i\, \bar{v}^{(i)} + L_t^\top (u^+ + u^-) \\ \text{s.t.} \quad & \sum_{i \in \mathcal{V}_t} \varphi_i\, x^{(i)} + u^+ - u^- = x \\ & \sum_{i \in \mathcal{V}_t} \varphi_i = 1, \qquad \varphi,\, u^+,\, u^- \geq 0 \end{aligned}

where φi\varphi_i is the convex-combination weight of vertex ii, u+u^+ and u−u^- are the componentwise positive and negative deviations of xx from the combined vertex state ∑iφi x(i)\sum_i \varphi_i\, x^{(i)}, and LtL_t is the vector of per-state-component Lipschitz constants Lt,jL_{t,j} (see below), so that the deviation of each state component jj is weighted by its own Lt,jL_{t,j}.

Interpretation: Vˉt\bar{V}_t is convex and piecewise linear in xx, and Vˉt(x(i))≤vˉ(i)\bar{V}_t(x^{(i)}) \leq \bar{v}^{(i)} at every vertex. It is an upper bound on the convex cost-to-go VtV_t when every vertex value bounds the cost-to-go at its state from above, vˉ(i)≥Vt(x(i))\bar{v}^{(i)} \geq V_t(x^{(i)}), and VtV_t changes by at most Lt,jL_{t,j} per unit change of each state component jj: the inner (upper) counterpart to the outer (lower) cut approximation, both convex.

The Lipschitz constants would bound the rate of change of the value function with respect to each state component. The state components carry different units, hm³ for a storage component and the units of its own lag for an inflow-lag component, so LtL_t is the vector of per-state-component constants Lt,jL_{t,j}, each in $ per unit of its component jj. For SDDP with penalty-based feasibility (relatively complete recourse):

  • Storage component. A hm³ of stored water is priced in the stage by the energy it displaces (the penalty bound in $/MWh times the energy that hm³ yields through the productivities of the plants it reaches, in MWh/hm³), by the penalties charged per hm³ of storage (the storage-floor and filling-target shortfall costs of Penalty System), and by the cost of spilling water that cannot be stored (converted from $/(m³/s·h) to $/hm³). Its constant Lt,jL_{t,j}, in $/hm³, bounds that price from above.
  • Inflow-lag component. Its constant carries the units of its own lag: it bounds, in $ per unit of that lag, the change in cost through the inflows that the lag enters.

Backward accumulation, per storage component jj: at the terminal stage, LT,jL_{T,j} is the stage’s own bound, whose energy term is built from the largest penalty coefficient cmaxpenaltyc_{max}^{penalty} of that stage; at each earlier stage tt, Lt,jL_{t,j} adds the stage’s own bound, whose energy term is built from the largest stage-tt penalty coefficient cmaxpenalty,tc_{max}^{penalty,t} (in $/MWh), to the discounted next-stage constant dt→t+1⋅Lt+1,jd_{t \to t+1} \cdot L_{t+1,j}, where dt→t+1d_{t \to t+1} is the discount factor for transition t→t+1t \to t+1 (see Discount Rate Formulation).

During the upper bound evaluation pass (a backward pass variant), vertex values would be computed as follows.

At terminal stage TT:

vˉ(i)=EωT[cT(x(i),ωT)](expected immediate cost only)\bar{v}^{(i)} = \mathbb{E}_{\omega_T}\left[c_T(x^{(i)}, \omega_T)\right] \quad \text{(expected immediate cost only)}

At stage t<Tt < T:

For each vertex (x(i),⋅)∈Vt(x^{(i)}, \cdot) \in \mathcal{V}_t:

  1. For each scenario ωt\omega_t, the stage subproblem would be solved with incoming state x(i)x^{(i)} and realization ωt\omega_t
  2. The optimal outgoing state xt∗(ωt)x_t^*(\omega_t) would be obtained
  3. The next stage’s inner approximation would be evaluated at that outgoing state: θˉ(ωt)=Vˉt+1(xt∗(ωt))\bar{\theta}(\omega_t) = \bar{V}_{t+1}(x_t^*(\omega_t))
  4. The vertex value would be set as the expected discounted cost-to-go:
vˉ(i)=Eωt[ct(x(i),ωt)+dt→t+1⋅θˉ(ωt)]\bar{v}^{(i)} = \mathbb{E}_{\omega_t}\left[c_t(x^{(i)}, \omega_t) + d_{t \to t+1} \cdot \bar{\theta}(\omega_t)\right]

For policy evaluation with the inner approximation, the stage LP would replace the outer approximation (cut constraints on θ\theta) with the inner approximation (convex-combination constraints on θˉ\bar{\theta}).

Standard LP (outer approximation, lower bound):

min⁡  ct(xt,ut)+dt→t+1⋅θ\min \; c_t(x_t, u_t) + d_{t \to t+1} \cdot \theta s.t. θ≥β0+β⊤xtfor every cut (β0,β)\text{s.t. } \theta \geq \beta_0 + \beta^\top x_t \quad \text{for every cut } (\beta_0, \beta)

Inner approximation LP (upper bound):

min⁡  ct(xt,ut)+dt→t+1⋅θˉ\min \; c_t(x_t, u_t) + d_{t \to t+1} \cdot \bar{\theta} s.t.   θˉ≥∑i∈Vt+1φi vˉ(i)+Lt+1⊤(u++u−)∑i∈Vt+1φi x(i)+u+−u−=xt∑i∈Vt+1φi=1,φ, u+, u−≥0\begin{aligned} \text{s.t. } \; & \bar{\theta} \geq \sum_{i \in \mathcal{V}_{t+1}} \varphi_i\, \bar{v}^{(i)} + L_{t+1}^\top (u^+ + u^-) \\ & \sum_{i \in \mathcal{V}_{t+1}} \varphi_i\, x^{(i)} + u^+ - u^- = x_t \\ & \sum_{i \in \mathcal{V}_{t+1}} \varphi_i = 1, \qquad \varphi,\, u^+,\, u^- \geq 0 \end{aligned}

The future-cost variable θˉ\bar{\theta} of stage tt stands for the next stage’s inner approximation, so the weights range over the vertices of Vt+1\mathcal{V}_{t+1}, the deviations are priced by Lt+1L_{t+1}, and the two constraints on the outgoing state xtx_t are those of the definition of Vˉt+1\bar{V}_{t+1}: at the optimum, θˉ=Vˉt+1(xt)\bar{\theta} = \bar{V}_{t+1}(x_t), with VˉT+1=0\bar{V}_{T+1} = 0 at the last stage.

Additional variables (one weight per vertex, one deviation pair per state component):

VariableDomainDescription
φi\varphi_i≥0\geq 0Convex-combination weight of vertex ii
u+u^+≥0\geq 0Componentwise positive deviation of xtx_t from the combined vertex state
u−u^-≥0\geq 0Componentwise negative deviation of xtx_t from the combined vertex state
θˉ\bar{\theta}freeUpper bound on future cost, bounded below by the convex-combination value
AspectImpact
Vertices per stageTypically O(iterations×Nforward_passes)\mathcal{O}(\text{iterations} \times N_{\text{forward\_passes}})
LP size increasenvertices+2×nstaten_{vertices} + 2 \times n_{state} additional variables
Evaluation frequencyTrade-off between gap accuracy and runtime
MemoryVertices stored separately from cuts

For the reserved cyclic policy graphs design (see Horizon Modes), the inner approximation would operate on the same seasonal cut-pool structure: vertices organized by season τ\tau, not by absolute stage ID. The Lipschitz constant would need to account for the cumulative discount around the cycle, which bounds the geometric series of future contributions.

The convergence guarantee would still hold: with dcycle<1d_{\text{cycle}} < 1, both the outer (cut) and inner (vertex) approximations would converge to the true value function at the fixed point.

  • SDDP Algorithm — Core algorithm providing the outer approximation (lower bound) that this chapter complements
  • Notation Conventions — Standard symbols for state variables, value functions, and cost-to-go
  • Discount Rate Formulation — Discount factor dd used in the exact bound’s discounted cost (section 2) and in the reserved vertex value computation and Lipschitz accumulation (appendix)
  • Policy Graphs — The enumerated-versus-sampled forward-pass distinction that selects between the statistical and exact upper-bound mechanisms (sections 1–2)
  • Horizon Modes — The reserved cyclic policy-graph target design and the season-indexed pool structure the appendix’s reserved inner approximation would mirror
  • Cut Management — Outer approximation cuts that provide the lower bound counterpart
  • Stopping Rules — The gap-based stopping rule, which compares this chapter’s training-phase upper bound (sections 1–2) against the lower bound (section 3)
  • Risk Measures — The nested risk-adjusted lower bound and why only the exact nested bound certifies a risk-averse policy
  • Scenario Generation — The opening tree and the forward sampling schemes whose estimates section 4 interprets, in training and in the post-training simulation (section 4.5)
  • Running Novomodelo: Convergence & Diagnostics — the software guide for reading and assessing this estimator’s output.