04 — Controls with Structure: Bang-Bang and Switching

Mathematical Foundations of Control and Machine Learning — Winter 2026

Central question. How do the structure of the admissible controls and the choice of cost determine the qualitative structure of an optimal control?

Minimizing a dual functional of the adjoint produces the control of minimal energy. This notebook shows that the same dual method can select controls with other properties — on/off controls of minimal amplitude, and controls that use one actuator at a time — by changing only the first term of the dual functional.

Table of Contents

  1. Why structured controls? — amplitude limits, on/off actuation, one actuator at a time
  2. The bang-bang functional — \(L^1\) of the observation, squared
  3. The optimality condition and the bang-bang control
  4. Why the bang-bang control has minimal amplitude — Hölder duality
  5. Two actuators: switching controls — the \(\max\) functional
  6. Details — analyticity, differentiability and variants
  7. Switching beyond the actuators
  8. Control ↔︎ ML: switches and layers
  9. Exercises
%matplotlib inline
import numpy as np
import torch
import matplotlib.pyplot as plt
import plotting as P           # the course palette, the house style, and the figure helpers

torch.manual_seed(0)
torch.set_default_dtype(torch.float64)
# RK4 integrator for x' = f(t, x) along the time grid ts
def odeint(f, x0, ts):
    xs = [x0]
    for t, t1 in zip(ts[:-1], ts[1:]):
        x, h = xs[-1], t1 - t
        k1 = f(t, x)
        k2 = f(t + h / 2, x + h / 2 * k1)
        k3 = f(t + h / 2, x + h / 2 * k2)
        k4 = f(t + h, x + h * k3)
        xs.append(x + h / 6 * (k1 + 2 * k2 + 2 * k3 + k4))
    return torch.stack(xs)

def lti(A, B, u):
    """Right-hand side of x' = Ax + Bu, with u an open-loop control u(t) -> R^m."""
    return lambda t, x: A @ x + B @ u(t)

def kalman(A, B):
    """Kalman matrix [B | AB | ... | A^{n-1}B]."""
    cols = [B]
    for _ in range(A.shape[0] - 1):
        cols.append(A @ cols[-1])
    return torch.cat(cols, dim=1)

def gramian(A, B, T, n_quad=400):
    """G_T = ∫_0^T e^{A(T-s)} B Bᵀ e^{Aᵀ(T-s)} ds, by the trapezoid rule (τ = T - s)."""
    taus = torch.linspace(0, T, n_quad + 1)
    integrand = torch.stack([(E := torch.matrix_exp(A * tau)) @ B @ B.T @ E.T for tau in taus])
    return torch.trapezoid(integrand, taus, dim=0)

Where are we?

Recap of notebook 03. For \(x'=Ax+Bu\), \(x(0)=x^0\), and the adjoint \(-\varphi'=A^*\varphi\), \(\varphi(T)=\varphi_T\), a control \(u\) steers \(x^0\) to \(x^1\) if and only if \[\int_0^T\langle u,B^*\varphi\rangle\,dt=\langle x^1,\varphi_T\rangle-\langle x^0,\varphi(0)\rangle\qquad\text{for every }\varphi_T\in\mathbb R^n.\tag{C}\] Minimizing \(J(\varphi_T)=\tfrac12\int_0^T|B^*\varphi|^2-\langle x^1,\varphi_T\rangle+\langle x^0,\varphi(0)\rangle\) gives the control \(u_2=B^*\hat{\varphi}\), the control of minimal \(L^2\) norm. Coercivity comes from observability, which is equivalent to the Kalman condition.

Duality answers whether a target can be reached and how the controls can be characterized, through observability. This notebook asks what optimal controls look like once structural constraints are imposed on the admissible controls. The functional \(J\) produces one particular control, the cheapest in energy. But there are infinitely many controls — smooth ones, bang-bang ones, and more. This notebook shows that the dual method can select controls with other properties. Only the first term of the functional changes:

Dual functional (first term) Resulting control What it minimizes Where
\(\tfrac12\int_0^T\lvert B^*\varphi\rvert^2\) \(u_2=B^*\hat{\varphi}\) \(L^2\) norm (energy) recap
\(\tfrac12\big(\int_0^T\lvert B^*\varphi\rvert\big)^2\) \(u_\infty=\lambda\,\operatorname{sgn}(B^*\hat{\varphi})\), bang-bang \(L^\infty\) norm (amplitude) §§2–4
\(\tfrac12\int_0^T\max\big(\lvert b_1\cdot\varphi\rvert^2,\lvert b_2\cdot\varphi\rvert^2\big)\) \(u_i=b_i\cdot\hat{\varphi}\) where actuator \(i\) dominates, switching one actuator at a time §5

The adjoint system, the duality identity and condition (C) stay exactly as in the recap.

