Part II · SSM Core Week 9 Published

Selective SSMs: Mamba-1, Mamba-2, and the SSD framework

Making the SSM parameters input-dependent — selectivity breaks linear time-invariance, collapses the convolution–recurrence duality, and leaves the associative scan as the only route; the structured state-space duality then re-reads the selective scan as a semiseparable matrix and, for scalar state, as masked linear attention.

On this page
  1. 9.1 Breaking time-invariance: input-dependent (Δ,B,C)(\stepsize, \inputmat, \outputmat)(Δ,B,C)
  2. 9.2 Selective SSMs as discretized linear time-varying systems
  3. 9.3 The selective scan: the §8.6 primitive, now the only route
  4. 9.4 The hardware-aware fused kernel
  5. 9.5 Mamba-2 and SSD: the semiseparable-matrix view
  6. 9.6 Duality with linear attention
  7. 9.7 What’s next
  8. 9.8 Exercises
  9. Exercise 9.1 (computation)
  10. Exercise 9.2 (code)
  11. Exercise 9.3 (computation)
  12. Exercise 9.4 (theory) — solution in §9.9
  13. Exercise 9.5 (theory) — solution in §9.9
  14. Exercise 9.6 (theory) — solution in §9.9
  15. 9.9 Full solutions to theory exercises
  16. Solution to Exercise 9.4
  17. Solution to Exercise 9.5
  18. Solution to Exercise 9.6
  19. 9.10 Companion code

Selective SSMs: Mamba-1, Mamba-2, and the SSD framework

9.1 Breaking time-invariance: input-dependent (Δ,B,C)(\stepsize, \inputmat, \outputmat)

Chapter 8 ended on a layer with three computational faces and one weakness it never named: an LTI SSM applies the same dynamics to every token. The discrete map hk+1=Aˉhk+Bˉuk\statevec_{k+1} = \discA\,\statevec_k + \discB\,u_k filters all inputs through one fixed kernel, so the layer cannot decide, based on content, what to keep and what to discard. On synthetic tasks that demand exactly that — selective copying, where only some tokens matter, or induction, where the model must latch onto a token seen once — a fixed kernel provably cannot route information by content Gu & Dao (2024) .

Mamba’s remedy is one structural change: make the parameters functions of the input. At step tt,

Δt=softplus ⁣(ω+sΔ(ut)),Bt=sB(ut),Ct=sC(ut),\stepsize_t = \mathrm{softplus}\!\big(\omega + s_\Delta(u_t)\big), \qquad \inputmat_t = s_B(u_t), \qquad \outputmat_t = s_C(u_t),

with sΔ,sB,sCs_\Delta, s_B, s_C linear projections and ω\omega a bias; only the diagonal state matrix A=elogA\statemat = -e^{\,\log \statemat} stays a fixed parameter (kept stable by the §8.5 sign-by-construction trick). Discretizing per step — Mamba uses the simplified form Aˉt=eΔtA\discA_t = e^{\stepsize_t \statemat}, Bˉt=ΔtBt\discB_t = \stepsize_t \inputmat_t — gives a recurrence whose transition Aˉt\discA_t now changes at every step:

ht=Aˉtht1+Bˉtut,yt=Ctht+Dut.\statevec_t = \discA_t \odot \statevec_{t-1} + \discB_t\, u_t, \qquad y_t = \outputmat_t \cdot \statevec_t + D\, u_t .

The cost of this freedom is the subject of the rest of the chapter, and it is exactly the structure Chapter 8 spent its length building. A single fixed Aˉ\discA is what let one kernel Ki=CAˉiBˉK_i = \outputmat\,\discA^{\,i}\,\discB exist. Once Aˉt\discA_t varies, that kernel is gone.

Proposition 9.1.

