Robustness, Calibration, and Safe Control › Risk-Sensitive and Constrained Planning
World Models HandbookAll chapters Robustness, Calibration, and Safe Control › Risk-Sensitive and Constrained PlanningOne section · Sections in this chapter4 / 8 ↓
Reading tools Definitions & inline links
Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.
Article links
Make inline references clickable
Everything so far has been about the model. Now we change the objective. Minimizing expected cost is risk-neutral with respect to that cost: a certain cost of 10 and an equally likely cost of 0 or 20 have the same expectation. A point prediction does not force risk neutrality; a controller can still use conservative margins, robust constraints, or nonlinear costs. A predictive distribution permits explicit tail objectives, whose suitability depends on the application's losses and requirements.
Two families of alternatives recur in practice:
- Risk-sensitive objectives use a tail-sensitive functional. For integrable costs, CVaR at level averages the worst probability mass, using fractional boundary mass when necessary. It approaches expected cost as decreases to zero; near one it emphasizes increasingly extreme upper-tail costs. Here selects the worst quarter.
- Constrained objectives separate feasibility requirements from performance. A pointwise constraint limits predicted states; a chance constraint such as imposes a hard bound on violation probability, not a promise that every realized state stays inside. The objective can itself be expected cost or a risk-sensitive functional.
The expected-cost objective summarizes average loss; CVaR summarizes a chosen upper tail. These answer different questions. Expected cost can penalize rare failures heavily if their assigned loss is large, and a hard constraint can reject them without CVaR. Conversely, minimizing CVaR can still permit a safety violation if it improves the chosen tail objective. Specify safety requirements separately from performance preferences.
Where the distribution comes from
A risk-sensitive planner needs a distribution of outcomes for a candidate action sequence, not a single rollout. Several sources are available, and they are not equivalent:
- Ensemble members as samples. Run the candidate sequence through each member. This uses variation between fitted models as an approximation to epistemic uncertainty, i.e., uncertainty about the model fit. Its quality depends on both coverage of plausible dynamics and the weights assigned to members; bootstrap ensembles do not by themselves guarantee calibrated tail probabilities. See Part VIII: Decision-Centric Research Lineages for the lineage.
- Residual-noise propagation. Add sampled process noise to each member's predicted transition. In this toy plant, position and velocity noise innovations satisfy , so they must not be sampled independently. This relation concerns the noise contributions, not the full state increments. Combining model fits with this noise defines an approximate rollout distribution; one-step calibration does not validate its multi-step joint distribution.
- Scenario evaluation. Evaluate explicit parameter and disturbance choices. A finite scenario set is inspectable, but checking it does not prove safety for unsampled conditions. Scenario-optimization guarantees require additional sampling, optimization, and support assumptions; merely naming a chosen schedule worst case supplies none.
The code combines alternative fitted models with residual-noise draws. It does not explicitly add total predictive variance on top of ensemble variation. Nevertheless, held-out residual variance can itself include fitting error, so this construction is not a decomposition into independent uncertainty sources. Its joint rollout spread requires validation; over- or under-dispersion and missed model families can affect planning.
For a random cost with and , CVaR has the threshold representation
where:
- : the random episode cost
- : the confidence level, where is the fraction of the distribution treated as the tail
- : a scalar threshold; an -quantile is a minimizer, with possible non-uniqueness for discrete distributions
- : the positive part, counting only how far each outcome exceeds the threshold
The expression includes the threshold itself plus scaled expected excess. It is convex in but generally non-smooth. Pointwise convex loss in controller parameters together with a parameter-independent sampling law is sufficient for convexity of CVaR in those parameters, not necessary in every instance. Nonlinear learned rollouts provide no such guarantee automatically. See Rockafellar and Uryasev's general-loss treatment.
For equal-weight samples, sort costs in descending order, . Let , , and . The exact empirical-distribution CVaR includes fractional boundary mass:
When is an integer, average the largest values and omit the boundary term entirely. Otherwise the next value contributes fraction . This also avoids indexing past the array when floating-point arithmetic rounds to at a tiny positive . Averaging the largest values is generally an approximation. At and , four costs contribute fully and the fifth contributes half. Such a small effective tail sample is noisy; evaluate selected controllers independently of the search samples.
The running environment already includes Gaussian process noise. We now add a soft envelope penalty to stage cost when exceeds a chosen threshold. This can amplify expensive excursions, but it is not a control barrier function or a hard constraint. Quadratic costs can also have substantial tails, and neither this penalty nor CVaR guarantees different actions or improved realized tail costs. The experiment measures those outcomes rather than assuming them.
The distinction between averaging across all outcomes and averaging across the worst outcomes is easiest to see directly on a cost distribution. The cell below draws a right-skewed set of synthetic episode costs and computes both summaries, using the same sample estimator the planner optimizes.
# A synthetic right-skewed cost distribution, used only to make the CVaR idea
# concrete. The seed is fixed so the figure is reproducible.
CVAR_RNG = np.random.default_rng(31337)
COST_SAMPLES = CVAR_RNG.lognormal(mean=0.30, sigma=0.60, size=4000)
CVAR_ALPHA = 0.75
cost_expectation = float(COST_SAMPLES.mean())
cvar_k = max(1, int(np.ceil((1.0 - CVAR_ALPHA) * COST_SAMPLES.size)))
cost_cvar = float(np.sort(COST_SAMPLES)[-cvar_k:].mean())
cost_tail_cut = float(np.quantile(COST_SAMPLES, CVAR_ALPHA))
SOFT_LIMIT = 0.50
BARRIER_WEIGHT = 5.0
W_P, W_V, W_U = 1.0, 0.05, 0.01
W_STACK = np.stack([W for W, _ in members]) # (M, F, 2)
M_MODELS, F_FEAT = W_STACK.shape[0], W_STACK.shape[1]
def plan(
state,
rng_,
mode="mean",
horizon=8,
n_cand=128,
n_draws=2,
cvar_alpha=0.75,
u_max=U_VALID,
return_sequence=False,
):
"""Random-shooting MPC. Return the first action, or the selected sequence."""
if mode not in ("mean", "cvar"):
raise ValueError("mode must be mean or cvar")
for name, value in (
("horizon", horizon),
("n_cand", n_cand),
("n_draws", n_draws),
):
if (
isinstance(value, (bool, np.bool_))
or not isinstance(value, (int, np.integer))
or value <= 0
):
raise ValueError(f"{name} must be a positive integer")
if not 0.0 < cvar_alpha < 1.0:
raise ValueError(
"CVaR confidence level must be strictly between zero and one"
)
S = M_MODELS * n_draws
W_rows = W_STACK[np.arange(S) % M_MODELS]
A = rng_.uniform(-u_max, u_max, size=(horizon, n_cand))
s = np.tile(np.asarray(state, dtype=float), (S, n_cand, 1))
costs = np.zeros((S, n_cand))
for t in range(horizon):
u = np.broadcast_to(A[t], (S, n_cand))
Phi = features(
np.column_stack([s[:, :, 0].ravel(), s[:, :, 1].ravel(), u.ravel()])
)
delta = np.einsum(
"snf,sfj->snj", Phi.reshape(S, n_cand, F_FEAT), W_rows
)
# A velocity innovation also shifts position by DT times that innovation.
noise_v = rng_.normal(0.0, np.sqrt(ALEATORIC[1]), size=(S, n_cand))
delta = delta + np.stack([DT * noise_v, noise_v], axis=-1)
s = s + delta
over = np.maximum(0.0, np.abs(s[:, :, 0]) - SOFT_LIMIT)
costs += (
W_P * s[:, :, 0] ** 2
+ W_V * s[:, :, 1] ** 2
+ W_U * A[t] ** 2
+ BARRIER_WEIGHT * over**2
)
if mode == "mean":
score = costs.mean(axis=0)
else:
tail_mass = (1.0 - cvar_alpha) * S
whole = int(np.floor(tail_mass))
fraction = tail_mass - whole
descending = np.sort(costs, axis=0)[::-1]
tail_sum = descending[:whole].sum(axis=0)
if fraction > 0.0 and whole < S:
tail_sum += fraction * descending[whole]
score = tail_sum / tail_mass
selected = A[:, int(np.argmin(score))]
return selected.copy() if return_sequence else float(selected[0])At the same state and RNG state, both modes generate the same candidate actions, member assignments, and linked noise draws. Only their cost aggregation changes: mean versus empirical CVaR. Once actions differ, closed-loop states and therefore imagined futures differ too. Using the same seeds pairs the search randomness; it does not make later state-conditioned predictions identical.
Running the comparison
We pair environment noise streams and search seeds across controllers. Different actions still lead to different states. Common random numbers reduce the variance of a difference when paired outcomes have positive covariance: . They can increase it when covariance is negative. This experiment reports a paired finite comparison, not a measured reduction in required episode count; see Glasserman and Yao's conditions for common random numbers.
N_EPISODES = 30
N_STEPS = 32
env_sampler = np.random.default_rng(4242)
EPISODES = []
for _ in range(N_EPISODES):
params = sample_nominal(env_sampler)
p0 = env_sampler.uniform(0.20, 0.40) * env_sampler.choice([-1.0, 1.0])
v0 = np.sign(p0) * env_sampler.uniform(0.20, 0.50)
EPISODES.append((params, (p0, v0)))
def run_regulation(mode, params, s0, steps, env_rng, plan_rng):
p, v = float(s0[0]), float(s0[1])
total = 0.0
for _ in range(steps):
u = plan(np.array([p, v]), plan_rng, mode=mode)
p, v = simulate(params, (p, v), [u], env_rng, SIGMA_P)[1]
over = max(0.0, abs(p) - SOFT_LIMIT)
total += (
W_P * p * p
+ W_V * v * v
+ W_U * u * u
+ BARRIER_WEIGHT * over * over
)
return total
def evaluate_planner(mode, plan_seed):
env_rng = np.random.default_rng(9999)
plan_rng = np.random.default_rng(plan_seed)
return np.array(
[
run_regulation(mode, prm, s0, N_STEPS, env_rng, plan_rng)
for prm, s0 in EPISODES
]
)
costs_mean = evaluate_planner("mean", 101)
costs_cvar = evaluate_planner("cvar", 101)planner mean cost median 90th pct max expected-cost MPC 1.600 1.670 2.372 2.593 CVaR MPC 1.673 1.727 2.463 2.853
The table gives mean, median, 90th percentile, and maximum episode cost for each planner across thirty paired episodes. These are empirical cost summaries, not population tail guarantees or safety outcomes. Reporting several summaries makes tradeoffs visible that a mean alone would hide.
The executed CVaR controller has mean cost 1.673, 90th-percentile cost 2.463, and maximum 2.853, compared with 1.600, 2.372, and 2.593 for expected-cost MPC. It does not improve the realized upper tail on these thirty episodes. Model mismatch, finite candidate search, and tail-sampling error are possible explanations, not isolated causal findings. Tune , sample counts, and cost weights on separate validation populations, then evaluate across independent seeds. Optimizing an imagined tail is not the same as improving the actual one.


