QuantumCore

Lesson 54 · 110 min · advanced

Quantum Reservoir Computing

Loading progress…

Reservoir computing splits a learning machine for time series into a fixed dynamical system, the reservoir, and a linear readout, the only trained part. This lesson builds the quantum reservoir of Fujii and Nakajima (2017): four qubits under a transverse-field Ising Hamiltonian, an input injected at every step by replacing qubit 00, and V=5V=5 virtual nodes between inputs. We prove that the injection is a quantum channel, show that the reservoir forgets its initial state, derive the ridge readout from the normal equations, and measure the memory and NARMA2 performance of the lab reservoir.

Prerequisites: Hamiltonian-Evolution Encoding & Trotterisation, Noise, Decoherence, $T_1$ and $T_2$

Objectives and key results
  • State the echo-state and fading-memory properties precisely, derive fading memory from a uniform echo-state property, and explain why training only a linear readout turns learning into a convex least-squares problem.

  • Write the input injection ρ↦∣ψs⟩⟨ψs∣0⊗Tr0ρ\rho\mapsto\lvert\psi_s\rangle\langle\psi_s\rvert_0\otimes\mathrm{Tr}_0\rho in Kraus form, prove that it is completely positive and trace preserving, and factor it into a reset followed by RY(2arcsin⁡s)R_Y(2\arcsin\sqrt s).

  • Prove that one reservoir step never increases the trace distance between two states, and distinguish this theorem from the measured, parameter-dependent exponential forgetting of the lab reservoir.

  • Count the nV+1nV+1 features of a time-multiplexed reservoir, compute ⟨Zq⟩=∑x(−1)xqρxx\langle Z_q\rangle=\sum_x(-1)^{x_q}\rho_{xx}, and derive the ridge solution W=(X⊤X+λI)−1X⊤yW=(X^\top X+\lambda I)^{-1}X^\top y including positive definiteness and the Cholesky solve.

  • Evaluate a readout with the NMSE, the memory curve rd2r_d^2 and the memory capacity, and explain why the NARMA2 benchmark must be driven by u=s/2u=s/2.

theorem · Input injection is a quantum channel
Ts(ρ)=∣ψs⟩⟨ψs∣0⊗Tr0 ρ=∑b∈{0,1}Kb ρ Kb†,Kb=∣ψs⟩⟨b∣0⊗I,∑bKb†Kb=I\mathcal T_s(\rho)=\lvert\psi_s\rangle\langle\psi_s\rvert_0\otimes\mathrm{Tr}_0\,\rho=\sum_{b\in\{0,1\}}K_b\,\rho\,K_b^\dagger,\qquad K_b=\lvert\psi_s\rangle\langle b\rvert_0\otimes I,\qquad\sum_bK_b^\dagger K_b=I
theorem · A reservoir step does not increase the trace distance
∥Ts(ρ)−Ts(σ)∥1=∥Tr0(ρ−σ)∥1≤∥ρ−σ∥1\big\lVert\mathcal T_s(\rho)-\mathcal T_s(\sigma)\big\rVert_1=\big\lVert\mathrm{Tr}_0(\rho-\sigma)\big\rVert_1\le\lVert\rho-\sigma\rVert_1
formula · Time-multiplexed features
ϕk=(⟨Zq⟩ρk(v))v=1..V, q=0..n−1⊕(1)∈RnV+1,⟨Zq⟩ρ=∑x(−1)xqρxx\phi_k=\big(\langle Z_q\rangle_{\rho_k^{(v)}}\big)_{v=1..V,\ q=0..n-1}\oplus(1)\in\mathbb R^{nV+1},\qquad\langle Z_q\rangle_\rho=\sum_x(-1)^{x_q}\rho_{xx}
formula · Ridge readout
W=arg⁡min⁡W∥XW−y∥2+λ∥W∥2=(X⊤X+λI)−1X⊤yW=\arg\min_W\lVert XW-y\rVert^2+\lambda\lVert W\rVert^2=\big(X^\top X+\lambda I\big)^{-1}X^\top y
definition · NMSE and memory capacity
NMSE=∑k(y^k−yk)2∑k(yk−yˉ)2,MC=∑d≥1rd2\mathrm{NMSE}=\frac{\sum_k(\hat y_k-y_k)^2}{\sum_k(y_k-\bar y)^2},\qquad\mathrm{MC}=\sum_{d\ge1}r_d^2
formula · NARMA2
yk=0.4 yk−1+0.4 yk−1yk−2+0.6 uk−13+0.1,uk=12sky_k=0.4\,y_{k-1}+0.4\,y_{k-1}y_{k-2}+0.6\,u_{k-1}^3+0.1,\qquad u_k=\tfrac12s_k

Reservoir computing: fixed dynamics, trained readout#

Recurrent neural networks process a time series s1,s2,…s_1,s_2,\dots by feeding every input into an internal state that also remembers earlier inputs; training their recurrent weights requires backpropagation through time. Jaeger (2001, echo state networks) and Maass, Natschläger and Markram (2002, liquid state machines) observed that this training is often unnecessary: a random but fixed recurrent system already produces rich nonlinear functions of the recent inputs, and a linear combination of its state variables, trained by least squares, suffices for many tasks. Any physical system with suitable dynamics can serve as the reservoir, a quantum system included.

Definition

Reservoir computer

A reservoir is a state space X\mathcal X with a metric DD, an input set U\mathcal U and an update map F:X×U→XF:\mathcal X\times\mathcal U\to\mathcal X, so that an input sequence s1,s2,…s_1,s_2,\dots drives the states xk=F(xk−1,sk)x_k=F(x_{k-1},s_k) from an initial state x0x_0. A feature map ϕ:X→RN\phi:\mathcal X\to\mathbb R^N extracts NN real numbers from each state, and the readout predicts y^k=ϕ(xk)⊤w\hat y_k=\phi(x_k)^\top w with a weight vector w∈RNw\in\mathbb R^N. Only ww is trained. Here X\mathcal X is the set of four-qubit density matrices, DD the trace distance, U=[0,1]\mathcal U=[0,1], and ϕ\phi the measured ⟨Zq⟩\langle Z_q\rangle values plus a constant 11.

Definition

Echo-state property and fading memory

The reservoir has the (uniform) echo-state property if there is a sequence δk→0\delta_k\to0 such that for all initial states x0,x0′x_0,x_0' and all input sequences, the two trajectories driven by the same inputs satisfy D(xk,xk′)≤δkD(x_k,x_k')\le\delta_k. The state after many steps is then, up to δk\delta_k, a function of the inputs alone; it echoes the input history and has forgotten where it started. The reservoir has fading memory if, for every ε>0\varepsilon>0, there is a horizon KK such that two input histories that agree on their last KK inputs lead to states within ε\varepsilon of each other, however different their earlier inputs and initial states were.

Derivation

