TorchLean API

NN.Proofs.RuntimeApprox.Graph.BackwardApprox

BackwardApprox #

Reverse-mode (backward) runtime→spec approximation framework.

This is the backward analogue of NN/Proofs/RuntimeApprox/Graph/ForwardApprox.lean.

It models a tape/SSA-style DAG where each node provides:

The global theorem RevGraph.backprop_approx composes these local bounds over the whole graph, analogously to FwdGraph.eval_approx.

Note: reverse-mode accumulation uses context-wise addition; the corresponding bound/soundness for accumulation is an explicit parameter to the theorem (addBound, addSound).

What you get #

Reading guide #

  1. RevNode / RevGraph: nodes carry both forward and VJP approximation data.
  2. RevGraph.eval_*: reuse the forward theory by forgetting VJP data.
  3. RevGraph.backprop*: executable reverse-mode accumulation + its explicit bound propagation.
  4. RevGraph.backprop_approx: composes node-local VJP bounds and accumulation bounds over the whole graph (induction over the snoc-list).

PyTorch correspondence / citations #

This mirrors the structure of reverse-mode AD in PyTorch Autograd: a forward pass produces intermediate values, and a backward pass propagates cotangents/gradients in reverse topological order while accumulating contributions at shared nodes. https://pytorch.org/docs/stable/autograd.html

Componentwise addition of error lists (used when accumulating cotangent/gradient bounds).

