| Safe Haskell | None |
|---|---|
| Language | GHC2024 |
Circuit.Diff.Star
Description
The Schur-complement bridge — trace solved by starMatrix.
This is where the three floors actually touch. A 'Diff knot body
has a backward pass that is affine in cotangents (calculus
promises linearity), so its channel self-coupling is a linear map
recoverable by probing with basis cotangents. Build that map as a
Matrix, take its Kleene star with starMatrix — Gaussian
elimination, (I − A)⁻¹, the fourth face of the four-for-one — and
the trace's pullback is the Schur complement
db = D·dc + B · star A · C·dc
recovered with one final probe at the backward fixpoint.
Cost: dim probes of backward plus one starMatrix per forward
point, shared across all cotangents; each subsequent pullback is
two probes and a matrix–vector product. Compare traceNFrom,
which pays n probes per cotangent and is only as exact as n is
large. Here the backward pass is exact whenever the star exists.
The dependency is deliberate: this module imports Circuit.Mat.Dense, making circuits-ad ⇄ star-matrix a literal edge rather than a nominal alias.
Synopsis
- traceStarMatrix :: forall {k} j c (p :: k) b. (StarSemiring j, MergeZero (->) c) => [j] -> Int -> Diff p ([j], b) ([j], c) -> Diff p b c
- solveStarBody :: forall s a b. Body (,) (StarChannel s) Pullback b a -> Pullback b a
- traceStarFromD :: forall {k} c (p :: k) b. MergeZero (->) c => Double -> Int -> Diff p (Double, b) (Double, c) -> Diff p b c
- traceStarMatrixD :: forall {k} c (p :: k) b. MergeZero (->) c => [Double] -> Int -> Diff p ([Double], b) ([Double], c) -> Diff p b c
Polymorphic bridge
Arguments
| :: forall {k} j c (p :: k) b. (StarSemiring j, MergeZero (->) c) | |
| => [j] | forward seed; its length is the channel dimension |
| -> Int | forward iteration count |
| -> Diff p ([j], b) ([j], c) | |
| -> Diff p b c |
Trace over a vector feedback channel, backward pass solved by
starMatrix.
The channel is a list [j] whose dimension is fixed by the seed.
Forward iterates from the seed (no closed form for a nonlinear
fixpoint). Backward:
- probe
backwardwith each basis cotangente_ito read off columniof the channel self-coupling A (in cotangent space); star Aby Conway block recursion —starMatrix;- per cotangent
dc:C·dc = fst (backward (0, dc)), thendb = snd (backward (star A · C·dc, dc)).
A and star A are forced once (lazily, on first pullback) and
shared across cotangents.
Proof obligation: probing assumes every primitive's pullback is a genuinely linear map — true for honestly-constructed 'Diff prims.
Body bridge
solveStarBody :: forall s a b. Body (,) (StarChannel s) Pullback b a -> Pullback b a Source #
Solve a (,) feedback body whose channel is StarChannel in closed form.
The channel type stays exposed, so the dictionary is read directly from the
StarChannel value carried on the feedback wire.
A self-coupled scalar body the lazy trace diverges on, solved exactly
(dj = 0.3·dj + 2·dc, db = dj, so db/dc = 2/0.7):
>>>:{let body (FieldStar dj, dc) = (FieldStar (0.3 * dj + 2.0 * dc), dj) b = Body (withStarChannel fieldStarChannel (Pullback body)) :: Body (,) (StarChannel FieldStar) Pullback Double Double :}
>>>let solved = solveStarBody b>>>abs (runPullback solved 1.0 - 2.0 / 0.7) < 1e-12True
Double adapters (via FieldStar)
traceStarFromD :: forall {k} c (p :: k) b. MergeZero (->) c => Double -> Int -> Diff p (Double, b) (Double, c) -> Diff p b c Source #
traceStarFrom for a bare Double channel, routed
through FieldStar so star a = recip (1 − a) is the class
method, not an ad-hoc formula.
Channel x' = 0.3x + b, output c = 2x. The fixpoint is
x = b/0.7, so dc/db = 2/0.7 ≈ 2.857 — the same number the
Neumann iteration approaches, computed here in closed form:
>>>:{let body = Diff (\(x, b) -> ( (0.3 * x + b, 2.0 * x) , \(dx', dc) -> (0.3 * dx' + 2.0 * dc, dx') )) :}
>>>let (y, pb) = runDiff (traceStarFromD 0 60 body) 1.0>>>abs (y - 2.0 / 0.7) < 1e-12True>>>abs (pb 1.0 - 2.0 / 0.7) < 1e-12True
traceStarMatrixD :: forall {k} c (p :: k) b. MergeZero (->) c => [Double] -> Int -> Diff p ([Double], b) ([Double], c) -> Diff p b c Source #
traceStarMatrix for bare [Double] channels, routed through
FieldStar so starMatrix performs honest (I − A)⁻¹.
A two-dimensional channel: x' = 0.5y + b, y' = 0.3x, output
c = x + 2y. Solving the fixpoint by hand: x = b/0.85,
y = 0.3b/0.85, c = 1.6b/0.85, so dc/db = 1.6/0.85.
>>>:{let body2 = Diff (\([x, y], b) -> ( ([0.5 * y + b, 0.3 * x], x + 2.0 * y) , \([dx', dy'], dc) -> ([0.3 * dy' + dc, 0.5 * dx' + 2.0 * dc], dx') )) :}
>>>let (y2, pb2) = runDiff (traceStarMatrixD [0, 0] 200 body2) 1.0>>>abs (y2 - 1.6 / 0.85) < 1e-12True>>>abs (pb2 1.0 - 1.6 / 0.85) < 1e-12True
Orphan instances
| Zero (->) FieldStar Source # | |
| Merge (->) FieldStar Source # |
These instances remain necessary because structural rows ( |