TorchLean API

NN.Proofs.Autograd.Tape.Nodes.Context

Tape-node context primitives #

This module contains the low-level vectorized context operations used by the tape-node proof library: block projections, one-hot cotangent injections, and the bridge from generic OpSpecFDerivCorrect witnesses to NodeFDerivCorrect nodes.

Coordinate lemmas for the Euclidean identification #

Mathlib's EuclideanSpace is PiLp 2, a type synonym carrying a WithLp wrapper. The four lemmas below are the plumbing that lets us forget the wrapper: each says that reading coordinate i of a vector built from f gives f i, for the various shapes the wrapper takes. They are boring on purpose, and having them as simp lemmas is what keeps the real proofs in this file readable.

@[simp]
theorem Proofs.Autograd.piLpContinuousLinearEquiv2_symm_apply {n : } (f : Fin n) (i : Fin n) :
((PiLp.continuousLinearEquiv 2 fun (x : Fin n) => ).symm f).ofLp i = f i

Coordinates of the inverse PiLp equivalence are the values of the underlying function.

@[simp]
theorem Proofs.Autograd.piLpContinuousLinearEquiv2_symm_clm_apply {n : } (f : Fin n) (i : Fin n) :
((PiLp.continuousLinearEquiv 2 fun (x : Fin n) => ).symm f).ofLp i = f i

The same, applied through the bundled continuous linear map.

@[simp]

The same again, with the ofLp projection made explicit.

@[simp]
theorem Proofs.Autograd.euclideanEquiv_symm_ofLp {n : } (f : Fin n) (i : Fin n) :

And once more for EuclideanSpace.equiv, the spelling used by vecOfFun.

@[simp]

Inner product against a one-dimensional constant vector collapses to a single product.

Scalar tensors vectorize to Vec 1, so this is the lemma that turns the adjointness statement for a scalar node into ordinary multiplication instead of a sum over Finset.univ.

Project a vectorized context onto the block at list position i.

CtxVec.get is the shape-indexed interface; it accepts an Idx Γ s and transports the result to the statically known shape s.