1. Why structured controls?

Three practical limitations motivate this notebook.

  • Amplitude constraints. Real actuators are bounded: a motor has a maximal torque, a valve opens at most fully. The question is then what is the smallest amplitude \(\|u\|_{L^\infty}=\sup_t|u(t)|\) that still reaches the target, and what such a control looks like.
  • On/off actuation. Many actuators work best at full power or not at all. A control taking only two values \(\pm\lambda\) is called bang-bang.
  • Sparsity in actuators. When several actuators are available, it may be impossible or wasteful to use them simultaneously, because of shared power or interference. The controllers of a system with several actuators are of switching form when only one of them is active at each instant.

All three questions have the same answer, in the duality framework of the recap: choose a different dual functional.

2. The bang-bang functional

Consider a single control, \(m=1\), so that \(B\in\mathbb R^{n\times1}\) is a column vector and \(u:[0,T]\to\mathbb R\). To build bang-bang controls we use the functional

\[ J_{bb}(\varphi_T)=\frac12\Big(\int_0^T|B^*\varphi(t)|\,dt\Big)^2-\langle x^1,\varphi_T\rangle+\langle x^0,\varphi(0)\rangle, \qquad\varphi\text{ the solution of the adjoint system}. \tag{BB} \]

Compared with the HUM functional, the \(L^2\) norm of the observation \(B^*\varphi\) is replaced by its \(L^1\) norm, \(N(\varphi_T):=\int_0^T|B^*\varphi|\,dt\), and then squared.

Existence of a minimizer. In finite dimension the argument is short. If the pair \((A,B)\) satisfies the Kalman condition, then \(N(\varphi_T)=0\) forces \(B^*\varphi\equiv0\), and hence \(\varphi_T=0\) by unique continuation. So \(N\) is a norm on \(\mathbb R^n\). All norms on \(\mathbb R^n\) are equivalent, so \(N(\varphi_T)\ge c\,|\varphi_T|\) for some \(c>0\). With \(d=x^1-e^{AT}x^0\), \[ J_{bb}(\varphi_T)=\tfrac12N(\varphi_T)^2-\langle d,\varphi_T\rangle\;\ge\;\tfrac12c^2|\varphi_T|^2-|d|\,|\varphi_T|, \] which tends to \(+\infty\). The functional is continuous and coercive, so it attains its minimum at some \(\hat{\varphi}_T\). (We do not claim uniqueness: the square of a norm need not be strictly convex.)

3. The optimality condition and the bang-bang control

Two facts give the analogue of the Euler–Lagrange equation of the HUM functional.

(i) The minimizer is not zero when \(d\ne0\), that is, when the free motion does not reach \(x^1\) by itself. Indeed \(J_{bb}(0)=0\), while for small \(s>0\) we have \(J_{bb}(s\,d)=\tfrac12s^2N(d)^2-s|d|^2<0\).

(ii) The observation of a nonzero adjoint has only finitely many zeros. Since \(m=1\), \(B^*\hat{\varphi}(t)=B^*e^{A^*(T-t)}\hat{\varphi}_T\) is a scalar analytic function of \(t\), not identically zero by unique continuation (the Kalman condition, with \(\hat{\varphi}_T\ne0\) by (i)). So it vanishes only at finitely many points of \([0,T]\), and \(\operatorname{sgn}(B^*\hat{\varphi}(t))\) is well defined except at those points.

With (ii), the function \(N\) is differentiable at \(\hat{\varphi}_T\), with \(\frac{d}{dh}N(\hat{\varphi}_T+h\psi_T)\big|_{h=0}=\int_0^T\operatorname{sgn}(B^*\hat{\varphi})\,B^*\psi\,dt\); the justification is in §6. Setting the directional derivatives of \(J_{bb}\) to zero gives the optimality condition

\[ N(\hat{\varphi}_T)\int_0^T\operatorname{sgn}\big(B^*\hat{\varphi}\big)\,B^*\psi\,dt=\langle x^1,\psi_T\rangle-\langle x^0,\psi(0)\rangle\qquad\text{for every }\psi_T\in\mathbb R^n . \]

Compare with (C): this is exactly condition (C) for the control

\[ \boxed{\;u_\infty(t)=\lambda\,\operatorname{sgn}\big(B^*\hat{\varphi}(t)\big),\qquad\lambda=N(\hat{\varphi}_T)=\int_0^T|B^*\hat{\varphi}|\,dt .\;} \]

By condition (C), \(u_\infty\) steers \(x^0\) to \(x^1\).

Structure. The control takes only the two values \(\pm\lambda\): it is bang-bang. It switches finitely many times, at the sign-changing zeros of \(B^*\hat{\varphi}\). Analyticity gives finitely many zeros of an observation that is not identically zero; a zero at which the sign does not change (a tangential zero) is not a switch. As for the minimal-energy control, the control is read off the observation of the optimal adjoint, but now only through its sign.