The uniform echo-state property implies fading memory

  1. Step 1:
    xk=Fsk∘Fsk−1∘⋯∘Fsk−K+1(xk−K),Fs(x)=F(x,s)x_k=F_{s_k}\circ F_{s_{k-1}}\circ\cdots\circ F_{s_{k-K+1}}\big(x_{k-K}\big),\qquad F_s(x)=F(x,s)
    Unroll the last KK updates. The state at time kk depends on the past only through the state xk−Kx_{k-K} reached KK steps earlier.
  2. Step 2:
    xk′=Fsk∘⋯∘Fsk−K+1(xk−K′)x'_k=F_{s_k}\circ\cdots\circ F_{s_{k-K+1}}\big(x'_{k-K}\big)
    A second history with possibly different early inputs and a different initial state, but the same last KK inputs sk−K+1,…,sks_{k-K+1},\dots,s_k, uses the same KK maps applied to another state xk−K′x'_{k-K}.
  3. Step 3:
    D(xk,xk′)≤sup⁡a,b∈XD(Fsk∘⋯∘Fsk−K+1(a), Fsk∘⋯∘Fsk−K+1(b))≤δKD(x_k,x'_k)\le\sup_{a,b\in\mathcal X}D\big(F_{s_k}\circ\cdots\circ F_{s_{k-K+1}}(a),\,F_{s_k}\circ\cdots\circ F_{s_{k-K+1}}(b)\big)\le\delta_K
    Both are KK-step trajectories of the same inputs from a=xk−Ka=x_{k-K} and b=xk−K′b=x'_{k-K}; the uniform echo-state property bounds their distance by δK\delta_K for every pair of initial states.
  4. Step 4:
    δK≤ε  for K≥K(ε)⇒D(xk,xk′)≤ε\delta_K\le\varepsilon\ \text{ for }K\ge K(\varepsilon)\quad\Rightarrow\quad D(x_k,x'_k)\le\varepsilon
    Since δK→0\delta_K\to0, choose the horizon K(ε)K(\varepsilon) with δK≤ε\delta_K\le\varepsilon. This is the fading-memory property, and the feature map turns it into a statement about the features if ϕ\phi is continuous.
  5. Step 5:
    ∣⟨Zq⟩ρ−⟨Zq⟩σ∣=∣Tr[Zq(ρ−σ)]∣≤∥Zq∥∞ ∥ρ−σ∥1=2 T(ρ,σ)\big\lvert\langle Z_q\rangle_{\rho}-\langle Z_q\rangle_{\sigma}\big\rvert=\big\lvert\mathrm{Tr}\big[Z_q(\rho-\sigma)\big]\big\rvert\le\lVert Z_q\rVert_\infty\,\lVert\rho-\sigma\rVert_1=2\,T(\rho,\sigma)
    For the quantum features: Hölder's inequality with ∥Zq∥∞=1\lVert Z_q\rVert_\infty=1 and the trace distance T=12∥ρ−σ∥1T=\tfrac12\lVert\rho-\sigma\rVert_1. Each feature is Lipschitz in the state, so states within ε\varepsilon give features within 2ε2\varepsilon.
Derivation

Why only the readout is trained

  1. Step 1:
    y^k=ϕk⊤w,ϕk=ϕ(xk)  independent of w\hat y_k=\phi_k^\top w,\qquad\phi_k=\phi(x_k)\ \text{ independent of }w
    The states, and therefore the feature vectors ϕk\phi_k, are computed once from the fixed dynamics; the prediction is linear in the trainable parameters.
  2. Step 2:
    L(w)=∑k(ϕk⊤w−yk)2+λ∥w∥2=∥Xw−y∥2+λ∥w∥2,Xkj=(ϕk)jL(w)=\sum_k\big(\phi_k^\top w-y_k\big)^2+\lambda\lVert w\rVert^2=\lVert Xw-y\rVert^2+\lambda\lVert w\rVert^2,\qquad X_{kj}=(\phi_k)_j
    The squared-error loss with an ℓ2\ell_2 penalty is a quadratic polynomial in ww; stacking the feature vectors as the rows of a matrix XX gives the compact form.
  3. Step 3:
    ∇2L=2(X⊤X+λI)≻0\nabla^2L=2\big(X^\top X+\lambda I\big)\succ0
    The Hessian is constant and positive definite for λ>0\lambda>0 (ridge section), so LL is strictly convex: no local minima, no learning rate, and a closed-form minimiser.
  4. Step 4:
    ∂xk∂θ=∑m≤k(∏j=m+1k∂F∂x∣xj−1,sj)∂F∂θ∣xm−1,sm\frac{\partial x_k}{\partial\theta}=\sum_{m\le k}\Big(\prod_{j=m+1}^{k}\frac{\partial F}{\partial x}\Big|_{x_{j-1},s_j}\Big)\frac{\partial F}{\partial\theta}\Big|_{x_{m-1},s_m}
    Training a parameter θ\theta of the dynamics instead would require this backpropagation-through-time sum, with products of up to kk Jacobians.
  5. Step 5:
    ∥∏j=m+1k∂F∂x∥≤∏j=m+1kηj → k−m→∞  0\Big\lVert\prod_{j=m+1}^{k}\frac{\partial F}{\partial x}\Big\rVert\le\prod_{j=m+1}^{k}\eta_j\ \xrightarrow{\ k-m\to\infty\ }\ 0
    For the quantum reservoir each step is a linear map on density matrices whose trace-norm gain ηj\eta_j on differences of states is at most 11 (next section). The contraction that produces fading memory also makes these gradient products vanish, and on hardware the state xkx_k is not even accessible.

The quantum reservoir: Ising dynamics and input injection#

Fujii and Nakajima (2017) proposed the natural dynamics of a small quantum many-body system as the reservoir: the state space of nn qubits has 4n−14^n-1 real parameters. The lab reservoir has n=4n=4 qubits, a fixed Ising Hamiltonian with all-to-all XXXX couplings and a transverse field, and an input written onto qubit 00 at every time step.

Derivation

The reservoir Hamiltonian of the lab

  1. Step 1:
    H=∑0≤i<j≤3Jij XiXj+h∑q=03ZqH=\sum_{0\le i<j\le3}J_{ij}\,X_iX_j+h\sum_{q=0}^{3}Z_q
    The blueprint model: an Ising interaction in the xx direction between every pair of qubits and a field hh in the zz direction, which does not commute with the couplings and therefore generates nontrivial dynamics.
  2. Step 2:
    (J01,J02,J03,J12,J13,J23)=(0.0695, 0.6305, −0.0920, −0.0749, −0.3440, 0.8774),h=0.5(J_{01},J_{02},J_{03},J_{12},J_{13},J_{23})=(0.0695,\ 0.6305,\ -0.0920,\ -0.0749,\ -0.3440,\ 0.8774),\qquad h=0.5
    The fixed couplings of the lab, drawn once at random and then frozen. Couplings of different sizes and signs avoid symmetries between qubits, which would make some features linearly dependent.
  3. Step 3:
    H=0.0695 XXII+0.6305 XIXI−0.0920 XIIX−0.0749 IXXI−0.3440 IXIX+0.8774 IIXX+0.5 (ZIII+IZII+IIZI+IIIZ)H=0.0695\,XXII+0.6305\,XIXI-0.0920\,XIIX-0.0749\,IXXI-0.3440\,IXIX+0.8774\,IIXX+0.5\,(ZIII+IZII+IIZI+IIIZ)
    The same operator as a sum of ten Pauli words, which is how the engine stores it before building the 16×1616\times16 matrix.
  4. Step 4:
    H⊤=H=H‾,spec⁡H⊂[−2.6358, 2.5890]H^\top=H=\overline H,\qquad\operatorname{spec}H\subset[-2.6358,\ 2.5890]
    XX and ZZ are real symmetric, hence so are their tensor products and HH. Its sixteen eigenvalues lie between −2.6358-2.6358 and 2.58902.5890 and are non-degenerate. The Bohr frequencies ωab=Ea−Eb\omega_{ab}=E_a-E_b that appear in ⟨Zq⟩(t)\langle Z_q\rangle(t) range from 0.05480.0548 to 5.22485.2248, i.e. periods 2π/ωab2\pi/\omega_{ab} from 1.2031.203 to 114.7114.7: during one input period τ=4\tau=4 the fastest modes complete more than three oscillations while the slowest barely move, so the features mix fast and slow time scales.
  5. Step 5:
    XiXj P=P XiXj,Zq P=P Zq,P=Z0Z1Z2Z3 ⇒ [H,P]=0X_iX_j\,P=P\,X_iX_j,\quad Z_q\,P=P\,Z_q,\qquad P=Z_0Z_1Z_2Z_3\ \Rightarrow\ [H,P]=0
    XX anticommutes with ZZ on the same qubit, so XiXjX_iX_j anticommutes with ZiZ_i and with ZjZ_j, and two sign changes cancel. The unitary dynamics alone conserves the parity PP; the injection, which resets qubit 00, breaks this conservation law and lets the input steer the state.
Theorem

Input injection is completely positive and trace preserving

For s∈[0,1]s\in[0,1] let ∣ψs⟩=1−s ∣0⟩+s ∣1⟩\lvert\psi_s\rangle=\sqrt{1-s}\,\lvert0\rangle+\sqrt s\,\lvert1\rangle. The discard-and-replace map on four qubits Ts(ρ)=∣ψs⟩⟨ψs∣0⊗Tr0 ρ\mathcal T_s(\rho)=\lvert\psi_s\rangle\langle\psi_s\rvert_0\otimes\mathrm{Tr}_0\,\rho has the Kraus operators Kb=∣ψs⟩⟨b∣0⊗I123K_b=\lvert\psi_s\rangle\langle b\rvert_0\otimes I_{123}, b∈{0,1}b\in\{0,1\}, with ∑bKb†Kb=I\sum_bK_b^\dagger K_b=I. Hence Ts\mathcal T_s is a quantum channel: it maps density matrices to density matrices, also when the four qubits are entangled with an outside reference system.

Proof (7 steps)
  1. Step 1:
    Tr0 ρ=∑b∈{0,1}(⟨b∣0⊗I) ρ (∣b⟩0⊗I)\mathrm{Tr}_0\,\rho=\sum_{b\in\{0,1\}}\big(\langle b\rvert_0\otimes I\big)\,\rho\,\big(\lvert b\rangle_0\otimes I\big)
    Definition of the partial trace over qubit 00 (partial-trace lesson): the sum of the two diagonal 8×88\times8 blocks of ρ\rho.
  2. Step 2:
    Kb ρ Kb†=(∣ψs⟩⟨b∣⊗I)ρ(∣b⟩⟨ψs∣⊗I)=∣ψs⟩⟨ψs∣⊗(⟨b∣⊗I)ρ(∣b⟩⊗I)K_b\,\rho\,K_b^\dagger=\big(\lvert\psi_s\rangle\langle b\rvert\otimes I\big)\rho\big(\lvert b\rangle\langle\psi_s\rvert\otimes I\big)=\lvert\psi_s\rangle\langle\psi_s\rvert\otimes\big(\langle b\rvert\otimes I\big)\rho\big(\lvert b\rangle\otimes I\big)
    Write ∣ψs⟩⟨b∣⊗I=(∣ψs⟩⊗I)(⟨b∣⊗I)\lvert\psi_s\rangle\langle b\rvert\otimes I=(\lvert\psi_s\rangle\otimes I)(\langle b\rvert\otimes I); the outer factors ∣ψs⟩\lvert\psi_s\rangle and ⟨ψs∣\langle\psi_s\rvert act on qubit 00 only and produce the projector ∣ψs⟩⟨ψs∣\lvert\psi_s\rangle\langle\psi_s\rvert in the tensor product.
  3. Step 3:
    ∑bKb ρ Kb†=∣ψs⟩⟨ψs∣⊗Tr0 ρ=Ts(ρ)\sum_bK_b\,\rho\,K_b^\dagger=\lvert\psi_s\rangle\langle\psi_s\rvert\otimes\mathrm{Tr}_0\,\rho=\mathcal T_s(\rho)
    Sum the previous line over bb and use the first line: the Kraus form reproduces the discard-and-replace map exactly.
  4. Step 4:
    ∑bKb†Kb=∑b∣b⟩⟨ψs∣ψs⟩⟨b∣⊗I=∑b∣b⟩⟨b∣⊗I=I,⟨ψs∣ψs⟩=(1−s)+s=1\sum_bK_b^\dagger K_b=\sum_b\lvert b\rangle\langle\psi_s\vert\psi_s\rangle\langle b\rvert\otimes I=\sum_b\lvert b\rangle\langle b\rvert\otimes I=I,\qquad\langle\psi_s\vert\psi_s\rangle=(1-s)+s=1
    Completeness of the Kraus operators, using that ∣ψs⟩\lvert\psi_s\rangle is normalised for every s∈[0,1]s\in[0,1].
  5. Step 5:
    Tr Ts(ρ)=∑bTr(KbρKb†)=Tr(∑bKb†Kb ρ)=Tr ρ\mathrm{Tr}\,\mathcal T_s(\rho)=\sum_b\mathrm{Tr}\big(K_b\rho K_b^\dagger\big)=\mathrm{Tr}\Big(\sum_bK_b^\dagger K_b\,\rho\Big)=\mathrm{Tr}\,\rho
    Trace preservation follows from cyclicity of the trace and completeness.
  6. Step 6:
    (Ts⊗idR)(Ω)=∑bMb Ω Mb†,Mb=Kb⊗IR;⟨v∣MbΩMb†∣v⟩=⟨Mb†v∣ Ω ∣Mb†v⟩≥0(\mathcal T_s\otimes\mathrm{id}_R)(\Omega)=\sum_bM_b\,\Omega\,M_b^\dagger,\quad M_b=K_b\otimes I_R;\qquad\langle v\rvert M_b\Omega M_b^\dagger\lvert v\rangle=\langle M_b^\dagger v\rvert\,\Omega\,\lvert M_b^\dagger v\rangle\ge0
    Complete positivity: extended to any reference system RR, the map keeps its Kraus form, and each term MΩM†M\Omega M^\dagger of a positive semidefinite Ω\Omega is positive semidefinite, hence so is the sum.
  7. Step 7:
    ∣ψs⟩⟨ψs∣=(1−ss(1−s)s(1−s)s)\lvert\psi_s\rangle\langle\psi_s\rvert=\begin{pmatrix}1-s&\sqrt{s(1-s)}\\\sqrt{s(1-s)}&s\end{pmatrix}
    The injected single-qubit state as a matrix: a pure state with populations 1−s1-s and ss and real coherences.

∎

Derivation

Injection = reset, then a rotation R_Y(2 arcsin √s)

  1. Step 1:
    R(ρ)=∑b(∣0⟩⟨b∣0⊗I)ρ(∣b⟩⟨0∣0⊗I)=∣0⟩⟨0∣0⊗Tr0 ρ\mathcal R(\rho)=\sum_{b}\big(\lvert0\rangle\langle b\rvert_0\otimes I\big)\rho\big(\lvert b\rangle\langle0\rvert_0\otimes I\big)=\lvert0\rangle\langle0\rvert_0\otimes\mathrm{Tr}_0\,\rho
    The non-selective reset of qubit 00 has the Kraus operators ∣0⟩⟨0∣\lvert0\rangle\langle0\rvert and ∣0⟩⟨1∣\lvert0\rangle\langle1\rvert; it is the case s=0s=0 of the theorem, since ∣ψ0⟩=∣0⟩\lvert\psi_0\rangle=\lvert0\rangle.
  2. Step 2:
    RY(θ)=(cos⁡θ2−sin⁡θ2sin⁡θ2cos⁡θ2),RY(θ)∣0⟩=cos⁡θ2∣0⟩+sin⁡θ2∣1⟩R_Y(\theta)=\begin{pmatrix}\cos\frac\theta2&-\sin\frac\theta2\\\sin\frac\theta2&\cos\frac\theta2\end{pmatrix},\qquad R_Y(\theta)\lvert0\rangle=\cos\tfrac\theta2\lvert0\rangle+\sin\tfrac\theta2\lvert1\rangle
    RY(θ)=e−iθY/2=cos⁡θ2I−isin⁡θ2YR_Y(\theta)=e^{-i\theta Y/2}=\cos\frac\theta2I-i\sin\frac\theta2Y with −iY=(0−110)-iY=\begin{pmatrix}0&-1\\1&0\end{pmatrix}; its first column is the image of ∣0⟩\lvert0\rangle.
  3. Step 3:
    θs=2arcsin⁡s:sin⁡θs2=s,cos⁡θs2=1−sin⁡2θs2=1−s\theta_s=2\arcsin\sqrt s:\qquad\sin\tfrac{\theta_s}2=\sqrt s,\qquad\cos\tfrac{\theta_s}2=\sqrt{1-\sin^2\tfrac{\theta_s}2}=\sqrt{1-s}
    arcsin⁡s∈[0,π2]\arcsin\sqrt s\in[0,\frac\pi2] for s∈[0,1]s\in[0,1], where the cosine is non-negative, so the positive square root is the right one. Hence RY(θs)∣0⟩=∣ψs⟩R_Y(\theta_s)\lvert0\rangle=\lvert\psi_s\rangle.
  4. Step 4:
    RY(θs)=(1−s−ss1−s)R_Y(\theta_s)=\begin{pmatrix}\sqrt{1-s}&-\sqrt s\\\sqrt s&\sqrt{1-s}\end{pmatrix}
    The rotation written with the input itself, exactly the matrix the engine applies after its reset.
  5. Step 5:
    (RY(θs)⊗I)(∣0⟩⟨0∣⊗σ)(RY(θs)⊗I)†=∣ψs⟩⟨ψs∣⊗σ  ⇒  Ts=AdRY(θs)∘R\big(R_Y(\theta_s)\otimes I\big)\big(\lvert0\rangle\langle0\rvert\otimes\sigma\big)\big(R_Y(\theta_s)\otimes I\big)^\dagger=\lvert\psi_s\rangle\langle\psi_s\rvert\otimes\sigma\ \ \Rightarrow\ \ \mathcal T_s=\mathrm{Ad}_{R_Y(\theta_s)}\circ\mathcal R
    Apply the rotation to the reset state with σ=Tr0ρ\sigma=\mathrm{Tr}_0\rho. The injection is a reset followed by an ordinary data-dependent rotation, as in angle encoding, except that the reset discards whatever qubit 00 carried.
  6. Step 6:
    ⟨Z0⟩=Tr[(Z⊗I) (∣ψs⟩⟨ψs∣⊗σ)]=⟨ψs∣Z∣ψs⟩ Tr σ=(1−s)−s=1−2s\langle Z_0\rangle=\mathrm{Tr}\big[(Z\otimes I)\,(\lvert\psi_s\rangle\langle\psi_s\rvert\otimes\sigma)\big]=\langle\psi_s\vert Z\vert\psi_s\rangle\,\mathrm{Tr}\,\sigma=(1-s)-s=1-2s
    Right after the injection, the magnetisation of qubit 00 encodes the input linearly; also ⟨X0⟩=2s(1−s)\langle X_0\rangle=2\sqrt{s(1-s)} and ⟨Y0⟩=0\langle Y_0\rangle=0, so the Bloch vector lies in the xzxz plane at polar angle θs\theta_s. For the first input s0=0.6011s_0=0.6011 of the lab, ⟨Z0⟩=−0.2022\langle Z_0\rangle=-0.2022.

Quick check

The input s=0.25s=0.25 is injected into qubit 00. What is ⟨Z0⟩\langle Z_0\rangle immediately after the injection, before any evolution?

tolerance ±0.000001

Forgetting the initial state. One reservoir step is the channel Es(ρ)=UVTs(ρ) U−V\mathcal E_s(\rho)=U^V\mathcal T_s(\rho)\,U^{-V}. The injection destroys everything stored in qubit 00, and the Hamiltonian keeps moving information from qubits 11 to 33 onto qubit 00, where the next injection destroys it. A step can never increase the distinguishability of two states; how fast it decreases depends on the dynamics.

Proposition

Reservoir steps do not increase the trace distance

For all four-qubit density matrices ρ,σ\rho,\sigma and every input ss, ∥Ts(ρ)−Ts(σ)∥1=∥Tr0(ρ−σ)∥1≤∥ρ−σ∥1,\lVert\mathcal T_s(\rho)-\mathcal T_s(\sigma)\rVert_1=\lVert\mathrm{Tr}_0(\rho-\sigma)\rVert_1\le\lVert\rho-\sigma\rVert_1, and the full step Es=AdUV∘Ts\mathcal E_s=\mathrm{Ad}_{U^V}\circ\mathcal T_s satisfies the same inequality. Consequently, for any two initial states driven by the same input sequence, Dk=12∥ρk−σk∥1D_k=\tfrac12\lVert\rho_k-\sigma_k\rVert_1 is non-increasing in kk. Equality holds in the inequality whenever ρ−σ=∣a⟩⟨a∣0⊗Δ′\rho-\sigma=\lvert a\rangle\langle a\rvert_0\otimes\Delta' for a pure state ∣a⟩\lvert a\rangle of qubit 00, for example when both states have the same pure qubit 00 and differ only on qubits 11 to 33.

Proof (7 steps)
  1. Step 1:
    Ts(ρ)−Ts(σ)=∣ψs⟩⟨ψs∣⊗Tr0(ρ−σ)\mathcal T_s(\rho)-\mathcal T_s(\sigma)=\lvert\psi_s\rangle\langle\psi_s\rvert\otimes\mathrm{Tr}_0(\rho-\sigma)
    The partial trace is linear, and both states receive the same injected factor ∣ψs⟩⟨ψs∣\lvert\psi_s\rangle\langle\psi_s\rvert.
  2. Step 2:
    ∥A⊗B∥1=∥A∥1 ∥B∥1,∥∣ψs⟩⟨ψs∣∥1=1\lVert A\otimes B\rVert_1=\lVert A\rVert_1\,\lVert B\rVert_1,\qquad\big\lVert\lvert\psi_s\rangle\langle\psi_s\rvert\big\rVert_1=1
    The singular values of A⊗BA\otimes B are the products of the singular values of AA and BB, so the sums factorise. A pure-state projector has the single nonzero singular value 11. This proves the equality in the statement.
  3. Step 3:
    ∥Δ∥1=max⁡O=O†, ∥O∥∞≤1Tr(OΔ)(Δ=Δ†)\lVert\Delta\rVert_1=\max_{O=O^\dagger,\ \lVert O\rVert_\infty\le1}\mathrm{Tr}(O\Delta)\quad(\Delta=\Delta^\dagger)
    Duality of the trace norm: with Δ=∑iλi∣ei⟩⟨ei∣\Delta=\sum_i\lambda_i\lvert e_i\rangle\langle e_i\rvert, Tr(OΔ)=∑iλi⟨ei∣O∣ei⟩≤∑i∣λi∣\mathrm{Tr}(O\Delta)=\sum_i\lambda_i\langle e_i\vert O\vert e_i\rangle\le\sum_i\lvert\lambda_i\rvert because ∣⟨ei∣O∣ei⟩∣≤1\lvert\langle e_i\vert O\vert e_i\rangle\rvert\le1, with equality for O=∑isgn(λi)∣ei⟩⟨ei∣O=\sum_i\mathrm{sgn}(\lambda_i)\lvert e_i\rangle\langle e_i\rvert.
  4. Step 4:
    Tr(O Tr0Δ)=Tr((I0⊗O) Δ)≤∥Δ∥1⇒∥Tr0Δ∥1≤∥Δ∥1\mathrm{Tr}\big(O\,\mathrm{Tr}_0\Delta\big)=\mathrm{Tr}\big((I_0\otimes O)\,\Delta\big)\le\lVert\Delta\rVert_1\quad\Rightarrow\quad\lVert\mathrm{Tr}_0\Delta\rVert_1\le\lVert\Delta\rVert_1
    The defining property of the partial trace, with ∥I0⊗O∥∞=∥O∥∞≤1\lVert I_0\otimes O\rVert_\infty=\lVert O\rVert_\infty\le1. Taking the maximum over OO on the left gives the contraction of the trace norm under the partial trace.
  5. Step 5:
    ∥WΔW†∥1=∥Δ∥1(W unitary)\big\lVert W\Delta W^\dagger\big\rVert_1=\lVert\Delta\rVert_1\quad(W\ \text{unitary})
    Unitary conjugation does not change the singular values. The evolution UVU^V between injections therefore preserves the trace distance exactly; it only moves information around.
  6. Step 6:
    Dk=12∥Esk(ρk−1)−Esk(σk−1)∥1≤12∥ρk−1−σk−1∥1=Dk−1D_k=\tfrac12\lVert\mathcal E_{s_k}(\rho_{k-1})-\mathcal E_{s_k}(\sigma_{k-1})\rVert_1\le\tfrac12\lVert\rho_{k-1}-\sigma_{k-1}\rVert_1=D_{k-1}
    Combine the last two steps for one full step; induction over kk gives a non-increasing sequence D0≥D1≥D2≥⋯D_0\ge D_1\ge D_2\ge\cdots.
  7. Step 7:
    ρ−σ=∣a⟩⟨a∣⊗Δ′ ⇒ Tr0(ρ−σ)=Δ′,∥ρ−σ∥1=∥Δ′∥1=∥Tr0(ρ−σ)∥1\rho-\sigma=\lvert a\rangle\langle a\rvert\otimes\Delta'\ \Rightarrow\ \mathrm{Tr}_0(\rho-\sigma)=\Delta',\quad\lVert\rho-\sigma\rVert_1=\lVert\Delta'\rVert_1=\lVert\mathrm{Tr}_0(\rho-\sigma)\rVert_1
    The equality case: a difference stored on qubits 11 to 33 passes an injection untouched. Information is only erased after the Hamiltonian has carried it onto qubit 00, so the speed of forgetting is a property of the dynamics.

∎

Measured forgetting of the lab reservoir. Start one copy in ∣0000⟩\lvert0000\rangle and another in ∣1111⟩\lvert1111\rangle and feed both the same inputs sk=s_k= mulberry32(42)(). After the first step D1=1D_1=1 exactly: the injection leaves ∣000⟩\lvert000\rangle and ∣111⟩\lvert111\rangle on qubits 11 to 33, which are orthogonal, so ∥Tr0(ρ0−σ0)∥1=2\lVert\mathrm{Tr}_0(\rho_0-\sigma_0)\rVert_1=2, and the unitary keeps them orthogonal. From then on the engine measures:

step kkDk=12∥ρk−σk∥1D_k=\frac12\lVert\rho_k-\sigma_k\rVert_1
111.0001.000
229.670×10−19.670\times10^{-1}
556.968×10−16.968\times10^{-1}
10103.250×10−13.250\times10^{-1}
20206.011×10−26.011\times10^{-2}
30308.711×10−38.711\times10^{-3}
40401.276×10−31.276\times10^{-3}
60604.931×10−54.931\times10^{-5}
1001004.998×10−84.998\times10^{-8}
2002003.000×10−143.000\times10^{-14}

The distance falls by a factor of about 0.840.84 per step between k=20k=20 and k=60k=60. Since ∣⟨Zq⟩ρ−⟨Zq⟩σ∣≤2Dk\lvert\langle Z_q\rangle_\rho-\langle Z_q\rangle_\sigma\rvert\le2D_k, the features after the lab's 200200-step washout depend on the initial state by less than 10−1310^{-13}.

The scope runs the lab reservoir on 12001200 inputs and plots the inputs, the twenty feature traces, the delay-11 readout against its target, and the test NMSE for delays 11 to 66. Move the sliders for hh, τ\tau and VV. With a short evolution the input written onto qubit 00 is overwritten by the next injection before the couplings have spread it to the other qubits: the engine measures a delay-11 test NMSE of 0.39170.3917 for τ=0.5\tau=0.5 and 0.99780.9978, no memory at all, for τ=0.2\tau=0.2. The lab's τ=4\tau=4 is not the optimum either; τ=2\tau=2 gives a memory capacity (defined below) of 5.5935.593 instead of 5.1275.127.

Virtual nodes: more features from the same qubits#

Four ⟨Zq⟩\langle Z_q\rangle per input are too few features. Fujii and Nakajima therefore read out the system at VV equally spaced times between two inputs; each intermediate time acts as an additional virtual node, giving nVnV features that sample the trajectory.

Derivation

Time multiplexing and the feature vector

  1. Step 1:
    U=e−iHτ/V,UV=e−iHτU=e^{-iH\tau/V},\qquad U^V=e^{-iH\tau}
    All factors are exponentials of the same operator, so they commute and their exponents add. The VV sub-steps reproduce the evolution over the full time τ\tau between inputs; here τ/V=0.8\tau/V=0.8.
  2. Step 2:
    ρk(0)=Tsk(ρk−1),ρk(v)=Uρk(v−1)U†=Uvρk(0)U−v(v=1,…,V),ρk=ρk(V)\rho_k^{(0)}=\mathcal T_{s_k}(\rho_{k-1}),\qquad\rho_k^{(v)}=U\rho_k^{(v-1)}U^\dagger=U^v\rho_k^{(0)}U^{-v}\quad(v=1,\dots,V),\qquad\rho_k=\rho_k^{(V)}
    Inject the input, then evolve in VV sub-steps. The state after the last sub-step is the reservoir state that the next injection acts on.
  3. Step 3:
    Zq∣x⟩=(−1)xq∣x⟩,xq=⌊x/2 n−1−q⌋ mod 2Z_q\lvert x\rangle=(-1)^{x_q}\lvert x\rangle,\qquad x_q=\big\lfloor x/2^{\,n-1-q}\big\rfloor\bmod2
    ZqZ_q is diagonal in the computational basis; with qubit 00 as the most significant bit, the bit of qubit qq is bit n−1−qn-1-q of the integer xx.
  4. Step 4:
    ⟨Zq⟩ρ=Tr(Zqρ)=∑x⟨x∣Zqρ∣x⟩=∑x(−1)xqρxx\langle Z_q\rangle_\rho=\mathrm{Tr}(Z_q\rho)=\sum_x\langle x\vert Z_q\rho\vert x\rangle=\sum_x(-1)^{x_q}\rho_{xx}
    Evaluate the trace in the computational basis and use ⟨x∣Zq=(−1)xq⟨x∣\langle x\rvert Z_q=(-1)^{x_q}\langle x\rvert. Only the diagonal, i.e. the measurement probabilities ρxx\rho_{xx}, enters.
  5. Step 5:
    ϕk=(⟨Z0⟩ρk(1),…,⟨Z3⟩ρk(1), …, ⟨Z0⟩ρk(V),…,⟨Z3⟩ρk(V), 1)∈RnV+1\phi_k=\Big(\langle Z_0\rangle_{\rho_k^{(1)}},\dots,\langle Z_3\rangle_{\rho_k^{(1)}},\ \dots,\ \langle Z_0\rangle_{\rho_k^{(V)}},\dots,\langle Z_3\rangle_{\rho_k^{(V)}},\ 1\Big)\in\mathbb R^{nV+1}
    The feature row of time step kk, ordered sub-step by sub-step, followed by a constant 11 that lets the readout add an offset (the bias column).
  6. Step 6:
    nV+1=4⋅5+1=21,X∈R600×21 (training rows k=200,…,799)nV+1=4\cdot5+1=21,\qquad X\in\mathbb R^{600\times21}\ \text{(training rows }k=200,\dots,799)
    The lab readout therefore has 2121 weights. The first 200200 rows are discarded as washout and the last 400400 rows are the test window.
  7. Step 7:
    2V⋅163=40 960 complex multiply-adds per input2V\cdot16^3=40\,960\ \text{complex multiply-adds per input}
    The cost of the exact simulation: each sub-step computes UρU†U\rho U^\dagger, two products of 16×1616\times16 matrices. On hardware each expectation value needs many shots and measurement disturbs the state, so each feature needs an ensemble of identical systems (the NMR setting of Fujii and Nakajima) or a re-run of the input history.

For the first input s0=0.6011037519s_0=0.6011037519, starting from ∣0000⟩\lvert0000\rangle: right after the injection ⟨Z0⟩=1−2s0=−0.2022\langle Z_0\rangle=1-2s_0=-0.2022, and after the first sub-step of duration 0.80.8 the four features are ⟨Z0⟩,…,⟨Z3⟩=−0.089304, 0.850546, 0.230656, 0.300436\langle Z_0\rangle,\dots,\langle Z_3\rangle=-0.089304,\ 0.850546,\ 0.230656,\ 0.300436. The couplings have already transported part of the input into qubits 22 and 33. The remaining sixteen entries of the row follow the state through the other four sub-steps.

Quick check

The same four-qubit reservoir is read out with V=10V=10 virtual nodes instead of 55, with ⟨Zq⟩\langle Z_q\rangle of every qubit after every sub-step and a bias column. How many weights does the linear readout have?

tolerance ±0.5

Training the readout: ridge regression#

Given the feature matrix XX (rows ϕk⊤\phi_k^\top, bias column included) and the targets yy, the readout minimises the squared error plus a ridge penalty, which keeps the problem well posed when features are nearly collinear.

Theorem

The ridge readout solves the normal equations

Let X∈RT×FX\in\mathbb R^{T\times F}, y∈RTy\in\mathbb R^T and λ>0\lambda>0. The function J(W)=∥XW−y∥2+λ∥W∥2J(W)=\lVert XW-y\rVert^2+\lambda\lVert W\rVert^2 has exactly one minimiser, W⋆=(X⊤X+λI)−1X⊤y,W^\star=\big(X^\top X+\lambda I\big)^{-1}X^\top y, and X⊤X+λIX^\top X+\lambda I is symmetric positive definite. For λ=0\lambda=0 the same formula holds if and only if XX has full column rank.

Proof (7 steps)
  1. Step 1:
    J(W)=(XW−y)⊤(XW−y)+λW⊤W=W⊤X⊤XW−2W⊤X⊤y+y⊤y+λW⊤WJ(W)=(XW-y)^\top(XW-y)+\lambda W^\top W=W^\top X^\top XW-2W^\top X^\top y+y^\top y+\lambda W^\top W
    Expand the squared norms; the two cross terms W⊤X⊤yW^\top X^\top y and y⊤XWy^\top XW are equal scalars.
  2. Step 2:
    ∇W(W⊤AW)=(A+A⊤)W=2AW (A=A⊤),∇W(W⊤c)=c\nabla_W\big(W^\top AW\big)=(A+A^\top)W=2AW\ (A=A^\top),\qquad\nabla_W\big(W^\top c\big)=c
    Gradients of a quadratic and a linear form, obtained by differentiating ∑ijWiAijWj\sum_{ij}W_iA_{ij}W_j and ∑iWici\sum_iW_ic_i with respect to WmW_m.
  3. Step 3:
    ∇WJ=2X⊤XW−2X⊤y+2λW=2X⊤(XW−y)+2λW\nabla_WJ=2X^\top XW-2X^\top y+2\lambda W=2X^\top(XW-y)+2\lambda W
    Apply the two rules with A=X⊤XA=X^\top X, which is symmetric, c=−2X⊤yc=-2X^\top y, and A=λIA=\lambda I for the penalty.
  4. Step 4:
    ∇WJ=0  ⟺  (X⊤X+λI)W=X⊤y\nabla_WJ=0\iff\big(X^\top X+\lambda I\big)W=X^\top y
    Setting the gradient to zero gives the normal equations, a linear system of size F×FF\times F, here 21×2121\times21, independent of the number of time steps TT.
  5. Step 5:
    v⊤(X⊤X+λI)v=∥Xv∥2+λ∥v∥2≥λ∥v∥2>0(v≠0)v^\top\big(X^\top X+\lambda I\big)v=\lVert Xv\rVert^2+\lambda\lVert v\rVert^2\ge\lambda\lVert v\rVert^2>0\quad(v\ne0)
    The matrix is symmetric because (X⊤X)⊤=X⊤X(X^\top X)^\top=X^\top X, and positive definite because the quadratic form is a sum of a non-negative term and a positive one. A positive definite matrix has only positive eigenvalues, so it is invertible and W⋆W^\star exists.
  6. Step 6:
    J(W⋆+v)=J(W⋆)+2v⊤[(X⊤X+λI)W⋆−X⊤y]+v⊤(X⊤X+λI)v=J(W⋆)+v⊤(X⊤X+λI)vJ(W^\star+v)=J(W^\star)+2v^\top\big[(X^\top X+\lambda I)W^\star-X^\top y\big]+v^\top\big(X^\top X+\lambda I\big)v=J(W^\star)+v^\top\big(X^\top X+\lambda I\big)v
    Exact second-order expansion of the quadratic JJ; the linear term vanishes by the normal equations. The remaining term is positive for v≠0v\ne0, so W⋆W^\star is the unique global minimiser and there are no other critical points.
  7. Step 7:
    λ=0:v⊤X⊤Xv=∥Xv∥2>0  ∀v≠0  ⟺  ker⁡X={0}\lambda=0:\quad v^\top X^\top Xv=\lVert Xv\rVert^2>0\ \ \forall v\ne0\iff\ker X=\{0\}
    Without regularisation the argument goes through exactly when no nonzero vv satisfies Xv=0Xv=0, i.e. when the columns of XX are linearly independent (ordinary least squares).

∎

Derivation

The bias inside X, and the Cholesky solve

  1. Step 1:
    ∑k(y^k−yk)=−λ WF−1\sum_k\big(\hat y_k-y_k\big)=-\lambda\,W_{F-1}
    Row F−1F-1 (the bias column, all ones) of the normal equations reads ∑kXk,F−1((XW)k−yk)+λWF−1=0\sum_kX_{k,F-1}\big((XW)_k-y_k\big)+\lambda W_{F-1}=0. Because the bias sits inside XX, the penalty shrinks it as well, as in the engine. Textbook ridge often leaves the intercept unpenalised, which would make the mean residual exactly zero.
  2. Step 2:
    1T∑k(y^k−yk)=−10−6⋅0.4913600=−8.19×10−10\frac1T\sum_k(\hat y_k-y_k)=-\frac{10^{-6}\cdot0.4913}{600}=-8.19\times10^{-10}
    For the lab's delay-11 readout (λ=10−6\lambda=10^{-6}, T=600T=600, bias weight 0.49130.4913) the effect is negligible: the mean residual on the training rows is below 10−910^{-9}.
  3. Step 3:
    A=X⊤X+λI=LL⊤,Aij=∑m≤jLimLjm(i≥j)A=X^\top X+\lambda I=LL^\top,\qquad A_{ij}=\sum_{m\le j}L_{im}L_{jm}\quad(i\ge j)
    Every symmetric positive definite matrix has a unique Cholesky factorisation with LL lower triangular and Ljj>0L_{jj}>0. Writing out the product shows which entries of LL enter each AijA_{ij}.
  4. Step 4:
    Ljj=Ajj−∑m<jLjm2,Lij=1Ljj(Aij−∑m<jLimLjm)(i>j)L_{jj}=\sqrt{A_{jj}-\sum_{m<j}L_{jm}^2},\qquad L_{ij}=\frac1{L_{jj}}\Big(A_{ij}-\sum_{m<j}L_{im}L_{jm}\Big)\quad(i>j)
    Solve the previous equation column by column for the diagonal entry and then for the entries below it. The radicand is positive: it equals det⁡A[0..j]/det⁡A[0..j−1]\det A_{[0..j]}/\det A_{[0..j-1]}, a ratio of leading principal minors, which are positive for a positive definite matrix.
  5. Step 5:
    Lz=X⊤y: zi=(X⊤y)i−∑m<iLimzmLii;L⊤W=z: Wi=zi−∑m>iLmiWmLiiLz=X^\top y:\ z_i=\frac{(X^\top y)_i-\sum_{m<i}L_{im}z_m}{L_{ii}};\qquad L^\top W=z:\ W_i=\frac{z_i-\sum_{m>i}L_{mi}W_m}{L_{ii}}
    AW=L(L⊤W)AW=L(L^\top W), so the system splits into a forward substitution from the top and a back substitution from the bottom.
  6. Step 6:
    TF2+13F3+2F2=600⋅441+3087+882≈2.7×105 operationsTF^2+\tfrac13F^3+2F^2=600\cdot441+3087+882\approx2.7\times10^5\ \text{operations}
    Forming X⊤XX^\top X dominates. The factorisation costs F3/3F^3/3 multiply-adds and the two triangular solves F2F^2 each; the lab's system is tiny.
  7. Step 7:
    spec⁡(X⊤X)⊂[0.002504, 614.7] ⇒ κ≈2.5×105\operatorname{spec}\big(X^\top X\big)\subset[0.002504,\ 614.7]\ \Rightarrow\ \kappa\approx2.5\times10^5
    The measured eigenvalues of the lab's 21×2121\times21 Gram matrix. The condition number is large but harmless in double precision; λ=10−6\lambda=10^{-6} shifts the smallest eigenvalue by less than 0.1%0.1\%, so it guards against singularity without biasing the fit.

Measuring the reservoir: NMSE, memory capacity and NARMA2#

Definition

Normalised mean squared error

On an evaluation window of TT steps with targets yky_k, mean yˉ\bar y and predictions y^k\hat y_k, NMSE=∑k(y^k−yk)2∑k(yk−yˉ)2=1T∑k(y^k−yk)2Var(y),\mathrm{NMSE}=\frac{\sum_k(\hat y_k-y_k)^2}{\sum_k(y_k-\bar y)^2}=\frac{\frac1T\sum_k(\hat y_k-y_k)^2}{\mathrm{Var}(y)}, with the population variance Var(y)=1T∑k(yk−yˉ)2\mathrm{Var}(y)=\frac1T\sum_k(y_k-\bar y)^2. The NMSE is 00 for a perfect prediction and does not change when the targets are rescaled. The lab and the engine evaluate it on the test window k=800,…,1199k=800,\dots,1199, which the readout never saw during training.

Derivation

Reference values of the NMSE

  1. Step 1:
    y^k≡c:∑k(c−yk)2=∑k(yk−yˉ)2+T(c−yˉ)2\hat y_k\equiv c:\qquad\sum_k(c-y_k)^2=\sum_k(y_k-\bar y)^2+T(c-\bar y)^2
    Insert c−yk=(c−yˉ)−(yk−yˉ)c-y_k=(c-\bar y)-(y_k-\bar y) and expand; the cross term 2(c−yˉ)∑k(yk−yˉ)2(c-\bar y)\sum_k(y_k-\bar y) vanishes by the definition of yˉ\bar y.
  2. Step 2:
    NMSEc=1+(c−yˉ)2Var(y),NMSEyˉ=1\mathrm{NMSE}_{c}=1+\frac{(c-\bar y)^2}{\mathrm{Var}(y)},\qquad\mathrm{NMSE}_{\bar y}=1
    Divide by ∑k(yk−yˉ)2=T Var(y)\sum_k(y_k-\bar y)^2=T\,\mathrm{Var}(y). Predicting the mean scores exactly 11; a useful readout must stay well below 11.
  3. Step 3:
    y^≡0: NMSE0=1+yˉ2Var(y)≈1+1/41/12=4(s∼U[0,1))\hat y\equiv0:\ \mathrm{NMSE}_0=1+\frac{\bar y^2}{\mathrm{Var}(y)}\approx1+\frac{1/4}{1/12}=4\quad(s\sim\mathcal U[0,1))
    The all-zero readout. For inputs uniform on [0,1)[0,1) the mean is 12\frac12 and the variance 112\frac1{12}. On the lab's test window yˉ=0.5131\bar y=0.5131 and Var(y)=0.08075\mathrm{Var}(y)=0.08075, which gives 4.2604.260.
  4. Step 4:
    y^k=sk−d′, yk=sk−d, d′≠d:1T∑k(sk−d′−sk−d)2≈2 Var(s) ⇒ NMSE≈2\hat y_k=s_{k-d'},\ y_k=s_{k-d},\ d'\ne d:\qquad\frac1T\sum_k(s_{k-d'}-s_{k-d})^2\approx2\,\mathrm{Var}(s)\ \Rightarrow\ \mathrm{NMSE}\approx2
    Recalling the wrong delay perfectly is worse than predicting the mean: for independent inputs of equal variance, E(a−b)2=Var a+Var b+(Ea−Eb)2=2 Var(s)\mathbb E(a-b)^2=\mathrm{Var}\,a+\mathrm{Var}\,b+(\mathbb Ea-\mathbb Eb)^2=2\,\mathrm{Var}(s).
  5. Step 5:
    λ=0: X⊤(y−y^)=0 ⇒ ∑k(yk−y^k)=0,∑k(y^k−yˉ)(yk−y^k)=0\lambda=0:\ X^\top(y-\hat y)=0\ \Rightarrow\ \sum_k(y_k-\hat y_k)=0,\quad\sum_k(\hat y_k-\bar y)(y_k-\hat y_k)=0
    On the training rows of an ordinary least-squares fit, the residual is orthogonal to every column of XX. The bias column gives a zero mean residual, and since y^−yˉ1=X(W−yˉeF−1)\hat y-\bar y\mathbf 1=X(W-\bar ye_{F-1}) lies in the column space, it is orthogonal to the residual.
  6. Step 6:
    ∑k(yk−yˉ)2=∑k(y^k−yˉ)2+∑k(yk−y^k)2 ⇒ r2(y^,y)=∑k(y^k−yˉ)2∑k(yk−yˉ)2=1−NMSE\sum_k(y_k-\bar y)^2=\sum_k(\hat y_k-\bar y)^2+\sum_k(y_k-\hat y_k)^2\ \Rightarrow\ r^2(\hat y,y)=\frac{\sum_k(\hat y_k-\bar y)^2}{\sum_k(y_k-\bar y)^2}=1-\mathrm{NMSE}
    Pythagoras for the orthogonal decomposition y−yˉ=(y^−yˉ)+(y−y^)y-\bar y=(\hat y-\bar y)+(y-\hat y). Moreover ∑k(y^k−yˉ)(yk−yˉ)=∑k(y^k−yˉ)2\sum_k(\hat y_k-\bar y)(y_k-\bar y)=\sum_k(\hat y_k-\bar y)^2, so the squared Pearson correlation equals the explained fraction. On the training rows r2=1−NMSEr^2=1-\mathrm{NMSE} exactly; on test rows only approximately.

Quick check

The inputs sks_k are independent and uniform on [0,1)[0,1), and the task is to recall yk=sk−1y_k=s_{k-1}. A readout returns w=0w=0, so it predicts y^k=0\hat y_k=0 at every step. Approximately what NMSE does the grader measure on a long test window?

tolerance ±0.3

Definition

Memory curve and short-term memory capacity

For the delay task yk=sk−dy_k=s_{k-d}, train a readout for each delay d=1,2,…d=1,2,\dots and let rd2r_d^2 be the squared Pearson correlation between its prediction and the target on the test window. The function d↦rd2d\mapsto r_d^2 is the memory curve, and MC=∑d≥1rd2\mathrm{MC}=\sum_{d\ge1}r_d^2 is the short-term memory capacity (Jaeger 2001). A perfect memory of the last mm inputs contributes mm. For independent inputs, Jaeger showed that the capacity summed over all delays cannot exceed the number NN of reservoir features (here N=20N=20).

The memory curve of the lab reservoir (engine values, inputs from mulberry32(42), 12001200 steps, washout 200200, training rows 200200 to 799799, test rows 800800 to 11991199, λ=10−6\lambda=10^{-6}):

delay ddtest NMSErd2r_d^2
110.010520.010520.98950.9895
220.035710.035710.96440.9644
330.050270.050270.95020.9502
440.11930.11930.88360.8836
550.20960.20960.79160.7916
660.45230.45230.54800.5480

Summed over d=1,…,6d=1,\dots,6 the memory capacity is MC=5.127\mathrm{MC}=5.127 out of a maximum of 66. The last three inputs are recalled almost perfectly; beyond d=4d=4 the memory fades quickly, as the measured contraction predicts. On the test window rd2≈1−NMSEr_d^2\approx1-\mathrm{NMSE}, the training-window identity derived above.

With the delay set to 33, the predicted trace still follows the target closely (test NMSE 0.05030.0503), and the bar chart shows the whole memory curve. Increase dd to 66 and the prediction visibly shrinks towards the mean: the readout cannot reconstruct what the dynamics has already forgotten.

Definition

NARMA2 benchmark

The second-order nonlinear autoregressive moving-average task (Atiya and Parlos 2000) asks the readout to emulate the recurrence yk=0.4 yk−1+0.4 yk−1yk−2+0.6 uk−13+0.1,y0=0, y−1=0,y_k=0.4\,y_{k-1}+0.4\,y_{k-1}y_{k-2}+0.6\,u_{k-1}^3+0.1,\qquad y_0=0,\ y_{-1}=0, driven by an input sequence uku_k. The target needs both memory (two past outputs, one past input) and nonlinearity (a product and a cube), so it tests more than the delay tasks. In this lesson, in the engine and in the scope, NARMA2 is driven by uk=sk/2u_k=s_k/2 (the constant NARMA2_INPUT_SCALE = 0.5 of the engine), while the reservoir itself still receives sks_k.

Derivation

Why the drive must be scaled: bounded for u ≤ 1/2, divergent for u on [0, 1)

  1. Step 1:
    uk∈[0,12],  yk−1,yk−2∈[0,b] ⇒ 0.1≤yk≤0.4b+0.4b2+0.6⋅18+0.1=0.4b+0.4b2+0.175u_k\in[0,\tfrac12],\ \ y_{k-1},y_{k-2}\in[0,b]\ \Rightarrow\ 0.1\le y_k\le0.4b+0.4b^2+0.6\cdot\tfrac18+0.1=0.4b+0.4b^2+0.175
    All terms are non-negative, which gives the lower bound 0.10.1; the upper bound uses u3≤18u^3\le\frac18.
  2. Step 2:
    0.4b+0.4b2+0.175≤b  ⟺  0.4b2−0.6b+0.175≤0  ⟺  b∈[0.6−0.080.8, 0.6+0.080.8]=[0.3964, 1.1036]0.4b+0.4b^2+0.175\le b\iff0.4b^2-0.6b+0.175\le0\iff b\in\Big[\tfrac{0.6-\sqrt{0.08}}{0.8},\ \tfrac{0.6+\sqrt{0.08}}{0.8}\Big]=[0.3964,\ 1.1036]
    Solve the quadratic inequality; its discriminant is 0.36−4⋅0.4⋅0.175=0.08>00.36-4\cdot0.4\cdot0.175=0.08>0.
  3. Step 3:
    b=0.4:0.16+0.064+0.175=0.399≤0.4 ⇒ yk∈[0.1, 0.4]  ∀k≥1b=0.4:\quad0.16+0.064+0.175=0.399\le0.4\ \Rightarrow\ y_k\in[0.1,\ 0.4]\ \ \forall k\ge1
    Induction starting from y0=y−1=0∈[0,0.4]y_0=y_{-1}=0\in[0,0.4]: the interval [0,0.4][0,0.4] is mapped into [0.1,0.399][0.1,0.399]. With the scaled drive the target is bounded; the engine measures yk∈[0.1163, 0.3343]y_k\in[0.1163,\ 0.3343] for the seed-4242 inputs.
  4. Step 4:
    u≡1:y=0.4y+0.4y2+0.7  ⟺  0.4y2−0.6y+0.7=0,0.36−4⋅0.4⋅0.7=−0.76<0u\equiv1:\quad y=0.4y+0.4y^2+0.7\iff0.4y^2-0.6y+0.7=0,\qquad0.36-4\cdot0.4\cdot0.7=-0.76<0
    For inputs near 11 there is no equilibrium at all: the fixed-point equation of the constant drive has no real solution. Since every term is non-negative, yk≥0.4 yk−1yk−2y_k\ge0.4\,y_{k-1}y_{k-2}; once two consecutive values exceed 2.52.5, each new value exceeds the previous one and ln⁡yk≳ln⁡yk−1+ln⁡yk−2+ln⁡0.4\ln y_k\gtrsim\ln y_{k-1}+\ln y_{k-2}+\ln0.4 grows like a Fibonacci sequence, a double-exponential blow-up.
  5. Step 5:
    uk=sk∈[0,1):∣yk∣>1 first at k=57,y75=2.322×104,y85=+∞u_k=s_k\in[0,1):\quad\lvert y_k\rvert>1\ \text{first at }k=57,\qquad y_{75}=2.322\times10^{4},\qquad y_{85}=+\infty
    Measured with the engine for the seed-4242 inputs: a run of large inputs pushes yy above 11 at step 5757, the value first exceeds 10310^3 at step 7575 (the 7676th value), and at step 8585 it overflows double precision. A target that diverges cannot be learned by any bounded readout, so the benchmark uses u=s/2u=s/2, the range [0,0.5][0,0.5] for which Atiya and Parlos defined it.

With the same features and ridge readout, the NARMA2 test NMSE is 0.10150.1015: ten times the delay-11 error, but far below the mean predictor's 11. Products such as yk−1yk−2y_{k-1}y_{k-2} are only partly present in twenty expectation values; larger reservoirs, correlators ⟨ZiZj⟩\langle Z_iZ_j\rangle and more virtual nodes are the usual levers (Mujal et al. 2021).

The TypeScript cell reproduces every number of this lesson with the engine: the inputs, the first feature row, the delay-11 to delay-33 test errors, the memory curve, the trace distances of the two copies and both NARMA2 runs.

TypeScriptrunnable
import { DensityMatrix, Statevector, expmIHermitian, hamiltonianToMatrix, matrix, traceDistance } from 'quantumcore';
import { L54_RESERVOIR, delayTask, injectInput, memoryCurve, narma2, narma2Target, nmse, predictReadout, reservoirFeatures, reservoirHamiltonian, reservoirInputs, ridgeRegression } from 'quantumcore/qml';

const spec = L54_RESERVOIR; // n = 4, the six J_ij, h = 0.5, tau = 4, V = 5, injection on qubit 0
const s = reservoirInputs(42, 1200); // s_k = mulberry32(42)()
const sci = (v: number) => v.toExponential(3).replace(/e([+-])(\d)$/, (_m, sign, digit) => 'e' + sign + '0' + digit); // 1.000e+00 as in Python
console.log('inputs s_0..s_2: ' + s.slice(0, 3).map((v) => v.toFixed(10)).join(', '));

// Exact density-matrix reservoir: one row per input = 4 x 5 values <Z_q> followed by the bias 1.
const X = reservoirFeatures(spec, s);
console.log('features: ' + X.length + ' rows x ' + X[0].length + ' columns, row 0 starts ' + X[0].slice(0, 4).map((v) => v.toFixed(6)).join(' '));

// Ridge readout trained on k = 200..799, tested on k = 800..1199.
for (const d of [1, 2, 3]) {
  const y = delayTask(s, d);
  const w = ridgeRegression(X.slice(200, 800), y.slice(200, 800), 1e-6);
  console.log('delay ' + d + ': test NMSE ' + nmse(predictReadout(X.slice(800), w), y.slice(800)).toPrecision(4) + ', ' + w.length + ' weights');
}
const r2 = memoryCurve(spec, s, 6, { washout: 200, trainEnd: 800, lambda: 1e-6, features: X });
console.log('memory curve r_d^2: ' + r2.map((v) => v.toFixed(4)).join(' ') + ' -> MC = ' + r2.reduce((a, b) => a + b, 0).toFixed(3));

// Fading memory: the same inputs drive |0000> and |1111>; one step = injection + V sub-steps U = exp(-i H tau / V).
const U = expmIHermitian(hamiltonianToMatrix(reservoirHamiltonian(spec), 4), spec.tau / spec.virtualNodes);
const Ud = matrix.adjoint(U);
function step(rho: DensityMatrix, input: number): DensityMatrix {
  injectInput(rho, spec.injectQubit, input);
  for (let v = 0; v < spec.virtualNodes; v++) rho = new DensityMatrix(4, matrix.mul(matrix.mul(U, rho.toMatrix()), Ud).data);
  return rho;
}
let a = DensityMatrix.fromStatevector(Statevector.fromBitstring('0000'));
let b = DensityMatrix.fromStatevector(Statevector.fromBitstring('1111'));
const dist: string[] = [];
for (let k = 1; k <= 60; k++) {
  a = step(a, s[k - 1]);
  b = step(b, s[k - 1]);
  if ([1, 10, 20, 40, 60].includes(k)) dist.push('k=' + k + ' ' + sci(traceDistance(a, b)));
}
console.log('trace distance: ' + dist.join(', '));

// NARMA2: diverges when driven by s in [0, 1), bounded when driven by u = s/2.
const raw = narma2(s.slice(0, 80));
console.log('NARMA2 driven by s: |y_k| > 1 first at k = ' + raw.findIndex((v) => Math.abs(v) > 1) + ', > 1000 at k = ' + raw.findIndex((v) => Math.abs(v) > 1000));
const yN = narma2Target(s); // = narma2(s.map((v) => v / 2))
const wN = ridgeRegression(X.slice(200, 800), yN.slice(200, 800), 1e-6);
console.log('NARMA2 driven by s/2: y in [' + Math.min(...yN.slice(1)).toFixed(4) + ', ' + Math.max(...yN).toFixed(4) + '], test NMSE ' + nmse(predictReadout(X.slice(800), wN), yN.slice(800)).toPrecision(4));

Expected output

inputs s_0..s_2: 0.6011037519, 0.4482905590, 0.8524657935
features: 1200 rows x 21 columns, row 0 starts -0.089304 0.850546 0.230656 0.300436
delay 1: test NMSE 0.01052, 21 weights
delay 2: test NMSE 0.03571, 21 weights
delay 3: test NMSE 0.05027, 21 weights
memory curve r_d^2: 0.9895 0.9644 0.9502 0.8836 0.7916 0.5480 -> MC = 5.127
trace distance: k=1 1.000e+00, k=10 3.250e-01, k=20 6.011e-02, k=40 1.276e-03, k=60 4.931e-05
NARMA2 driven by s: |y_k| > 1 first at k = 57, > 1000 at k = 75
NARMA2 driven by s/2: y in [0.1163, 0.3343], test NMSE 0.1015

The NumPy cell rebuilds the reservoir from scratch: a port of mulberry32, the Hamiltonian from Kronecker products, the injection as an explicit partial trace and the ridge readout by Cholesky. It prints the same lines as the TypeScript cell.

Pythonrunnable
import numpy as np


# Port of the engine's mulberry32 (bit-for-bit identical floats).
def mulberry32(seed):
    a = seed & 0xFFFFFFFF

    def imul(u, v):
        return (u * v) & 0xFFFFFFFF

    def r():
        nonlocal a
        a = (a + 0x6D2B79F5) & 0xFFFFFFFF
        t = imul(a ^ (a >> 15), 1 | a)
        t = ((t + imul(t ^ (t >> 7), 61 | t)) & 0xFFFFFFFF) ^ t
        return (t ^ (t >> 14)) / 4294967296

    return r


# The L54 reservoir: 4 qubits (qubit 0 = most significant bit), H = sum J_ij X_i X_j + h sum Z_q.
n, h, tau, V = 4, 0.5, 4.0, 5
J = {(0, 1): 0.0695, (0, 2): 0.6305, (0, 3): -0.0920, (1, 2): -0.0749, (1, 3): -0.3440, (2, 3): 0.8774}
I2, X, Z = np.eye(2), np.array([[0.0, 1.0], [1.0, 0.0]]), np.diag([1.0, -1.0])


def on(ops):  # tensor product with ops[q] on qubit q and I elsewhere
    out = np.eye(1)
    for q in range(n):
        out = np.kron(out, ops.get(q, I2))
    return out


H = sum(c * on({i: X, j: X}) for (i, j), c in J.items()) + h * sum(on({q: Z}) for q in range(n))
E, W = np.linalg.eigh(H)
U = W @ np.diag(np.exp(-1j * E * tau / V)) @ W.conj().T  # one virtual-node step e^{-i H tau / V}
SIGNS = np.array([[1 - 2 * ((x >> (n - 1 - q)) & 1) for q in range(n)] for x in range(2**n)])  # (-1)^{x_q}


def inject(rho, s):  # rho -> |psi_s><psi_s| (x) Tr_0 rho
    blocks = rho.reshape(2, 8, 2, 8)
    reduced = blocks[0, :, 0, :] + blocks[1, :, 1, :]
    psi = np.array([np.sqrt(1 - s), np.sqrt(s)])
    return np.kron(np.outer(psi, psi), reduced)


def step(rho, s):  # inject, then V sub-steps; returns the new state and the 4V features
    rho, row = inject(rho, s), []
    for _ in range(V):
        rho = U @ rho @ U.conj().T
        row.extend(SIGNS.T @ np.real(np.diag(rho)))  # <Z_q> = sum_x (-1)^{x_q} rho_xx
    return rho, row


def basis_state(bits):
    rho = np.zeros((2**n, 2**n), dtype=complex)
    rho[int(bits, 2), int(bits, 2)] = 1
    return rho


r = mulberry32(42)
s = np.array([r() for _ in range(1200)])
print("inputs s_0..s_2:", ", ".join(f"{v:.10f}" for v in s[:3]))

rho, rows = basis_state("0000"), []
for sk in s:
    rho, row = step(rho, sk)
    rows.append(row + [1.0])
F = np.array(rows)
print(f"features: {F.shape[0]} rows x {F.shape[1]} columns, row 0 starts", " ".join(f"{v:.6f}" for v in F[0, :4]))


def ridge(Xm, y, lam):  # (X^T X + lam I) w = X^T y by Cholesky
    L = np.linalg.cholesky(Xm.T @ Xm + lam * np.eye(Xm.shape[1]))
    return np.linalg.solve(L.T, np.linalg.solve(L, Xm.T @ y))


def nmse(pred, y):
    return np.sum((pred - y) ** 2) / np.sum((y - y.mean()) ** 2)


r2 = []
for d in range(1, 7):
    y = np.concatenate([np.full(d, np.nan), s[:-d]])  # y_k = s_{k-d}
    w = ridge(F[200:800], y[200:800], 1e-6)
    pred = F[800:] @ w
    r2.append(np.corrcoef(pred, y[800:])[0, 1] ** 2)
    if d <= 3:
        print(f"delay {d}: test NMSE {nmse(pred, y[800:]):.4g}, {len(w)} weights")
print("memory curve r_d^2:", " ".join(f"{v:.4f}" for v in r2), f"-> MC = {sum(r2):.3f}")

# Fading memory: the same inputs drive |0000> and |1111>; trace distance T = 1/2 sum |eigenvalues of the difference|.
a, b, dist = basis_state("0000"), basis_state("1111"), {}
for k in range(1, 61):
    a, _ = step(a, s[k - 1])
    b, _ = step(b, s[k - 1])
    dist[k] = 0.5 * np.sum(np.abs(np.linalg.eigvalsh(a - b)))
print("trace distance:", ", ".join(f"k={k} {dist[k]:.3e}" for k in (1, 10, 20, 40, 60)))


def narma2(u):
    y = np.zeros(len(u))
    for k in range(1, len(u)):
        y_km2 = y[k - 2] if k >= 2 else 0.0
        y[k] = 0.4 * y[k - 1] + 0.4 * y[k - 1] * y_km2 + 0.6 * u[k - 1] ** 3 + 0.1
    return y


raw = narma2(s[:80])
print(f"NARMA2 driven by s: |y_k| > 1 first at k = {np.argmax(np.abs(raw) > 1)}, > 1000 at k = {np.argmax(np.abs(raw) > 1000)}")
y = narma2(0.5 * s)  # u = s/2
w = ridge(F[200:800], y[200:800], 1e-6)
print(f"NARMA2 driven by s/2: y in [{y[1:].min():.4f}, {y.max():.4f}], test NMSE {nmse(F[800:] @ w, y[800:]):.4g}")

Expected output

inputs s_0..s_2: 0.6011037519, 0.4482905590, 0.8524657935
features: 1200 rows x 21 columns, row 0 starts -0.089304 0.850546 0.230656 0.300436
delay 1: test NMSE 0.01052, 21 weights
delay 2: test NMSE 0.03571, 21 weights
delay 3: test NMSE 0.05027, 21 weights
memory curve r_d^2: 0.9895 0.9644 0.9502 0.8836 0.7916 0.5480 -> MC = 5.127
trace distance: k=1 1.000e+00, k=10 3.250e-01, k=20 6.011e-02, k=40 1.276e-03, k=60 4.931e-05
NARMA2 driven by s: |y_k| > 1 first at k = 57, > 1000 at k = 75
NARMA2 driven by s/2: y in [0.1163, 0.3343], test NMSE 0.1015

In the lab you write the readout yourself; the grader scores your weights on the 400400 test steps.

References

  1. K. Fujii and K. Nakajima, Harnessing disordered-ensemble quantum dynamics for machine learning, Physical Review Applied 8, 024030 (2017).doi:10.1103/PhysRevApplied.8.024030
  2. H. Jaeger, The "echo state" approach to analysing and training recurrent neural networks, GMD Report 148, German National Research Center for Information Technology (2001).ai.rug.nl
  3. H. Jaeger, Short term memory in echo state networks, GMD Report 152, German National Research Center for Information Technology (2002).
  4. K. Nakajima and I. Fischer (eds.), Reservoir Computing: Theory, Physical Implementations, and Applications, Springer, Singapore (2021).doi:10.1007/978-981-13-1687-6
  5. P. Mujal, R. Martínez-Peña, J. Nokkala, J. García-Beni, G. L. Giorgi, M. C. Soriano and R. Zambrini, Opportunities in quantum reservoir computing and extreme learning machines, Advanced Quantum Technologies 4, 2100027 (2021).doi:10.1002/qute.202100027
  6. A. F. Atiya and A. G. Parlos, New results on recurrent network training: unifying the algorithms and accelerating convergence, IEEE Transactions on Neural Networks 11, 697–709 (2000).doi:10.1109/72.846741
  7. W. Maass, T. Natschläger and H. Markram, Real-time computing without stable states: a new framework for neural computation based on perturbations, Neural Computation 14, 2531–2560 (2002).doi:10.1162/089976602760407955

Hands-on labs

  • Train the ridge readout of a quantum reservoir

    1 step · auto-graded

    The 44-qubit quantum reservoir of the lesson is fixed: its Ising Hamiltonian, the input injection on qubit 00 and the 55 virtual nodes per input are never trained. Only the linear readout is learned. Your TypeScript function receives the 600×21600\times21 feature matrix of the training window (the 2020 expectation values ⟨Zq⟩\langle Z_q\rangle plus a bias column) and the targets of a short-term memory task, and returns the ridge-regression weights w=(X⊤X+λI)−1X⊤yw=(X^\top X+\lambda I)^{-1}X^\top y. The grader recomputes the reservoir and scores your weights on 400400 unseen time steps: recalling the input of one step ago must reach NMSE≤0.03\mathrm{NMSE}\le0.03, recalling the input of two steps ago NMSE≤0.08\mathrm{NMSE}\le0.08.

    Open lab