Instances For

    Inject v into block i of a vectorized context and fill every other block with zeros.

    This is the adjoint of getBlock with respect to the Euclidean inner product.

    Instances For

      Adjointness of block projection and injection.

      This is the vectorized counterpart of the one-hot cotangent principle used in tape soundness.

      noncomputable def Proofs.Autograd.CtxVec.get {Γ : List Spec.Shape} {s : Spec.Shape} (idx : Idx Γ s) (x : CtxVec Γ) :

      Project the block specified by idx : Idx Γ s out of a vectorized context.

      Instances For

        Selecting a block after vectorization agrees with selecting the original tensor.

        Typed tensor selection commutes with vectorization, including its shape cast.

        noncomputable def Proofs.Autograd.CtxVec.single {Γ : List Spec.Shape} {s : Spec.Shape} (idx : Idx Γ s) (v : Vec s.size) :

        Inject a block into a vectorized context at idx, filling other blocks with zeros.

        Instances For
          theorem Proofs.Autograd.CtxVec.inner_get_single {Γ : List Spec.Shape} {s : Spec.Shape} (idx : Idx Γ s) (x : CtxVec Γ) (v : Vec s.size) :
          inner x (single idx v) = inner (get idx x) v

          Adjointness of get/single: ⟪x, single idx v⟫ = ⟪get idx x, v⟫.

          Continuous linear map extracting the head block of a nonempty vectorized context.

          Instances For
            @[simp]
            theorem Proofs.Autograd.CtxVec.headCLM_apply {s : Spec.Shape} {ss : List Spec.Shape} (x : CtxVec (s :: ss)) (j : Fin s.size) :

            headCLM reads the leading block of coordinates, exactly as flattenCtx_cons lays them out.

            Continuous linear map extracting the tail blocks of a nonempty vectorized context.

            Instances For
              @[simp]
              theorem Proofs.Autograd.CtxVec.tailCLM_apply {s : Spec.Shape} {ss : List Spec.Shape} (x : CtxVec (s :: ss)) (j : Fin (ctxSize ss)) :

              tailCLM reads the trailing blocks.

              getBlock as a continuous linear map, constructed recursively from headCLM and tailCLM.

              Instances For
                @[simp]

                The bundled getBlockCLM computes the same thing as the plain getBlock.

                This is the payoff of building it recursively from headCLM and tailCLM: block selection comes out continuous and linear by construction, so nothing downstream has to prove it again.

                noncomputable def Proofs.Autograd.CtxVec.getCLM {Γ : List Spec.Shape} {s : Spec.Shape} (idx : Idx Γ s) :

                get packaged as a continuous linear map.

                Instances For
                  @[simp]
                  theorem Proofs.Autograd.CtxVec.getCLM_apply {Γ : List Spec.Shape} {s : Spec.Shape} (idx : Idx Γ s) (x : CtxVec Γ) :
                  (getCLM idx) x = get idx x

                  And the shape-indexed getCLM agrees with get.

                  Nodes in this file are authored directly on the vectorized context CtxVec.

                  This is the most convenient authoring style for analytic proofs: forwardVec/jvpVec/vjpVec are definitional, and the correctness obligation is an inner-product identity on Euclidean vectors.

                  noncomputable def Proofs.Autograd.Node.ofFn {Γ : List Spec.Shape} {τ : Spec.Shape} (f : CtxVec ΓVec τ.size) (jvp : CtxVec ΓCtxVec ΓVec τ.size) (vjp : CtxVec ΓVec τ.sizeCtxVec Γ) (correct_inner : ∀ (x dx : CtxVec Γ) (δ : Vec τ.size), inner (jvp x dx) δ = inner dx (vjp x δ)) :
                  Node Γ τ

                  Convenience constructor: build a tape Node from vector-level forward/JVP/VJP plus adjointness.

                  The correct_inner field is exactly the local VJP/JVP law: ⟪jvp x dx, δ⟫ = ⟪dx, vjp x δ⟫.

                  Instances For
                    @[simp]
                    theorem Proofs.Autograd.Node.forwardVec_ofFn {Γ : List Spec.Shape} {τ : Spec.Shape} (f : CtxVec ΓVec τ.size) (jvp : CtxVec ΓCtxVec ΓVec τ.size) (vjp : CtxVec ΓVec τ.sizeCtxVec Γ) (h : ∀ (x dx : CtxVec Γ) (δ : Vec τ.size), inner (jvp x dx) δ = inner dx (vjp x δ)) :
                    (ofFn f jvp vjp h).forwardVec = f

                    A node built by ofFn has the given forward map.

                    @[simp]
                    theorem Proofs.Autograd.Node.jvpVec_ofFn {Γ : List Spec.Shape} {τ : Spec.Shape} (f : CtxVec ΓVec τ.size) (jvp : CtxVec ΓCtxVec ΓVec τ.size) (vjp : CtxVec ΓVec τ.sizeCtxVec Γ) (h : ∀ (x dx : CtxVec Γ) (δ : Vec τ.size), inner (jvp x dx) δ = inner dx (vjp x δ)) :
                    (ofFn f jvp vjp h).jvpVec = jvp

                    A node built by ofFn has the given forward-mode derivative.

                    @[simp]
                    theorem Proofs.Autograd.Node.vjpVec_ofFn {Γ : List Spec.Shape} {τ : Spec.Shape} (f : CtxVec ΓVec τ.size) (jvp : CtxVec ΓCtxVec ΓVec τ.size) (vjp : CtxVec ΓVec τ.sizeCtxVec Γ) (h : ∀ (x dx : CtxVec Γ) (δ : Vec τ.size), inner (jvp x dx) δ = inner dx (vjp x δ)) :
                    (ofFn f jvp vjp h).vjpVec = vjp

                    A node built by ofFn has the given reverse-mode derivative. Together the three projection lemmas mean a caller never has to unfold ofFn, only supply the soundness argument h once.

                    noncomputable def Proofs.Autograd.OpSpecFDerivCorrect.linear {inDim outDim : } (m : Spec.LinearSpec inDim outDim) :
                    OpSpecFDerivCorrect inDim outDim

                    OpSpecFDerivCorrect instance for a linear layer.

                    This is the analytic correctness lemma behind the tape node constructors: it identifies the JVP with the Fréchet derivative (a matrix multiplication) for linearSpec.

                    PyTorch analogue: the torch.nn.Linear forward map is affine, so its derivative is constant. https://pytorch.org/docs/stable/generated/torch.nn.Linear.html

                    Instances For