chc.barrier¶
Stability tier: stable.
Safety certificates when the control effect is only PARTIALLY IDENTIFIED (§40).
The pessimism line (chc.support, chc.uncertainty) spends an identification radius on
performance: a worse effect estimate buys a wider penalty and a costlier plan. This module spends
the same radius on safety, and the accounting is different in a way that matters operationally.
For a control-affine plant xdot = f(x) + B u and a safe set {h >= 0}, the barrier condition
is grad h . (f + B u) >= -alpha * h. Write a = grad h . f for the drift term, g for the
control channel and U for the actuation limit. If the effect matrix is known only up to a radius
Delta -- here an identification radius from §32's bounded-density-ratio model at level
Gamma, not a disturbance bound -- the guaranteed barrier derivative is a + g*u - d*|u| with
d = Delta * ||grad h||, and:
- the best guaranteed margin is
a + (|g| - d)_+ * U, so the margin lost to an identification radiusdisU * min(d, |g|)-- first order indwhile control authority lasts, then flat: pastd = |g|there is nothing left to lose; - at
d >= |g|the robust-optimal action is exactly zero: with the sign of the channel unidentified, acting cannot improve the guarantee (the safety analogue of §11's sign threshold); - certification is sharp at
d* = |g| - D/U, whereD = -alpha*h - ais the deficit the drift leaves for the controller, which inverts to a largest tolerable sensitivityGamma*. Three regimes, and only the third is the interesting one:D <= 0(the drift alone is safe, no radius can break it),D > U*|g|(nominally infeasible -- not certified even atd = 0), and0 < D <= U*|g|(d*in[0, |g|), the case the threshold formula describes).
The tightening itself is the standard robust-CBF one (Jankovic 2018; Kolathaya-Ames 2019). What is
new here is the source of the radius and the resulting order dichotomy: the same effect error
costs performance regret only at second order (§33, L_reg * e**2): an interior optimum has a
vanishing gradient, while a binding constraint has no envelope protection and pays at first
order. Objectives are protected; constraints are not. That comparison lives in d < |g|, which is
also where any usable controller lives -- once the radius exceeds the channel the safety loss is
capped at U*|g| simply because the guarantee is already gone. Within that band, and below
e = U / L_reg, safety is the larger loss by a ratio that diverges as the error shrinks.
Uncertainty-set assumption. a + <w, u> - d*||u|| is the worst case for a symmetric,
isotropic set: ||u||_2 <= U for the action and a dual-norm ball of radius d for the channel
error. It is exact there (Cauchy-Schwarz is attained). For box actuation limits or anisotropic
channel uncertainty the worst case is the corresponding support function and the closed forms below
are only an outer bound. For an asymmetric scalar interval g_true in [g - d_lo, g + d_hi] the
two branch slopes differ (g - d_lo right, g + d_hi left) and the zero-action rule reads in
its general form: acting is pointless exactly when the identified interval contains zero.
NumPy, like the rest of the §32-§40 sensitivity line, so it is independent of the JAX x64 flag.
Maxima validation/barrier_feasibility.mac, Rocq proofs/barrier_feasibility.v.
BarrierConfoundingCurve
dataclass
¶
Measured evidence for §40 over a sensitivity grid on one confounded safety problem.
SafetyFilterBenchmark
dataclass
¶
Closed-loop evidence for the §40 claim that a regret-sized budget is not a safety budget.
control_channel(grad_h, b_hat)
¶
||B^T grad h|| -- how strongly the control can move the barrier, in the best direction.
The multivariate stand-in for the scalar |g|. Cauchy-Schwarz is tight at
u = U * w / ||w||, so every bound below is attained rather than conservative.
robust_barrier_margin(drift, channel, radius, u_max)
¶
Best barrier derivative guaranteed against every effect inside the identified set.
drift + (channel - radius)_+ * u_max. The clip at zero is the whole content: past
radius = channel extra actuation buys nothing, because the adversary can cancel it. So the
margin lost relative to a perfectly identified channel is u_max * min(radius, channel) --
first order in the radius until the authority runs out, then constant. Exact for a Euclidean
action ball and an isotropic channel radius (see the module docstring).
robust_safe_action(grad_h, b_hat, radius, u_max)
¶
The action attaining robust_barrier_margin: full authority, or nothing at all.
Returns exactly 0 when radius >= ||B^T grad h||. That is not a numerical artefact and
not conservatism -- it is the optimum: with the channel's sign unidentified, every nonzero
action has a worst case at least as bad as standing still.
identification_radius_threshold(drift, channel, u_max, alpha_h)
¶
Largest radius d* whose safety certificate still holds: channel - D / u_max.
D = -alpha_h - drift is the deficit the drift leaves for the controller to cover, and the
answer is piecewise in it -- the formula alone is a trap, because it happily returns a
negative "largest radius" for a problem no radius can save:
D <= 0-- the uncontrolled system already satisfies the barrier. No radius can break it, so the threshold is vacuous andinfsays so rather than inviting a comparison.D > u_max * channel-- nominally infeasible: even a perfectly identified channel at full authority cannot cover the deficit, so nothing is certified, not even atradius = 0.nan(the module's empty-set convention, as inadmissible_action_interval).0 < D <= u_max * channel-- the case worth having a threshold for:d*lands in[0, channel)and certification holds iffradius <= d*.
barrier_gamma_star(threshold_radius, cvar_gap, grad_norm)
¶
Largest MSM Gamma a safety certificate survives: (gap + c) / (gap - c).
Inverts §32's Delta(Gamma) = (Gamma-1)/(Gamma+1) * cvar_gap at threshold_radius, with
c = threshold_radius / grad_norm the effect-space radius the barrier can absorb. The closed
form is only valid on 0 < c < cvar_gap; outside it the four cases are genuinely different
answers rather than edge-case noise, and the denominator would silently change sign:
c < 0(ornan) -- nothing is certified, not even atGamma = 1where the radius is zero.nan, because noGamma >= 1works and reporting1.0would claim the opposite.c == 0-- exact identification and nothing more:1.0.0 < c < cvar_gap-- the finite ceiling(gap + c) / (gap - c).c >= cvar_gap--Deltasaturates atcvar_gapasGamma -> inf, so the threshold is beyond anything the sensitivity model can produce:inf.
grad_norm == 0 is a state where the barrier is flat, such as the centre of a ball, and there
the radius Delta * grad_norm is zero at every Gamma: the step holds at every level or at
none, inf when threshold_radius >= 0 and nan otherwise.
admissible_action_interval(channel, radius, u_max, drift, alpha_h)
¶
The scalar actions whose guaranteed barrier derivative clears -alpha_h.
channel is the signed grad h . B, unlike the norm taken by
robust_barrier_margin -- which way to push is the whole question here. The guaranteed
derivative drift + channel*u - radius*|u| is concave in u, so the admissible set is an
interval; combined with |u| <= u_max it stays one. Returns an empty interval as
(nan, nan) when no admissible action exists, which the caller must handle rather than
silently clip into.
A non-positive deficit means u = 0 is admissible -- it does not mean every action is.
The control that serves the task is exactly the one that can spend the drift's slack and cross
the boundary, so both ends are computed from the branch slopes in every case.
robust_safety_filter(u_nominal, channel, radius, u_max, drift, alpha_h)
¶
Least-restrictive admissible action: the nominal, clipped into the certified interval.
Minimal intervention in the exact sense -- among all actions whose guaranteed margin clears, the
one closest to what the task controller asked for. Scalar control only: for m > 1 inputs the
same set is convex but its projection is no longer a clip, and a filter that quietly over-brakes
would misreport the price of safety. Use robust_safe_action there, which maximises the
margin rather than tracking a nominal.
When the interval is empty -- the deficit exceeds what the identified channel can deliver -- the
margin-maximising action sign(channel)*u_max is returned: it does not certify, and the
caller should already know that from identification_radius_threshold.
barrier_confounding_certificate(channel=0.6, drift=-0.9, u_max=2.0, alpha_h=0.5, cvar_gap=1.0, grad_norm=1.0, l_reg=3.0, gammas=(1.0, 1.5, 2.0, 3.0, 5.0, 9.0))
¶
Sweep the sensitivity level and check the threshold, the zero-action rule and the orders.
The defaults are chosen so the sweep crosses every regime rather than sitting inside one: the
drift is in deficit (D = 0.4 > 0) so the controller is load-bearing, Gamma* = 7/3 falls
inside the grid so certification genuinely fails partway, and the radius overtakes the channel
at Gamma = 4 so the tail of the grid exercises the zero-action rule. A configuration with
D <= 0 would certify everything and prove nothing.
safety_filter_benchmark(b_true=1.0, kappa=-0.5, confounding=1.0, gamma=3.0, decay=0.3, x0=0.0, x_ref=3.0, x_limit=2.0, alpha=1.0, dt=0.1, n_steps=60, u_max=6.0, n_data=4000, seed=0)
¶
Drive a confounded plant at a reference beyond a safety limit, four ways.
The scalar plant x' = decay*x + b_true*u must track x_ref while respecting
x <= x_limit, and the two are in conflict by construction -- the reference sits past the
limit, so nothing but the constraint stops the controller. The drift is unstable (decay >
0), which is what makes the threshold bite: near the limit the plant pushes outward on its
own, so the controller has a real deficit to cover and Gamma* is finite. The actuator gain
is calibrated from an observational log whose action responded to a latent driver (kappa < 0
attenuates it), so the controller believes a weaker actuator than it has and over-commands.
The four rows are the point:
oraclefilters with the true gain and a zero radius -- the best achievable safe tracking;safety_calibratedfilters with the biased gain and the §32 radius atgamma;regret_calibratedshrinks its action by the §33 accounting instead -- the radius spent on the objective, which is what this library did everywhere before §40;greedybelieves the biased gain and does nothing about it.
Returns violation rate, worst excursion and tracking cost for each. Read the tracking column
with its floor in mind: a controller that respects the limit cannot beat
(x_limit - x_ref)**2 on this plant, so the violators' lower cost is bought with the
excursions in the other two columns and is not evidence that they control better. This is a
demonstration on one synthetic plant, not a theorem: it grounds the order argument rather
than proving it.