The minimum value. Taking \(\psi_T=\hat{\varphi}_T\) in the optimality condition gives \(\lambda^2=\langle x^1,\hat{\varphi}_T\rangle-\langle x^0,\hat{\varphi}(0)\rangle\), hence \[ \min J_{bb}=\tfrac12\lambda^2-\lambda^2=-\tfrac12\lambda^2=-\tfrac12\|u_\infty\|_{L^\infty}^2 , \] the exact analogue of \(\min J=-\tfrac12\|u_2\|_{L^2}^2\) for the minimal-energy control.

4. Why the bang-bang control has minimal amplitude

Proposition 1 (\(L^\infty\)-minimality). Assumptions: \(m=1\), the Kalman condition holds, \(\hat{\varphi}_T\) minimizes \(J_{bb}\), and \(u\) is any control in \(L^\infty(0,T)\) steering \(x^0\) to \(x^1\).

Conclusion: \(\|u_\infty\|_{L^\infty}=\lambda\le\|u\|_{L^\infty}\).

Interpretation: no control reaching the target can have smaller amplitude than the bang-bang control.

Proof. Since \(u\) is a control, it satisfies (C). Take \(\varphi_T=\hat{\varphi}_T\) there. The right-hand side equals \(\lambda^2\), by the computation of the minimum value above, so \[ \lambda^2=\int_0^T u\,B^*\hat{\varphi}\,dt\;\le\;\|u\|_{L^\infty}\int_0^T|B^*\hat{\varphi}|\,dt=\|u\|_{L^\infty}\,\lambda . \] Dividing by \(\lambda>0\) gives \(\lambda\le\|u\|_{L^\infty}\). \(\square\)

Why \(L^1\) produces \(L^\infty\). The proof is Hölder’s inequality \(\int fg\le\|f\|_{L^\infty}\|g\|_{L^1}\): the norm on the observation and the norm on the control are dual to each other. In the HUM functional the observation is measured in \(L^2\), which is its own dual, and the control is \(L^2\)-minimal. Here the observation is measured in \(L^1\), and the control is \(L^\infty\)-minimal.

Amplitude constraints. If the actuator is limited to \(|u(t)|\le U\), the target can be reached in time \(T\) if and only if \(\lambda\le U\): the bang-bang control is then admissible, and no control with smaller amplitude exists. The relation between the bound \(U\) and the shortest possible time is the classical time-optimal problem; its systematic tool is Pontryagin’s maximum principle. Exercises 3 and 5 explore the question.

Code and plot. Minimize \(J_{bb}\) for the task of stopping the harmonic oscillator \(x_1''+x_1=u\) from \(x^0=(1,0)\) at \(T=5\), locate the switching times, and compare the bang-bang control with the minimal-energy control. Will \(\lambda\) be larger or smaller than \(\max_t|u_2(t)|\)?

A = torch.tensor([[0.0, 1.0], [-1.0, 0.0]])            # the harmonic oscillator, one actuator (the force)
B = torch.tensor([[0.0], [1.0]])
T = 5.0
x0 = torch.tensor([1.0, 0.0])                          # displaced, at rest
x1 = torch.tensor([0.0, 0.0])                          # at rest at the origin
ts = torch.linspace(0, T, 4001)
Es = torch.stack([torch.matrix_exp(A.T * (T - t)) for t in ts])    # e^{A^T (T-t)} on the grid
EAT = torch.matrix_exp(A * T)
d = x1 - EAT @ x0

def J_bb(phi_T):
    g = ((Es @ phi_T) @ B).squeeze(-1)                 # the observation B* phi(t)
    return 0.5 * torch.trapezoid(g.abs(), ts) ** 2 - d @ phi_T

obs_at = lambda t, phi_T: float(B.T @ torch.matrix_exp(A.T * (T - t)) @ phi_T)

def sign_changes(values, grid, f, phi_T):
    """Zeros of the scalar function f(t, phi_T), located by bisection from grid sign changes."""
    zeros = []
    for a, b in zip(grid[:-1], grid[1:]):
        if f(a, phi_T) * f(b, phi_T) < 0:
            a, b = float(a), float(b)
            for _ in range(60):
                m = (a + b) / 2
                a, b = (m, b) if f(a, phi_T) * f(m, phi_T) > 0 else (a, m)
            zeros.append((a + b) / 2)
    return np.array(zeros)

# Minimize J_bb (L-BFGS with autograd; |.| is handled by its a.e. derivative, the sign)
phi_bb = torch.tensor([0.1, -0.1], requires_grad=True)
opt = torch.optim.LBFGS([phi_bb], max_iter=200, tolerance_grad=1e-13, tolerance_change=1e-16,
                        line_search_fn="strong_wolfe")