(LTI collapse.) If the discrete transition is input-dependent — AˉtAˉt\discA_t \neq \discA_{t'} for some t,tt, t' — then the map uyDuu \mapsto y - D u is causal and linear, hence lower-triangular, but not Toeplitz: there is no single kernel KK with y=Ku+Duy = K * u + D u. The convolutional view of §8.3 exists if and only if the system is time-invariant.

The proof (Exercise 9.4, §9.9) is short: a causal linear map is a convolution exactly when its matrix has constant diagonals, and input-dependence makes even the main diagonal vary. The duality of §8.3 was a property of time-invariance all along; selectivity spends it.

9.2 Selective SSMs as discretized linear time-varying systems

The dynamical-systems name for what just happened is familiar. Chapter 8’s LTI SSM is the discretization of an autonomous linear system h˙=Ah+Bu\dot{\statevec} = \statemat\,\statevec + \inputmat\,u, whose coefficients do not depend on tt. A selective SSM is the discretization of a linear time-varying (LTV), or non-autonomous, system h˙(t)=A(t)h(t)+B(t)u(t)\dot{\statevec}(t) = \statemat(t)\,\statevec(t) + \inputmat(t)\,u(t). The whole apparatus of §8.3 — a single Aˉ\discA, its powers Aˉi\discA^{\,i}, one kernel — assumed autonomy. LTV systems replace the matrix power with a matrix product.

Definition 9.2.

(Discrete state-transition operator.) For the LTV recurrence ht=Aˉtht1+Bˉtut\statevec_t = \discA_t \statevec_{t-1} + \discB_t u_t with h0=0\statevec_0 = 0, the state is

hk=j=1kΦ(k,j)Bˉjuj,Φ(k,j)=AˉkAˉk1Aˉj+1    (Φ(k,k)=I),\statevec_k = \sum_{j=1}^{k} \Phi(k, j)\,\discB_j\, u_j, \qquad \Phi(k, j) = \discA_k \discA_{k-1} \cdots \discA_{j+1} \;\;(\Phi(k,k) = I),

where Φ(k,j)\Phi(k, j) is the state-transition operator carrying state from step jj to step kk. The input\tooutput map therefore has (k,j)(k, j) entry CkΦ(k,j)Bˉj\outputmat_k\,\Phi(k, j)\,\discB_j — a path-ordered product of transitions, not the power Aˉkj\discA^{\,k-j} of the LTI case.

This is why no kernel exists: the tap from source jj to target kk depends on the entire path of step sizes between them, Φ(k,j)\Phi(k,j), and not on the offset kjk - j. For a diagonal A\statemat the product is elementwise and the per-mode transition is a clean exponential of an accumulated step, Φ(k,j)n=exp ⁣(Ani=j+1kΔi)\Phi(k,j)_n = \exp\!\big(\statemat_n \sum_{i=j+1}^{k} \stepsize_i\big) — the companion’s segsum computes exactly this cumulative decay. Reading the dynamics through the transition operator is the right altitude: it is what survives into §9.5 as the entries of a structured matrix, and it is what makes the LTV system non-Toeplitz but still cheaply structured.

Selectivity is visible already in a single mode. Drive one stable mode with a content impulse and contrast a fixed-Δ\stepsize LTI system against a selective one whose gate Aˉt=eΔtA\discA_t = e^{\stepsize_t \statemat} opens (Δt\stepsize_t large, Aˉt0\discA_t \to 0: overwrite) on the content token and closes (Δt0\stepsize_t \to 0, Aˉt1\discA_t \to 1: hold) elsewhere. The selective system writes once and holds; the LTI system, forced to apply the same decay everywhere, forgets.

Two panels. Left: an input impulse at step 5 and a selective step-size that spikes there and is near zero elsewhere. Right: the selective state holds nearly flat after the impulse while the LTI state decays rapidly toward zero.
Selectivity as a content-dependent gate, single mode $\statemat = -1$. Left: the input impulse and the selective $\stepsize_t$ (large to write, near-zero to hold). Right: with the gate held, the selective state retains 84.4% of the written value 34 steps later; the fixed-$\stepsize$ LTI system, applying one decay everywhere, retains 0.004%. Produced by companions/ch09/jax/selective_vs_lti.py.

9.3 The selective scan: the §8.6 primitive, now the only route

The convolution is gone (Proposition, §9.1), so the O(LlogL)O(L\log L) FFT path of training-time S4 has no analogue here. What does survive is the parallel scan of §8.6 — and it survives because it never needed time-invariance in the first place. Recall the associative operator on (transition,input)(\text{transition}, \text{input}) pairs,

(a1,b1)(a2,b2)=(a2a1,  a2b1+b2),(a_1, b_1) \bullet (a_2, b_2) = (a_2 \odot a_1,\; a_2 \odot b_1 + b_2),

which composes “apply the first affine update, then the second.” Chapter 8 fed it the same Aˉ\discA at every step; nothing in the operator required that. Feeding it the time-varying pairs (Aˉt,  Bˉtut)(\discA_t,\; \discB_t u_t) scans the selective recurrence directly. This is the selective scan.

Proposition 9.3.

(Selective scan equivalence.) The operator \bullet is associative for arbitrary first components ata_t (not necessarily equal). Its inclusive prefix scan over (Aˉ1,Bˉ1u1),,(AˉL,BˉLuL)(\discA_1, \discB_1 u_1), \dots, (\discA_L, \discB_L u_L) has as its second components exactly the LTV states h1,,hL\statevec_1, \dots, \statevec_L, computed in parallel depth O(logL)O(\log L) Blelloch (1990) . Because no convolution exists (Proposition, §9.1), the O(LlogL)O(L\log L) FFT path of training-time S4 is gone; this scan recovers O(logL)O(\log L) depth at linear O(L)O(L) work and is the primitive the layer is computed with. (Section 9.5 derives a second parallel route — a quadratic matrix multiply — from the same structure.)

The proof (Exercise 9.5, §9.9) is the §8.6 argument with one observation added: the associativity computation never used a1=a2a_1 = a_2, so the LTI assumption was load-bearing only for the convolution, never for the scan. The companion pins the equivalence to machine precision — the selective associative scan and the sequential recurrence agree to a measured residual 1015\sim 10^{-15} across sequence lengths, which test_selective_scan_equals_sequential holds below 101210^{-12}.

Two panels. Left: the maximum difference between the selective associative scan and the sequential recurrence versus sequence length, flat near 1e-15. Right: log-log critical-path depth, the sequential curve rising as L and the selective-scan curve as log L.
The selective scan equals the sequential recurrence (left, residual $\sim 10^{-15}$, pinned below $10^{-12}$) while keeping the parallel critical-path depth $\lceil\log_2 L\rceil$ against the sequential $L$ (right). Unlike S4, there is no FFT-convolution fallback — the scan is the only parallel route. Produced by companions/ch09/jax/selective_scan_demo.py; pinned by test_selective_scan_equals_sequential.

9.4 The hardware-aware fused kernel

Making the scan the only route raises the stakes on computing it efficiently, and the obstacle is memory, not arithmetic. The selective scan’s state is htRN\statevec_t \in \R^N per channel: for a batch of BB sequences of length LL with DD channels and state size NN, materializing every intermediate state — which the naive backward pass needs — costs O(BLDN)O(B L D N), an N×N\times blow-up over the O(BLD)O(B L D) inputs and outputs. At B=8B = 8, L=2048L = 2048, D=1024D = 1024, N=16N = 16 that is 1.1 GB of fp32 state against 0.067 GB of output (figure below) — at Mamba’s working dimensions, the difference between fitting in memory and not.

Two panels. Left: log-log memory in gigabytes versus state dimension N, the materialized line B·L·D·N rising linearly while the fused line B·L·D stays flat. Right: the ratio materialized-over-fused versus N, a straight line equal to N.
Why the selective scan needs a fused kernel. For $B=8$, $L=2048$, $D=1024$, materializing all states costs $B L D N$ — at $N=16$ that is 1.1 GB of fp32 against 0.067 GB for the $B L D$ outputs, a $16\times$ ($=N$) gap. Mamba avoids it by keeping the expanded state in SRAM and recomputing it in the backward pass. Produced by companions/ch09/jax/selective_scan_demo.py.

Mamba’s selective-scan kernel resolves this with three hardware-aware moves Gu & Dao (2024) . It fuses discretization, scan, and output projection into a single GPU kernel, so the expanded (B,L,D,N)(B, L, D, N) state is formed and consumed in fast on-chip SRAM and never written to slow HBM. It recomputes that state in the backward pass instead of storing it — the activation-recomputation trade that pays compute to save memory, the same jax.checkpoint discipline the Mamba-1 reference implementation applies to its selective-scan body. And it exploits the fact, from §9.3, that there is no convolution to fall back on: the scan must be fast, so the engineering goes into the scan rather than into an alternative path. The companion does not implement a CUDA kernel — it makes the memory accounting concrete (the figure above), which is the part that explains why the kernel exists.

9.5 Mamba-2 and SSD: the semiseparable-matrix view

Section 9.2 wrote the input\tooutput map entry by entry. Collect those entries into a matrix and a second, matmul-friendly computation appears. Stacking y=Mu+Duy = M u + D u with

Mkj=CkΦ(k,j)Bˉj=nCk,nexp ⁣(Ani=j+1kΔi)ΔjBj,n(kj),M_{kj} = \outputmat_k\,\Phi(k, j)\,\discB_j = \sum_{n} \outputmat_{k,n}\, \exp\!\Big(\statemat_n \sum_{i=j+1}^{k} \stepsize_i\Big)\, \stepsize_j\, \inputmat_{j,n} \quad (k \ge j),

and Mkj=0M_{kj} = 0 for k<jk < j, gives a lower-triangular L×LL \times L matrix. This is the object Mamba-2 organizes the layer around, and it has exactly the structure that makes both computations cheap.

Theorem 9.4.

(Structured state-space duality.) For a diagonal state matrix ARN\statemat \in \R^N, the selective-SSM output map MM is NN-semiseparable: every submatrix lying strictly below the diagonal has rank at most NN. Consequently y=Muy = M u admits two computations of the same result — a linear one, the recurrent scan of §9.3 in O(LN)O(L N) work and O(N)O(N) memory, and a quadratic one, forming MM and multiplying, in O(L2N)O(L^2 N) work using dense matrix multiplies.

The rank bound is the duality’s engine (Exercise 9.6, §9.9): writing the accumulated decay as exp(An(ckcj))\exp(\statemat_n(c_k - c_j)) with ck=ikΔic_k = \sum_{i \le k}\stepsize_i factors each strictly-lower block into a sum of NN rank-one outer products. The two computations trade off by regime: the recurrent (scan) mode wins for long sequences and autoregressive inference; the quadratic (matmul) mode wins for short chunks, because dense matrix multiplies are what tensor cores do fastest. Mamba-2’s production algorithm chunks the sequence and uses the quadratic mode within chunks and the linear mode across them — both unlocked by the same structure. The companion confirms the two modes agree to a measured residual 1013\sim 10^{-13} (pinned below 101210^{-12} by test_recurrent_equals_matmul) and certifies the rank bound numerically.

Two panels. Left: a heatmap of the absolute SSD matrix M, nonzero on and below the diagonal, with magnitudes that vary along each diagonal. Right: the singular values of an off-diagonal block on a log scale, with a sharp cliff after index N.
The SSD matrix $M$ for a selective system with $N=4$ modes. Left: $M$ is lower-triangular and, because the system is time-varying, its diagonals are not constant (not Toeplitz, §9.1). Right: an off-diagonal block has exactly $N$ significant singular values then a cliff to machine zero — the $N$-semiseparable rank bound made visible. Produced by companions/ch09/jax/ssd_semiseparable.py; pinned by test_ssm_matrix_is_n_semiseparable.

9.6 Duality with linear attention

The semiseparable view pays its largest dividend when the state matrix is a scalar. Mamba-2 restricts A=aI\statemat = a\,I — one shared decay per head — which makes the accumulated decay a scalar, Lkj=exp ⁣(ai=j+1kΔi)L_{kj} = \exp\!\big(a \sum_{i=j+1}^{k}\stepsize_i\big), and factors the matrix entry into a decay times an inner product:

Mkj=Lkj(CkBj)ΔjM=L(CB)diag(Δ),M_{kj} = L_{kj}\,(\outputmat_k \cdot \inputmat_j)\,\stepsize_j \quad\Longleftrightarrow\quad M = L \circ (\outputmat\, \inputmat^{\top})\,\diag(\stepsize),

with \circ the Hadamard product. Read the right-hand side as attention: C\outputmat are queries, B\inputmat are keys, CB\outputmat\,\inputmat^\top is the score matrix, uu are values, and LL is a causal decay mask in place of softmax. Two things separate it from softmax attention. The mask Lkj=exp(ai=j+1kΔi)L_{kj} = \exp(a\sum_{i=j+1}^{k}\stepsize_i) is fixed by the accumulated step sizes between the two positions, not by a content–content interaction of kk and jj; and the scores enter linearly — there is no softmax nonlinearity — which is precisely what lets the same operator also run in the linear-cost recurrent mode (§9.5). It is linear attention, not softmax attention.

Theorem 9.5.

(Selective SSM as masked linear attention.) For scalar A=aI\statemat = a I, the selective SSM output equals y=(L(CB))diag(Δ)u+Duy = \big(L \circ (\outputmat\,\inputmat^{\top})\big)\,\diag(\stepsize)\,u + D u, a masked linear attention with decay mask Lkj=exp(ai=j+1kΔi)L_{kj} = \exp(a\sum_{i=j+1}^k \stepsize_i). The mask LL is 1-semiseparable (rank-one strictly-lower blocks). The recurrent scan and this masked matmul are the SSM and attention faces of one operator.

This is the formal sense in which “transformers are SSMs” Dao & Gu (2024) : the linear-attention layer of Katharopoulos et al. Katharopoulos et al. (2020) and the selective scan compute the same family of contractions, distinguished only by which mode — recurrent or quadratic — is run. The companion verifies the identity as a matrix equation, with the directly-built MM and the masked-attention form agreeing to 1014\sim 10^{-14} (pinned below 101210^{-12} by test_scalar_A_equals_masked_attention), and certifies that LL is 1-semiseparable. Chapter 11 enters this same duality from the attention side — linear attention and the delta-rule lineage are the “transformer” reading of the structure this section reached from the SSM side.

9.7 What’s next

The thread of this chapter is one structural change and its consequences. Making Δ,B,C\stepsize, \inputmat, \outputmat depend on the input turns the LTI SSM into a linear time-varying system (§9.2); time-variance breaks the convolution–recurrence duality, so no single kernel exists (§9.1) and the §8.6 associative scan — fed input-dependent transitions — becomes the parallel primitive the layer is computed with (§9.3), which is why Mamba needs a fused, recompute-in-backward kernel (§9.4). Re-reading that scan as a matrix exposes its NN-semiseparable structure and the recurrent/quadratic duality (§9.5), and for scalar state that matrix is masked linear attention (§9.6).

Chapter 10 keeps selectivity and changes the discretization: Mamba-3 moves to a complex state and replaces zero-order hold with the exponential-trapezoidal scheme of Chapter 4 when the selective dynamics turn stiff Lahoti et al. (2026) . That chapter is where the symplectic-integrator pilot finds its empirical anchor — the selective layer built here, run with a second-order geometric integrator. Chapter 11 takes the §9.6 duality the other way, developing linear attention and the delta-rule lineage as the attention-side reading of the same structured contractions. The selective scan and the semiseparable matrix are the two objects everything downstream reuses.

9.8 Exercises

Six problems mixing computation and theory. Short/numerical (9.1–9.3) have inline collapsible solutions; the theory exercises (9.4–9.6) have full worked solutions in §9.9.

Exercise 9.1 (computation)

Take one stable mode A=1\statemat = -1 with B=C=1\inputmat = \outputmat = 1, and two step sizes: a “write” step Δw=1.5\stepsize_{\text{w}} = 1.5 and a “hold” step Δh=0.01\stepsize_{\text{h}} = 0.01. (a) Compute the discrete transitions Aˉw=eΔwA\discA_{\text{w}} = e^{\stepsize_{\text{w}}\statemat} and Aˉh=eΔhA\discA_{\text{h}} = e^{\stepsize_{\text{h}}\statemat}. (b) A value written into the state then held for 2020 steps is multiplied by Aˉh20\discA_{\text{h}}^{20}; compute the retained fraction. (c) Contrast with an LTI system that must use Δ=Δw\stepsize = \stepsize_{\text{w}} for all 2020 steps. What does this say about selectivity?

Solution

(a) Aˉw=e1.5=0.2231\discA_{\text{w}} = e^{-1.5} = 0.2231 (gate nearly open: most of the old state is overwritten), Aˉh=e0.01=0.9900\discA_{\text{h}} = e^{-0.01} = 0.9900 (gate nearly closed: the state is held). (b) Holding for 20 steps retains Aˉh20=e0.2=0.8187\discA_{\text{h}}^{20} = e^{-0.2} = 0.8187, about 82%82\%. (c) The LTI system stuck at Δw\stepsize_{\text{w}} retains Aˉw20=e309×1014\discA_{\text{w}}^{20} = e^{-30} \approx 9\times10^{-14} — total forgetting. Selectivity is precisely the freedom to make Aˉt\discA_t near 11 on tokens worth holding and near 00 on tokens worth overwriting; a fixed Δ\stepsize cannot do both, which is the §9.2 figure in two numbers.

Exercise 9.2 (code)

Run companions/ch09/jax/selective_scan_demo.py and confirm the selective associative scan matches the sequential recurrence (the companion reports a residual 1015\sim 10^{-15}). Then explain why the S4 trick of computing the same output by an FFT convolution is unavailable here, referencing Proposition (§9.1).

Solution

The associative scan and the sequential recurrence compute the identical linear recurrence by different reduction orders, so for the same (Aˉt,Bˉtut)(\discA_t, \discB_t u_t) they agree to floating-point error (the companion measures 1015\sim 10^{-15}, pinned below 101210^{-12}). The FFT path is unavailable because it computes a convolution y=Kuy = K * u, which requires a single kernel KK. By Proposition (§9.1) no such kernel exists once Aˉt\discA_t is input-dependent: the map is not Toeplitz, so it is not a convolution, so there is nothing to transform. The scan, by contrast, only needs the per-step pairs and an associative operator, neither of which assumes time-invariance (§9.3).

Exercise 9.3 (computation)

Consider a scalar-state (N=1N = 1) selective system of length 44 with shared decay aa, step sizes Δ1,,Δ4\stepsize_1, \dots, \stepsize_4, scalar projections Bj,Ck\inputmat_j, \outputmat_k. Write the entry MkjM_{kj} of the SSD matrix for kjk \ge j, and argue that any strictly-lower block (e.g. rows {3,4}\{3,4\}, columns {1,2}\{1,2\}) has rank 11.

Solution

With N=1N=1, Mkj=Ckexp ⁣(ai=j+1kΔi)ΔjBjM_{kj} = \outputmat_k\,\exp\!\big(a\sum_{i=j+1}^k\stepsize_i\big)\,\stepsize_j\,\inputmat_j for kjk\ge j. Write cm=imΔic_m = \sum_{i\le m}\stepsize_i, so the accumulated decay is exp(a(ckcj))=eackeacj\exp(a(c_k - c_j)) = e^{a c_k}\,e^{-a c_j}. Then for kjk\ge j,

Mkj=(Ckeack)ϕ(k)  (eacjΔjBj)ψ(j)=ϕ(k)ψ(j).M_{kj} = \underbrace{\big(\outputmat_k\, e^{a c_k}\big)}_{\phi(k)}\;\underbrace{\big(e^{-a c_j}\,\stepsize_j\,\inputmat_j\big)}_{\psi(j)} = \phi(k)\,\psi(j).

The block on rows {3,4}\{3,4\}, columns {1,2}\{1,2\} is [ϕ(k)ψ(j)]k{3,4},j{1,2}=ϕ{3,4}ψ{1,2}\big[\phi(k)\psi(j)\big]_{k\in\{3,4\},\,j\in\{1,2\}} = \phi_{\{3,4\}}\,\psi_{\{1,2\}}^\top, an outer product of two vectors — rank 11. Every strictly-lower block factors the same way, so the matrix is 11-semiseparable.

Exercise 9.4 (theory) — solution in §9.9

Prove Proposition (§9.1): if the discrete transition Aˉt\discA_t is input-dependent, the causal linear map uyDuu \mapsto y - Du is not Toeplitz, so no convolution kernel KK with y=Ku+Duy = K*u + Du exists. (Hint: a causal linear map is a convolution iff its matrix has constant diagonals.)

Exercise 9.5 (theory) — solution in §9.9

Prove Proposition (§9.3): the operator (a1,b1)(a2,b2)=(a2a1,a2b1+b2)(a_1,b_1)\bullet(a_2,b_2) = (a_2 a_1,\, a_2 b_1 + b_2) is associative for arbitrary a1,a2a_1, a_2, and its inclusive prefix scan over (Aˉt,Bˉtut)(\discA_t, \discB_t u_t) reproduces the LTV states ht\statevec_t. Identify the single place the §8.6 argument used time-invariance and confirm the selective scan does not need it.

Exercise 9.6 (theory) — solution in §9.9

Prove Theorem (§9.5): for diagonal ARN\statemat \in \R^N, every strictly-lower-triangular block of the SSD matrix Mkj=nCk,nexp(Ani=j+1kΔi)ΔjBj,nM_{kj} = \sum_n \outputmat_{k,n}\exp(\statemat_n\sum_{i=j+1}^k\stepsize_i)\stepsize_j\inputmat_{j,n} has rank N\le N. Then specialize to scalar A=aI\statemat = aI to derive the masked-attention form M=L(CB)diag(Δ)M = L \circ (\outputmat\,\inputmat^\top)\diag(\stepsize) of Theorem (§9.6) and show LL is 11-semiseparable.

9.9 Full solutions to theory exercises

Solution to Exercise 9.4

A causal linear map uvu \mapsto v on sequences of length LL is represented by a lower-triangular matrix MM with vk=jkMkjujv_k = \sum_{j\le k} M_{kj} u_j. It is a convolution v=Kuv = K * u — i.e. vk=jkKkjujv_k = \sum_{j\le k} K_{k-j} u_j — if and only if MkjM_{kj} depends only on the offset kjk - j, which is exactly the statement that MM is Toeplitz (constant along each diagonal kj=constk - j = \text{const}).

For the selective system, the diagonal-A\statemat entry is

Mkj=nCk,nexp ⁣(An ⁣i=j+1kΔi)ΔjBj,n,kj.M_{kj} = \sum_n \outputmat_{k,n}\,\exp\!\Big(\statemat_n\!\sum_{i=j+1}^k \stepsize_i\Big)\,\stepsize_j\,\inputmat_{j,n}, \qquad k \ge j .

Consider the main diagonal k=jk = j (offset 00): the accumulated sum is empty, so Mkk=nCk,nΔkBk,n=Δk(CkBk)M_{kk} = \sum_n \outputmat_{k,n}\,\stepsize_k\,\inputmat_{k,n} = \stepsize_k\,(\outputmat_k \cdot \inputmat_k). Because Δk,Ck,Bk\stepsize_k, \outputmat_k, \inputmat_k are input-dependent, MkkM_{kk} varies with kk whenever the input does, so the main diagonal is not constant and MM is not Toeplitz. (More strongly, for k>jk > j the factor i=j+1kΔi\sum_{i=j+1}^k \stepsize_i is not a function of kjk - j once Δ\stepsize varies, so no off-diagonal is constant either.) A non-Toeplitz causal map is not a convolution, so no kernel KK exists; the time-invariant case, where AˉtAˉ\discA_t \equiv \discA makes Mkj=CAˉkjBˉM_{kj} = \outputmat\,\discA^{\,k-j}\discB depend only on kjk-j, is the sole case that is Toeplitz. \blacksquare

Solution to Exercise 9.5

Associativity. Write a pair (a,b)(a, b) as the affine map hah+bh \mapsto a h + b (with aa acting elementwise). Composition of affine maps is associative because function composition is; concretely, with \bullet as defined,

((a1,b1)(a2,b2))(a3,b3)=(a3a2a1,  a3a2b1+a3b2+b3),\big((a_1,b_1)\bullet(a_2,b_2)\big)\bullet(a_3,b_3) = (a_3 a_2 a_1,\; a_3 a_2 b_1 + a_3 b_2 + b_3), (a1,b1)((a2,b2)(a3,b3))=(a3a2a1,  a3a2b1+a3b2+b3),(a_1,b_1)\bullet\big((a_2,b_2)\bullet(a_3,b_3)\big) = (a_3 a_2 a_1,\; a_3 a_2 b_1 + a_3 b_2 + b_3),

and the two agree. Nowhere did this computation assume a1=a2=a3a_1 = a_2 = a_3 — that is the single place §8.6 silently used (and did not need) time-invariance. Prefix scan. Let et=(Aˉt,Bˉtut)e_t = (\discA_t, \discB_t u_t) and let sk=e1eks_k = e_1 \bullet \cdots \bullet e_k be the inclusive scan. By induction on kk the second component of sks_k equals hk\statevec_k: for k=1k=1 it is Bˉ1u1=h1\discB_1 u_1 = \statevec_1 (from h0=0\statevec_0 = 0); and sk=sk1eks_k = s_{k-1}\bullet e_k has second component Aˉk(2nd comp of sk1)+Bˉkuk=Aˉkhk1+Bˉkuk=hk\discA_k\cdot(\text{2nd comp of }s_{k-1}) + \discB_k u_k = \discA_k \statevec_{k-1} + \discB_k u_k = \statevec_k. Since \bullet is associative, all prefixes are computable by a balanced reduction tree in depth O(logL)O(\log L) Blelloch (1990) . The selective scan is thus the §8.6 scan verbatim, with time-varying Aˉt\discA_t in place of a constant Aˉ\discA — the operator’s associativity never cared. \blacksquare

Solution to Exercise 9.6

Semiseparability. Fix a strictly-lower block: rows kKk \in \mathcal{K} and columns jJj \in \mathcal{J} with minK>maxJ\min\mathcal{K} > \max\mathcal{J}, so k>jk > j throughout and the accumulated sum is nonempty. Write cm=i=1mΔic_m = \sum_{i=1}^m \stepsize_i, so i=j+1kΔi=ckcj\sum_{i=j+1}^k \stepsize_i = c_k - c_j and exp(An(ckcj))=eAnckeAncj\exp(\statemat_n(c_k - c_j)) = e^{\statemat_n c_k}\,e^{-\statemat_n c_j}. Then

Mkj=n=1N(Ck,neAnck)(eAncjΔjBj,n)=n=1Nϕn(k)ψn(j),M_{kj} = \sum_{n=1}^N \big(\outputmat_{k,n}\, e^{\statemat_n c_k}\big)\,\big(e^{-\statemat_n c_j}\,\stepsize_j\,\inputmat_{j,n}\big) = \sum_{n=1}^N \phi_n(k)\,\psi_n(j),

with ϕn(k)=Ck,neAnck\phi_n(k) = \outputmat_{k,n} e^{\statemat_n c_k} and ψn(j)=eAncjΔjBj,n\psi_n(j) = e^{-\statemat_n c_j}\stepsize_j\inputmat_{j,n}. As a matrix the block is n=1Nϕnψn=ΦΨ\sum_{n=1}^N \phi_n\,\psi_n^\top = \Phi\Psi^\top with ΦRK×N\Phi \in \R^{\abs{\mathcal{K}}\times N}, ΨRJ×N\Psi \in \R^{\abs{\mathcal{J}}\times N}, hence rank N\le N. Every strictly-lower block has this form, so MM is NN-semiseparable. (The factorization is exactly what the chunked algorithm exploits: ϕ\phi is read out from the per-chunk states, ψ\psi folded into them.)

Scalar specialization. Put A=aI\statemat = aI, i.e. An=a\statemat_n = a for all nn. The decay no longer depends on nn, so it pulls out of the sum:

Mkj=exp ⁣(a ⁣i=j+1kΔi)Δjn=1NCk,nBj,n=Lkj(CkBj)Δj,M_{kj} = \exp\!\Big(a\!\sum_{i=j+1}^k \stepsize_i\Big)\,\stepsize_j \sum_{n=1}^N \outputmat_{k,n}\inputmat_{j,n} = L_{kj}\,(\outputmat_k \cdot \inputmat_j)\,\stepsize_j,

with Lkj=exp(a(ckcj))L_{kj} = \exp(a(c_k - c_j)). In matrix form M=L(CB)diag(Δ)M = L \circ (\outputmat\,\inputmat^\top)\,\diag(\stepsize), the masked-attention form of Theorem (§9.6): CB\outputmat\,\inputmat^\top is the score matrix and LL the decay mask. Finally Lkj=eackeacjL_{kj} = e^{a c_k}e^{-a c_j} for kjk\ge j, so any strictly-lower block of LL is the outer product (eack)k(eacj)j(e^{a c_k})_{k}\,(e^{-a c_j})_{j}^\top — rank one. Thus LL is 11-semiseparable, and the full MM is NN-semiseparable with NN the state size (here the rank of the score matrix). \blacksquare

9.10 Companion code

Two language tracks for Chapter 9 — JAX (the reference, with the parallel selective scan and the semiseparable-matrix tools) and PyTorch (the nn.Module layers and the masked-attention dual). Julia is omitted, as in Chapter 8: the selective scan and the SSD matrix are the same algorithm in any language, and the JAX/PyTorch pair already carries the cross-framework lesson. The two tracks are pinned bit-for-bit against each other in float64.

JAX (companions/ch09/jax/):

  • selective_ssm.py — the SISO selective-SSM core: the selection mechanism, the per-step ZOH discretization, and the selective scan via jax.lax.associative_scan with its sequential oracle. The §9.3 equivalence lives here.
  • selective_vs_lti.py — emits selective-vs-lti.png (§9.2): the held-vs-forgotten single-mode contrast.
  • selective_scan_demo.py — emits selective-scan.png (§9.3) and memory-cost.png (§9.4): scan-vs-sequential agreement and depth, and the materialized-vs-fused memory accounting.
  • ssd_semiseparable.py — the SSD tools: segsum, the semiseparable matrix build_ssm_matrix, the rank certificate is_n_semiseparable, and the scalar-A\statemat masked_attention_form; emits semiseparable.png (§9.5).
  • tests/test_selective.py pins the selective scan-equivalence, stability by construction, and the not-Toeplitz collapse; test_ssd.py pins the recurrent-vs-matmul duality, NN-semiseparability, and the scalar-A\statemat masked-attention identity.

PyTorch (companions/ch09/torch/):

  • selective_ssm.py — the selective SSM as an nn.Module (A_log a learnable nn.Parameter, selection projections as nn.Linear, eager sequential scan), plus the functional core mirrored from JAX.
  • ssd_matmul.py — the scalar-A\statemat dual form as SSDAttention: masked linear attention with the decay mask in place of softmax.
  • tests/test_selective_torch.py — cross-framework parity: the torch selective scan and SSD matrices equal their JAX counterparts to within 10910^{-9}.

To run from the repo root:

# JAX (uses the uv .venv with jax, numpy, matplotlib)
PYTHONPATH=. python companions/ch09/jax/selective_vs_lti.py
PYTHONPATH=. python companions/ch09/jax/selective_scan_demo.py
PYTHONPATH=. python companions/ch09/jax/ssd_semiseparable.py

# PyTorch (needs the .venv [torch] extra)
PYTHONPATH=. python companions/ch09/torch/selective_ssm.py
PYTHONPATH=. python companions/ch09/torch/ssd_matmul.py

All figures emit to public/figures/ch09/.