From soft penalties to explicit constraints
A finite soft penalty permits a tradeoff: a violating candidate can win if reductions in other cost terms outweigh its extra penalty. Our zero-target position cost does not make intrinsically better than . Nor does this example establish that no penalty choice could enforce feasibility in any problem: some bounded or finite problems admit exact penalties. The quadratic penalty here supplies no proof of pointwise safety. If an envelope is a requirement, encode and justify it separately rather than treating a tuned weight as a certificate.
The alternatives each have costs:
- Hard constraints on a nominal rollout enforce at modeled steps. Feasibility establishes that modeled property, not automatically the real plant's safety. Connecting the two requires justified error and disturbance assumptions.
- Chance constraints enforce under a specified probability law. Computing or estimating that probability can be difficult. Finite samples can under- or overestimate it, and rare violations can be absent from the sample. A bound on violation probability is a different requirement from all-disturbance invariance.
- Runtime assurance. Check a proposal against an independently justified safety condition and select a verified fallback when necessary. Guarantees require a sound decision module, an appropriate initial condition, and a fallback with proven properties under the declared plant and disturbance assumptions. Our next experiment illustrates the switching architecture without satisfying those proof obligations.
The code above implements a soft penalty and sampled CVaR, not constrained optimization. Zero observed violations among eighteen scenarios does not imply zero violation probability. A predictive safety filter needs justified uncertainty bounds and recursive feasibility; see Wabersich and Zeilinger. For continuous control-affine dynamics , a continuously differentiable barrier describes and constrains actions through , with an appropriate extended class-K function (for example , ). Forward invariance additionally needs regularity, feasible actions, correct dynamics or robust error bounds, an admissible initial state, and satisfaction over time. Sampling and delay require additional treatment. Our quadratic penalty is not this condition; see Ames et al..