opt.step(lambda: (opt.zero_grad(), loss := J_bb(phi_bb), loss.backward(), loss)[1])
residual = torch.autograd.grad(J_bb(phi_bb), phi_bb)[0].norm()
phi_bb = phi_bb.detach()

g_bb = ((Es @ phi_bb) @ B).squeeze(-1)
lam = float(torch.trapezoid(g_bb.abs(), ts))
switches = sign_changes(g_bb, ts, obs_at, phi_bb)
breaks = np.concatenate([[0.0], switches, [T]])
signs = np.array([np.sign(obs_at((a + b) / 2, phi_bb)) for a, b in zip(breaks[:-1], breaks[1:])])

# Propagate the piecewise-constant control exactly, piece by piece
x_end = x0
for a, b, s in zip(breaks[:-1], breaks[1:], signs):
    taus = torch.linspace(0, b - a, 201)
    Eint = torch.trapezoid(torch.stack([torch.matrix_exp(A * (b - a - r)) for r in taus]), taus, dim=0)
    x_end = torch.matrix_exp(A * (b - a)) @ x_end + lam * s * (Eint @ B).squeeze(-1)

# The minimal-energy control (the Gramian formula), for comparison
u_2 = ((Es @ torch.linalg.solve(gramian(A, B, T), d)) @ B).squeeze(-1)

print(f"|grad J_bb at the minimizer|         = {float(residual):.1e}")
print(f"bang-bang amplitude lambda           = {lam:.6f}")
print(f"peak of the minimal-energy control   = {float(u_2.abs().max()):.6f}")
print(f"switching times                      = {switches.round(5)}   (gap: {np.diff(switches).round(5)})")
print(f"terminal error |x(T) - x1|           = {float((x_end - x1).norm()):.1e}")
print(f"min J_bb = {float(J_bb(phi_bb)):.8f}   vs   -lambda^2/2 = {-0.5 * lam ** 2:.8f}")
|grad J_bb at the minimizer|         = 3.0e-04
bang-bang amplitude lambda           = 0.315761
peak of the minimal-energy control   = 0.400039
switching times                      = [0.24216 3.38375]   (gap: [3.14159])
terminal error |x(T) - x1|           = 8.3e-05
min J_bb = -0.04985039   vs   -lambda^2/2 = -0.04985246
u_inf = lambda s: lam * torch.sign(B.T @ torch.matrix_exp(A.T * (T - s)) @ phi_bb)
x_bb = odeint(lti(A, B, u_inf), x0, ts)
c_G = torch.linalg.solve(gramian(A, B, T), d)
x_2 = odeint(lti(A, B, lambda s: B.T @ torch.matrix_exp(A.T * (T - s)) @ c_G), x0, ts)

fig, (ax1, ax2) = P.panels(2, size=(4.4, 3.5))
ax1.plot(ts, u_2, color=P.GREY, label=r"minimal energy $u_2$")
ax1.step(ts, lam * torch.sign(g_bb), where="post", color=P.ORANGE, label=r"bang-bang $u_\infty$")
for s in switches:
    ax1.axvline(s, color=P.INK, lw=0.8, ls=":")
ax1.axhline(lam, color=P.ORANGE, lw=0.8, ls="--")
ax1.axhline(-lam, color=P.ORANGE, lw=0.8, ls="--")
P.label(ax1, "$t$", "control", zero="h", title="two controls, same task",
        legend={"loc": "lower left"})
P.phase(ax2, [x_2, x_bb], labels=["with $u_2$", r"with $u_\infty$"], colors=[P.GREY, P.BLUE],
        start=x0, target=x1, equal=True,
        xlabel="position $x_1$", ylabel="velocity $x_2$", title="trajectories")
plt.show()

The bang-bang control never exceeds \(\lambda\approx0.316\), below the peak \(\approx0.400\) of the minimal-energy control: Proposition 1 at work. It switches twice, at the two zeros of the observation \(B^*\hat{\varphi}\) inside \((0,T)\), both sign-changing (zeros of a sinusoid are simple), spaced exactly \(\pi\) apart (Exercise 1). The price is energy: \(u_\infty\) is “on” all the time, so its \(L^2\) norm exceeds that of \(u_2\), as the \(L^2\)-minimality of \(u_2\) guarantees. Each control is optimal for its own norm.

5. Two actuators: switching controls

Two different structures. Bang-bang (§§2–4) is structure in the amplitude: the control takes only the extreme values \(\pm\lambda\). Switching is structure in which actuator is active: at each instant at most one actuator acts, with values that need not be extreme. Neither is a special case of the other; §6 shows how to combine them.