Instances For
    structure Proofs.RuntimeApprox.RevNode {α : Type} (toSpec : αSpec.SpecScalar) (Γ : List Spec.Shape) (τ : Spec.Shape) extends Proofs.RuntimeApprox.FwdNode toSpec Γ τ :

    A node with both forward and VJP approximation data.

    Instances For
      inductive Proofs.RuntimeApprox.RevGraph {α : Type} (toSpec : αSpec.SpecScalar) (Γ : List Spec.Shape) :

      Tape/SSA DAG with reverse-mode metadata (nodes appended in topological order).

      Compared to FwdGraph, each node additionally carries a local VJP rule (RevNode.vjp*) plus an explicit error transformer vjpBound and its soundness lemma vjpSound.

      Instances For
        def Proofs.RuntimeApprox.RevGraph.toFwdGraph {α : Type} {toSpec : αSpec.SpecScalar} {Γ ss : List Spec.Shape} :
        RevGraph toSpec Γ ssFwdGraph toSpec Γ ss

        Forget the VJP metadata of a RevGraph, yielding a FwdGraph with the same node ordering.

        This lets us reuse the forward approximation theorem (FwdGraph.eval_approx) for free.

        Instances For
          def Proofs.RuntimeApprox.RevGraph.evalSpec {α : Type} {toSpec : αSpec.SpecScalar} {Γ ss : List Spec.Shape} (g : RevGraph toSpec Γ ss) (x : TList Spec.SpecScalar Γ) :

          Spec-level evaluation of a RevGraph (delegates to toFwdGraph).

          Instances For
            def Proofs.RuntimeApprox.RevGraph.evalRuntime {α : Type} {toSpec : αSpec.SpecScalar} {Γ ss : List Spec.Shape} (g : RevGraph toSpec Γ ss) (x : TList α Γ) :
            TList α (Γ ++ ss)

            Runtime-level evaluation of a RevGraph (delegates to toFwdGraph).

            Instances For
              def Proofs.RuntimeApprox.RevGraph.evalBounds {α : Type} {toSpec : αSpec.SpecScalar} {Γ ss : List Spec.Shape} (g : RevGraph toSpec Γ ss) (epsIn : EList Γ) (xR : TList α Γ) :
              EList (Γ ++ ss)

              Forward bound propagation for a RevGraph (delegates to toFwdGraph).

              Instances For
                theorem Proofs.RuntimeApprox.RevGraph.eval_approx {α : Type} {toSpec : αSpec.SpecScalar} {Γ ss : List Spec.Shape} (g : RevGraph toSpec Γ ss) (xS : TList Spec.SpecScalar Γ) (xR : TList α Γ) (epsIn : EList Γ) :
                approxCtx toSpec xS xR epsInapproxCtx toSpec (g.evalSpec xS) (g.evalRuntime xR) (g.evalBounds epsIn xR)

                Forward approximation theorem for RevGraph (just FwdGraph.eval_approx via toFwdGraph).

                def Proofs.RuntimeApprox.RevGraph.backpropSpec {α : Type} {toSpec : αSpec.SpecScalar} {Γ ss : List Spec.Shape} (g : RevGraph toSpec Γ ss) (x : TList Spec.SpecScalar Γ) (seed : TList Spec.SpecScalar (Γ ++ ss)) :

                Spec-level reverse-mode evaluation.

                Informally: run the forward pass to get node contexts, then traverse nodes in reverse topological order, applying each node’s VJP and accumulating the resulting context-cotangent into the running seed.

                Instances For
                  def Proofs.RuntimeApprox.RevGraph.backpropRuntime {α : Type} {toSpec : αSpec.SpecScalar} {Γ ss : List Spec.Shape} (g : RevGraph toSpec Γ ss) [Add α] (x : TList α Γ) (seed : TList α (Γ ++ ss)) :
                  TList α Γ

                  Runtime-level reverse-mode accumulation.

                  This mirrors backpropSpec, but uses runtime tensors and relies on an Add α instance to accumulate contributions at shared nodes.

                  Instances For
                    def Proofs.RuntimeApprox.RevGraph.backpropBounds {α : Type} {toSpec : αSpec.SpecScalar} {Γ ss : List Spec.Shape} (g : RevGraph toSpec Γ ss) [Add α] (epsIn : EList Γ) (xR : TList α Γ) (epsSeed : EList (Γ ++ ss)) (seedR : TList α (Γ ++ ss)) (addBound : {Δ : List Spec.Shape} → EList ΔEList ΔTList α ΔTList α ΔEList Δ) :

                    Backward error propagation for backprop*.

                    This is parameterized by:

                    • addBound: how to compute the (per-entry) error list for context-wise addition.

                    addBound may depend on the runtime addends, to account for rounding models.

                    Instances For
                      theorem Proofs.RuntimeApprox.RevGraph.backprop_approx {α : Type} {toSpec : αSpec.SpecScalar} {Γ ss : List Spec.Shape} (g : RevGraph toSpec Γ ss) [Add α] (addBound : {Δ : List Spec.Shape} → EList ΔEList ΔTList α ΔTList α ΔEList Δ) (addSound : ∀ {Δ : List Spec.Shape} (xS yS : TList Spec.SpecScalar Δ) (xR yR : TList α Δ) (epsx epsy : EList Δ), approxCtx toSpec xS xR epsxapproxCtx toSpec yS yR epsyapproxCtx toSpec (TList.add xS yS) (TList.add xR yR) (addBound epsx epsy xR yR)) (xS : TList Spec.SpecScalar Γ) (xR : TList α Γ) (epsIn : EList Γ) (seedS : TList Spec.SpecScalar (Γ ++ ss)) (seedR : TList α (Γ ++ ss)) (epsSeed : EList (Γ ++ ss)) :
                      approxCtx toSpec xS xR epsInapproxCtx toSpec seedS seedR epsSeedapproxCtx toSpec (g.backpropSpec xS seedS) (g.backpropRuntime xR seedR) (g.backpropBounds epsIn xR epsSeed seedR fun {Δ : List Spec.Shape} => addBound)

                      End-to-end reverse-mode approximation theorem for RevGraph.backprop*.

                      Informally: assume (1) the runtime inputs xR approximate the spec inputs xS with bounds epsIn, and (2) the runtime seed cotangents seedR approximate the spec seeds seedS with bounds epsSeed. Then the whole backprop result backpropRuntime g xR seedR approximates the spec backprop result backpropSpec g xS seedS, with an explicit bound computed by backpropBounds.

                      The only "extra" ingredient beyond per-node VJP approximation is how we accumulate contributions: addBound describes how addition affects error bounds, and addSound is the theorem justifying it (e.g. for exact reals it is trivial; for rounding models it carries the rounding-error analysis).