Now consider two scalar controls acting through vectors \(b_1,b_2\in\mathbb R^n\): \[ x'=Ax+u_1(t)\,b_1+u_2(t)\,b_2,\qquad x(0)=x^0 . \] In this section \(u_1,u_2\) denote the controls of the two actuators. (The \(L^2\)-minimal control \(u_2\) of §§2–4 does not appear here.) Without constraints, the system is controllable if and only if the Kalman condition holds for \(B=[b_1\ b_2]\). We look for switching controls:

\[ u_1(t)\,u_2(t)=0\qquad\text{for almost every }t\in(0,T): \]

only one actuator acts at a time. The classical functional \(\tfrac12\int(|b_1\cdot\varphi|^2+|b_2\cdot\varphi|^2)\) gives the minimal-energy pair \(u_i=b_i\cdot\hat{\varphi}\), and in general both are active simultaneously. Consider instead

\[ J_{sw}(\varphi_T)=\frac12\int_0^T\max\Big(|b_1\cdot\varphi(t)|^2,\ |b_2\cdot\varphi(t)|^2\Big)\,dt-\langle x^1,\varphi_T\rangle+\langle x^0,\varphi(0)\rangle . \tag{SW} \]

Theorem 2 (automatic switching). Assumptions: the pairs \((A,\,b_2-b_1)\) and \((A,\,b_2+b_1)\) satisfy the Kalman rank condition; \(T>0\); and \(x^1\ne e^{AT}x^0\) (otherwise \(u=0\) works and there is nothing to switch).

Conclusion: \(J_{sw}\) attains its minimum at some \(\tilde{\varphi}_T\), and the controls \[u_1(t)=\tilde{\varphi}(t)\cdot b_1\ \text{ where }|\tilde{\varphi}(t)\cdot b_1|>|\tilde{\varphi}(t)\cdot b_2|,\qquad u_2(t)=\tilde{\varphi}(t)\cdot b_2\ \text{ where }|\tilde{\varphi}(t)\cdot b_2|>|\tilde{\varphi}(t)\cdot b_1|,\] each set to zero elsewhere, steer \(x^0\) to \(x^1\), and they are of switching form.

Interpretation: the minimizer decides at each instant which actuator “sees” the adjoint more strongly, and uses only that one.

Why these rank conditions? A factorization. The actuators tie, \(|b_1\cdot\varphi|=|b_2\cdot\varphi|\), exactly when \[ |b_1\cdot\varphi|^2-|b_2\cdot\varphi|^2=\big((b_1-b_2)\cdot\varphi\big)\big((b_1+b_2)\cdot\varphi\big)=0 . \] So the tie set is the union of the zero sets of the two observations \((b_2-b_1)\cdot\varphi\) and \((b_2+b_1)\cdot\varphi\). By the rank conditions, each of them is a nonzero analytic function when \(\tilde{\varphi}_T\ne0\) (unique continuation for the pairs \((A,b_2\mp b_1)\)). Each therefore has only finitely many zeros: the switching set has measure zero, and the controls are genuinely of switching form.

The rank conditions on \((A,b_2\pm b_1)\) imply controllability with the pair \((b_1,b_2)\), but not conversely. For instance, if \(b_2=\pm b_1\), the actuators tie at every instant.

Existence and the control. Coercivity follows from \(|b_1\cdot\varphi|^2+|b_2\cdot\varphi|^2\le2\max(\cdot)\), which bounds \(J_{sw}\) below by a functional equivalent to the classical one. At the minimizer, the Euler–Lagrange equation reads \[ \int_{S_1}(\tilde{\varphi}\cdot b_1)(\psi\cdot b_1)\,dt+\int_{S_2}(\tilde{\varphi}\cdot b_2)(\psi\cdot b_2)\,dt=\langle x^1,\psi_T\rangle-\langle x^0,\psi(0)\rangle\quad\forall\psi_T, \] with \(S_i\) the set where actuator \(i\) dominates. This is condition (C) for \(u_i=(\tilde{\varphi}\cdot b_i)\mathbf 1_{S_i}\).

Code and plot. The harmonic oscillator with two actuators, \(b_1=(1,0)\) on the position and \(b_2=(0,1)\) on the velocity. Does the optimal control mix both actuators continuously, or select one at a time?

b1, b2 = torch.tensor([1.0, 0.0]), torch.tensor([0.0, 1.0])
B2 = torch.stack([b1, b2], dim=1)
col = lambda v: v.reshape(-1, 1)
print("Kalman ranks:  (A, b1):", int(torch.linalg.matrix_rank(kalman(A, col(b1)))),
      "  (A, b2):", int(torch.linalg.matrix_rank(kalman(A, col(b2)))),
      "  (A, b2-b1):", int(torch.linalg.matrix_rank(kalman(A, col(b2 - b1)))),
      "  (A, b2+b1):", int(torch.linalg.matrix_rank(kalman(A, col(b2 + b1)))))

def J_sw(phi_T):
    phi = Es @ phi_T
    return 0.5 * torch.trapezoid(torch.maximum((phi @ b1) ** 2, (phi @ b2) ** 2), ts) - d @ phi_T

phi_sw = torch.tensor([0.1, -0.1], requires_grad=True)
opt = torch.optim.LBFGS([phi_sw], max_iter=200, tolerance_grad=1e-13, tolerance_change=1e-16,
                        line_search_fn="strong_wolfe")
opt.step(lambda: (opt.zero_grad(), loss := J_sw(phi_sw), loss.backward(), loss)[1])
residual_sw = torch.autograd.grad(J_sw(phi_sw), phi_sw)[0].norm()
phi_sw = phi_sw.detach()

# The tie set: zeros of |b1.phi|^2 - |b2.phi|^2 = ((b1-b2).phi) ((b1+b2).phi)
tie_at = lambda t, p: (float((b1 - b2) @ torch.matrix_exp(A.T * (T - t)) @ p)
                       * float((b1 + b2) @ torch.matrix_exp(A.T * (T - t)) @ p))
phi_grid = Es @ phi_sw
ties = sign_changes((phi_grid @ b1) ** 2 - (phi_grid @ b2) ** 2, ts, tie_at, phi_sw)
sw_breaks = np.concatenate([[0.0], ties, [T]])
mids = torch.tensor((sw_breaks[:-1] + sw_breaks[1:]) / 2)
active = np.array([int(abs(torch.matrix_exp(A.T * (T - m)) @ phi_sw @ b2)
                       > abs(torch.matrix_exp(A.T * (T - m)) @ phi_sw @ b1)) for m in mids])

def u_switching(s):
    phi_s = torch.matrix_exp(A.T * (T - s)) @ phi_sw
    j = min(int(np.searchsorted(sw_breaks, float(s), side="right")) - 1, len(active) - 1)
    u = torch.zeros(2)
    u[active[j]] = phi_s @ (b1, b2)[active[j]]
    return u

x_sw = odeint(lti(A, B2, u_switching), x0, ts)
dominant = (phi_grid @ b1).abs() >= (phi_grid @ b2).abs()
U_sw = torch.stack([(phi_grid @ b1) * dominant, (phi_grid @ b2) * ~dominant], dim=1)
U_l2 = (Es @ torch.linalg.solve(gramian(A, B2, T), d)) @ B2    # the minimal-energy pair

print(f"\n|grad J_sw at the minimizer| = {float(residual_sw):.1e}")
print(f"switching times: {ties.round(5)}   active actuator on each piece: {active + 1}"
      f"   number of switches: {len(ties)}")
print(f"max_t |u1(t) u2(t)|  switching control: {float((U_sw[:, 0] * U_sw[:, 1]).abs().max()):.1e}"
      f"   minimal-energy pair: {float((U_l2[:, 0] * U_l2[:, 1]).abs().max()):.2f}")
print(f"terminal error |x(T) - x1| = {float((x_sw[-1] - x1).norm()):.1e}")
Kalman ranks:  (A, b1): 2   (A, b2): 2   (A, b2-b1): 2   (A, b2+b1): 2

|grad J_sw at the minimizer| = 1.9e-04
switching times: [0.775   2.3458  3.91659]   active actuator on each piece: [1 2 1 2]   number of switches: 3
max_t |u1(t) u2(t)|  switching control: 0.0e+00   minimal-energy pair: 0.02
terminal error |x(T) - x1| = 9.0e-05
fig, axes = P.panels(2, size=(4.4, 3.4))
P.curves(axes[0], ts, {"$u_1$": (U_l2[:, 0], P.BLUE), "$u_2$": (U_l2[:, 1], P.ORANGE)},
         xlabel="$t$", zero="h", title="minimal-energy pair: both act")
P.curves(axes[1], ts, {"$u_1$ (on position)": (U_sw[:, 0], P.BLUE),
                       "$u_2$ (on velocity)": (U_sw[:, 1], P.ORANGE)},
         xlabel="$t$", zero="h", title="switching control: one at a time")
for (a, b), i in zip(zip(sw_breaks[:-1], sw_breaks[1:]), active):
    axes[1].axvspan(a, b, color=(P.BLUE, P.ORANGE)[i], alpha=0.08)
for s in ties:
    axes[1].axvline(s, color=P.INK, lw=0.8, ls=":")
plt.show()

The minimizer of \(J_{sw}\) selects one actuator at a time, \(u_1u_2=0\), and switches three times; the shaded bands show the active actuator, the dotted lines the switching times, and the printed terminal error confirms that the target is reached. The pieces alternate between position and velocity actuation, following which component of the rotating adjoint is larger. Within each piece the control is a smooth sinusoid, not bang-bang: \(J_{sw}\) imposes structure on which actuator acts, not on the amplitude. The two laboratories together separate the three cases: minimal energy (no structure), bang-bang (amplitude), switching (actuator). Combining both requirements gives the switching bang-bang controls of §6.

6. Details: analyticity, differentiability and variants

Optional.

Differentiability of \(N\) and of \(J_{sw}\). For \(\varphi_T\) with \(B^*\varphi\) vanishing only on a null set, \(\frac1h\big(|B^*\varphi+hB^*\psi|-|B^*\varphi|\big)\to\operatorname{sgn}(B^*\varphi)B^*\psi\) almost everywhere as \(h\to0\). The quotients are bounded by \(|B^*\psi|\), so dominated convergence gives the derivative of §3. The same argument applies to \(\max(|b_1\cdot\varphi|^2,|b_2\cdot\varphi|^2)\) away from the tie set. In the laboratory the switching times are located exactly (sign changes followed by bisection), so the printed switch counts are those of the exact functional.

The analyticity argument. The tie set is the union of the zero sets of the scalar analytic functions \(\tilde{\varphi}\cdot(b_2-b_1)\) and \(\tilde{\varphi}\cdot(b_2+b_1)\) (§5). If either zero set had positive measure, that function would vanish identically, and the rank condition for \((A,b_2-b_1)\), respectively \((A,b_2+b_1)\), would force \(\tilde{\varphi}_T=0\). These two rank conditions are exactly the hypotheses of Theorem 2. Then \(J_{sw}(\varphi_T)\ge0=J_{sw}(0)\) for all \(\varphi_T\), which happens only in the trivial case \(x^1=e^{AT}x^0\).

Preassigned switching. Given a partition \(0=t_0<t_1<\dots<t_{2N}=T\), the functional \[J_\tau=\tfrac12\sum_j\int_{t_{2j}}^{t_{2j+1}}|b_1\cdot\varphi|^2+\tfrac12\sum_j\int_{t_{2j+1}}^{t_{2j+2}}|b_2\cdot\varphi|^2-\langle x^1,\varphi_T\rangle+\langle x^0,\varphi(0)\rangle\] is coercive under the same rank condition, by time-analyticity. It gives switching controls with switching times chosen in advance. \(J_{sw}\) instead chooses them automatically.

Switching bang-bang. Minimizing \(\tfrac12\big(\int_0^T\max(|b_1\cdot\varphi|,|b_2\cdot\varphi|)\big)^2-\langle x^1,\varphi_T\rangle+\langle x^0,\varphi(0)\rangle\) gives \(u_i=\lambda\,\operatorname{sgn}(\tilde{\varphi}\cdot b_i)\mathbf 1_{S_i}\), with \(\lambda=\int\max(|\tilde{\varphi}\cdot b_1|,|\tilde{\varphi}\cdot b_2|)\). These controls are bang-bang and switching, and they have minimal \(L^\infty(0,T;\mathbb R^2)\) norm. The switching controls of \(J_{sw}\) are minimal in \(L^2(0,T;\mathbb R^2)\), with \(\mathbb R^2\) carrying the \(\ell^1\) norm.

7. Switching beyond the actuators

Optional.

There are also systems in which the dynamics itself switches, \(x'=A(t)x+u_1b_1+u_2b_2\) with \(A(t)\in\{A_1,\dots,A_M\}\). Controllability and the design of the switching rule then interact with the switching of the state matrix, and the simple factorization of §5 is no longer available. Piecewise-constant controls and the number of switches reappear later in the course as a measure of complexity. In the classification results for neural ODEs, the controls are piecewise constant with \(O(N)\) switches for \(N\) data points.

8. Control ↔︎ ML: switches and layers

In the neural-ODE reading of residual networks, a control that is piecewise constant in time corresponds to a network whose parameters stay fixed within a block of layers, so that each time discontinuity corresponds to one change of layer. Counting switches, as in the two laboratories, will become a way of counting the depth needed for a task. This is an architectural precursor, not an identity: it holds for the neural-ODE model of a network, and the switching controls of §5 are not themselves networks.

Mathematical analogy. The duality between \(L^1\) on the observation and \(L^\infty\) on the control (§4) has a cousin in the \(\ell^1\)-sparse training of shallow networks. The structures are similar, not identical.

Key takeaways

  1. Structured controls answer practical limits: bounded amplitude, on/off actuators, one actuator at a time.
  2. Changing the first term of the dual functional changes the structure of the control; the adjoint and condition (C) stay the same.
  3. \(J_{bb}=\tfrac12\big(\int|B^*\varphi|\big)^2-\langle x^1,\varphi_T\rangle+\langle x^0,\varphi(0)\rangle\) gives \(u_\infty=\lambda\operatorname{sgn}(B^*\hat{\varphi})\), switching at the sign-changing zeros of the observation.
  4. \(\lambda=\|u_\infty\|_{L^\infty}\) is the smallest amplitude of any control, by Hölder’s inequality (\(L^1\) observation ↔︎ \(L^\infty\) control), and \(\min J_{bb}=-\tfrac12\lambda^2\).
  5. \(J_{sw}\), with a \(\max\) over two actuators, gives switching controls, \(u_1u_2=0\).
  6. The tie set is where \(\big((b_1-b_2)\cdot\varphi\big)\big((b_1+b_2)\cdot\varphi\big)=0\); the rank conditions on \((A,b_2\pm b_1)\) make it finite.

9. Exercises

★ conceptual · ★★ mathematical · ★★★ computational

  1. Deriving the bang-bang structure. ★★ (a) From the optimality condition of §3, explain why \(u_\infty\) takes only the values \(\pm\lambda\) and switches exactly at the sign-changing zeros of \(B^*\hat\varphi\). Which assumptions guarantee that there are only finitely many switches? (b) For the harmonic oscillator with one actuator, show that the observation of any adjoint solution has the form \(B^*\varphi(t)=\rho\sin(T-t+\theta)\) with \(\rho=|\varphi_T|\). Deduce that the bang-bang control switches at most \(\lceil T/\pi\rceil\) times on \((0,T)\), and that consecutive switching times are exactly \(\pi\) apart. Check against the lab.
  2. Amplitude or actuator? ★ (a) For each of the three functionals in the table of “Where are we?”, say whether the resulting control has structure in its amplitude, in the choice of actuator, or neither. (b) What structure do you expect from minimizing \(\tfrac12\big(\int_0^T\max(|b_1\cdot\varphi|,|b_2\cdot\varphi|)\,dt\big)^2-\langle x^1,\varphi_T\rangle+\langle x^0,\varphi(0)\rangle\)? (c) Why is the classical two-actuator functional (the sum of squares) unable to produce switching controls in general?
  3. Amplitude and time. ★★ Let \(\lambda(T)\) be the bang-bang amplitude for steering \(x^0\) to \(x^1=0\) in time \(T\). (a) Using Proposition 1, prove that \(\lambda(T')\le\lambda(T)\) for \(T'>T\). Hint: the origin is an equilibrium of the free system. (b) Deduce that for an actuator bound \(U\), the set of times in which the target can be reached with \(|u|\le U\) is an interval \([T^*(U),\infty)\), provided it is nonempty and closed.
  4. When switching fails. ★★ Take \(b_2=b_1\). (a) Which rank condition of Theorem 2 fails? (b) Show that \(J_{sw}\) reduces to the one-actuator HUM functional and that \(|b_1\cdot\varphi|=|b_2\cdot\varphi|\) at every time. (c) Is the system still controllable with the pair \((b_1,b_2)\)? Is the decomposition of a control into \(u_1\) and \(u_2\) unique?
  5. The amplitude–time trade-off. ★★★ Compute the bang-bang amplitude \(\lambda(T)\) for stopping the harmonic oscillator from \(x^0=(1,0)\), for \(T\in[1,15]\), by minimizing \(J_{bb}\) as in the lab. Plot \(\lambda(T)\), check numerically that it is non-increasing (Exercise 3), and estimate the minimal time \(T^*(U)\) for the actuator bound \(U=0.2\).
# TODO: student exercise (Exercise 5)
# For each T in a grid on [1, 15], minimize J_bb as in the lab (rebuild Es and d for each T)
# and record lambda(T). Then plot lambda(T) and find the smallest T with lambda(T) <= 0.2.

def bang_bang_amplitude(T_):
    ...  # your code here
    return None

Where are we going?

The controls built so far are open-loop: functions of time, computed in advance from the model. Notebook 05 turns to closed-loop control, where the control is computed from the current state. There, observability returns in a new role: it gives the decay rate of a stabilizing feedback.

References

  1. E. Zuazua, Switching control, Journal of the European Mathematical Society 13 (2011), 85–117.
  2. J.-M. Coron, Control and Nonlinearity, Mathematical Surveys and Monographs 136, AMS, 2007.
  3. L. S. Pontryagin, V. G. Boltyanskii, R. V. Gamkrelidze, E. F. Mishchenko, The Mathematical Theory of Optimal Processes, Interscience, 1962.
  4. E. D. Sontag, Mathematical Control Theory: Deterministic Finite Dimensional Systems, 2nd ed., Springer, 1998.