Documentation

LeanMlir.Proofs.Nets.ViT.ViTBackB0

ViT backward-graph faithfulness (per-token Mat VJP) #

The ViT analogue of the other four nets' *BackB0 capstones: backward StableHLO graphs (over the ch10 backward tokens — denseRowBack/geluBack/ lnRowBack/softmaxRowBack/matmulF/transposeF/scaleF/addV) whose denotations ARE the proven VJPs, from the MLP and MHSA pieces up to the multi-head vector-LN block the shipped net runs (transformerBlockV_has_vjp_mat) and the depth-k whole net (vitNetBackGraph).

Unlike the conv nets — whose blocks live natively as Vec → Vec (HasVJP) — a transformer block lives in the per-token matrix framework HasVJPMat (Mat N D → Mat N D). The block VJP's .backward is therefore Mat-valued, while den is Vec-valued; the faithfulness statements bridge the two through Mat.flatten (the convention the forward-graph faithfulness theorems use):

den (…BackGraph A e) = Mat.flatten ((… _has_vjp_mat …).backward A (Mat.unflatten (den e)))

The pieces, bottom-up:

The framework .backward rules (Tensor.lean):

Each ch10 backward den helper is a flattened rowwise op; here we tie it to the HasVJPMat .backward of the corresponding framework piece. These are the ViT-backward analogues of ViTFwdGraph's rowDenseFlat_flat/rowLNFlat_flat forward bridges.

theorem Proofs.StableHLO.rowDenseBackFlat_eq_backward {N a c : } (W : Mat a c) (b : Vec c) (A : Mat N a) (dY : Mat N c) :

Per-token dense input-VJP: the flat rowDenseBackFlat IS the flatten of the rowwise dense_per_token_has_vjp_mat.backward (which ignores the saved activation A, dense being affine — dense_has_vjp.backward _ dy = Mat.mulVec W dy).

theorem Proofs.StableHLO.rowLNBackFlat_eq_backward {N D : } (ε γ β : ) ( : 0 < ε) (A dY : Mat N D) :

Per-token LayerNorm input-VJP: rowLNBackFlat IS the flatten of the rowwise layerNorm_per_token_has_vjp_mat.backward at the saved pre-LN activation A. (layerNorm_has_vjp is definitionally bn_has_vjp, whose backward is bn_grad_input; rowLNBackFlat is the rowwise bn_grad_input.)

Per-token GELU input-VJP: the flat gelu_has_vjp (N*D) backward IS the flatten of the rowwise gelu_per_token_has_vjp_mat.backward at the saved pre-GELU activation A (GELU is elementwise, so flat and rowwise agree).

noncomputable def Proofs.StableHLO.transformerMlpBackGraph {Np1 D mlpDim : } (Wfc1 : Mat D mlpDim) (bfc1 : Vec mlpDim) (Wfc2 : Mat mlpDim D) (Y : Mat Np1 D) (e : SHlo (Np1 * D)) :
SHlo (Np1 * D)

The transformer MLP backward graph (reverse-order chain of transformerMlp_has_vjp_mat = dense2 ∘ gelu ∘ dense1 per-token; outermost backward token = earliest forward op = dense1):

denseRowBack(Wfc1) ∘ geluBack(@ pre-GELU = dense1(Y)) ∘ denseRowBack(Wfc2)

where Y is the MLP input (= LN₂ h). The GELU backward reads its saved pre-activation m1 = dense1 Y.

Equations
  • One or more equations did not get rendered due to their size.
Instances For
    theorem Proofs.StableHLO.transformerMlpBackGraph_faithful {Np1 D mlpDim : } (Wfc1 : Mat D mlpDim) (bfc1 : Vec mlpDim) (Wfc2 : Mat mlpDim D) (bfc2 : Vec D) (Y dz : Mat Np1 D) (ecot : SHlo (Np1 * D)) (hecot : den ecot = dz.flatten) :
    den (transformerMlpBackGraph Wfc1 bfc1 Wfc2 Y ecot) = ((transformerMlp_has_vjp_mat Np1 D mlpDim Wfc1 bfc1 Wfc2 bfc2).backward Y dz).flatten

    MLP backward-graph faithfulness. The reverse-order chain denotes the proven transformerMlp_has_vjp_mat.backward at the saved MLP input Y. The two dense backs ignore the activation; GELU's reads dense1 Y.

    ⭐ Stated over an arbitrary incoming-cotangent SUBGRAPH ecot (any graph whose den is the flattened cotangent), not over a bare Vec wrapped internally as .operand "%dz". That is what lets this arm sit downstream of another graph; the old statement is this one at ecot := .operand "%dz" (Mat.flatten dz).

    The proven mhsa_has_vjp_mat witness is built via by rw [mhsa_layer_eq_compose]; exact vjpMat_comp …, so its .backward field does NOT reduce by rfl (the Eq.mpr transport blocks whnf). We instead build a clean witness mhsaClean for the same factored function (whose .backward unfolds transparently), tie it to mhsa_has_vjp_mat by VJP determinism; the multi-head collapse below runs on it.

    noncomputable def Proofs.StableHLO.mhsaClean (N heads d_head : ) (Wq Wk Wv Wo : Mat (heads * d_head) (heads * d_head)) (bq bk bv bo : Vec (heads * d_head)) :
    HasVJPMat ((fun (M : Mat N (heads * d_head)) (n : Fin N) => dense Wo bo (M n)) colSlabApply (mhsa_g N d_head) fun (X' : Mat N (heads * d_head)) (n : Fin N) => dense (mhsa_qkv_W heads d_head Wq Wk Wv) (mhsa_qkv_b heads d_head bq bk bv) (X' n))

    A clean HasVJPMat witness for the factored MHSA — the same vjpMat_comp chain mhsa_has_vjp_mat's body uses, but stated for the explicit composition Wo-dense ∘ colSlabApply mhsa_g ∘ qkv-dense so its .backward reduces by rfl (no mhsa_layer_eq_compose transport in the way).

    Equations
    • One or more equations did not get rendered due to their size.
    Instances For
      theorem Proofs.StableHLO.mhsaClean_backward_eq (N heads d_head : ) (Wq Wk Wv Wo : Mat (heads * d_head) (heads * d_head)) (bq bk bv bo : Vec (heads * d_head)) (X dY : Mat N (heads * d_head)) :
      (mhsaClean N heads d_head Wq Wk Wv Wo bq bk bv bo).backward X dY = (mhsa_has_vjp_mat N heads d_head Wq Wk Wv Wo bq bk bv bo).backward X dY

      The clean witness's backward IS mhsa_has_vjp_mat's backward (both VJPs of mhsa_layer, tied by determinism).

      The colSlab-lifted MHSA backward collapses to a SUM over heads: each head h slices the dense Q/K/V projections and the Wo-back cotangent to head h's columns, runs sdpa_back_{Q,K,V} at d_head, and the qkv-stack dense-back contracts head h's SDPA backward against the finProdFinEquiv (h, ·) columns of Wq/Wk/Wv.

      noncomputable def Proofs.StableHLO.mhsaBackCollapsedMH (N heads d : ) (Wq Wk Wv Wo : Mat (heads * d) (heads * d)) (bq bk bv _bo : Vec (heads * d)) (X dh : Mat N (heads * d)) :
      Mat N (heads * d)

      The collapsed general-heads MHSA backward: for each head h, slice the dense Q/K/V projections and the Wo-back cotangent to head h's columns, run sdpa_back_{Q,K,V} at d, then contract per-head against the finProdFinEquiv (h, ·) columns of Wq/Wk/Wv, summed over heads.

      Equations
      • One or more equations did not get rendered due to their size.
      Instances For
        theorem Proofs.StableHLO.mhsaClean_backward_collapseMH (N heads d : ) (Wq Wk Wv Wo : Mat (heads * d) (heads * d)) (bq bk bv bo : Vec (heads * d)) (X dh : Mat N (heads * d)) :
        (mhsaClean N heads d Wq Wk Wv Wo bq bk bv bo).backward X dh = mhsaBackCollapsedMH N heads d Wq Wk Wv Wo bq bk bv bo X dh

        MHSA backward general-heads collapse. The clean MHSA witness's backward equals the per-head sum fan-in mhsaBackCollapsedMH.

        theorem Proofs.StableHLO.mhsa_backward_collapseMH (N heads d : ) (Wq Wk Wv Wo : Mat (heads * d) (heads * d)) (bq bk bv bo : Vec (heads * d)) (X dh : Mat N (heads * d)) :
        (mhsa_has_vjp_mat N heads d Wq Wk Wv Wo bq bk bv bo).backward X dh = mhsaBackCollapsedMH N heads d Wq Wk Wv Wo bq bk bv bo X dh

        The proven MHSA VJP's backward at general heads IS the per-head collapse.

        noncomputable def Proofs.StableHLO.sdpaBackQGraph (Np1 D : ) (ss : Vec (Np1 * Np1)) (k v : Vec (Np1 * D)) (e : SHlo (Np1 * D)) :
        SHlo (Np1 * D)

        SDPA dQ-segment subgraph: matmulF(scaleF(softmaxRowBack(matmulF(dAtt, transposeF v))), k) — denotes vitCotDQ. ss = saved pre-softmax scaled scores; k/v/dAtt saved.

        Equations
        • One or more equations did not get rendered due to their size.
        Instances For
          noncomputable def Proofs.StableHLO.sdpaBackKGraph (Np1 D : ) (ss : Vec (Np1 * Np1)) (q v : Vec (Np1 * D)) (e : SHlo (Np1 * D)) :
          SHlo (Np1 * D)

          SDPA dK-segment subgraph — denotes vitCotDK.

          Equations
          • One or more equations did not get rendered due to their size.
          Instances For
            noncomputable def Proofs.StableHLO.sdpaBackVGraph (Np1 D : ) (p : Vec (Np1 * Np1)) (e : SHlo (Np1 * D)) :
            SHlo (Np1 * D)

            SDPA dV-segment subgraph — denotes vitCotDV. p = saved post-softmax weights.

            Equations
            Instances For
              theorem Proofs.StableHLO.sdpaBackQGraph_faithful (Np1 D : ) (ss : Vec (Np1 * Np1)) (k v : Vec (Np1 * D)) (e : SHlo (Np1 * D)) :
              den (sdpaBackQGraph Np1 D ss k v e) = vitCotDQ D ss k v (den e)
              theorem Proofs.StableHLO.sdpaBackKGraph_faithful (Np1 D : ) (ss : Vec (Np1 * Np1)) (q v : Vec (Np1 * D)) (e : SHlo (Np1 * D)) :
              den (sdpaBackKGraph Np1 D ss q v e) = vitCotDK D ss q v (den e)
              theorem Proofs.StableHLO.sdpaBackVGraph_faithful (Np1 D : ) (p : Vec (Np1 * Np1)) (e : SHlo (Np1 * D)) :
              den (sdpaBackVGraph Np1 D p e) = vitCotDV p (den e)
              noncomputable def Proofs.StableHLO.mhsaBackGraphMH {Np1 hm1 d : } (Wq Wk Wv Wo : Mat ((hm1 + 1) * d) ((hm1 + 1) * d)) (Q K V : Fin (hm1 + 1)Vec (Np1 * d)) (ss p : Fin (hm1 + 1)Vec (Np1 * Np1)) (dh : Vec (Np1 * ((hm1 + 1) * d))) :
              SHlo (Np1 * ((hm1 + 1) * d))

              The whole multi-head MHSA backward graph (heads = hm1 + 1): for each head h, the three-way LN₁-fan-in over the per-head SDPA backward subgraphs (fed the head-h slice of the Wo-back), padded into head h's columns and contracted against Wq/Wk/Wv; summed over heads (headsSumG). Saved (per head): the dense Q/K/V projections, the scaled pre-softmax scores ss, the post-softmax weights p; plus the block cotangent dh.

              Equations
              • One or more equations did not get rendered due to their size.
              Instances For
                theorem Proofs.StableHLO.mhsaBackGraphMH_faithful {Np1 hm1 d : } (Wq Wk Wv Wo : Mat ((hm1 + 1) * d) ((hm1 + 1) * d)) (bq bk bv bo : Vec ((hm1 + 1) * d)) (X dh : Mat Np1 ((hm1 + 1) * d)) :
                den (mhsaBackGraphMH Wq Wk Wv Wo (fun (h : Fin (hm1 + 1)) => Mat.flatten fun (r : Fin Np1) (j : Fin d) => dense Wq bq (X r) (finProdFinEquiv (h, j))) (fun (h : Fin (hm1 + 1)) => Mat.flatten fun (r : Fin Np1) (j : Fin d) => dense Wk bk (X r) (finProdFinEquiv (h, j))) (fun (h : Fin (hm1 + 1)) => Mat.flatten fun (r : Fin Np1) (j : Fin d) => dense Wv bv (X r) (finProdFinEquiv (h, j))) (fun (h : Fin (hm1 + 1)) => Mat.flatten fun (i j : Fin Np1) => sdpa_scale d * Mat.mul (fun (r : Fin Np1) (j' : Fin d) => dense Wq bq (X r) (finProdFinEquiv (h, j'))) (Mat.transpose fun (r : Fin Np1) (j' : Fin d) => dense Wk bk (X r) (finProdFinEquiv (h, j'))) i j) (fun (h : Fin (hm1 + 1)) => (sdpa_weights Np1 d (fun (r : Fin Np1) (j' : Fin d) => dense Wq bq (X r) (finProdFinEquiv (h, j'))) fun (r : Fin Np1) (j' : Fin d) => dense Wk bk (X r) (finProdFinEquiv (h, j'))).flatten) dh.flatten) = ((mhsa_has_vjp_mat Np1 (hm1 + 1) d Wq Wk Wv Wo bq bk bv bo).backward X dh).flatten

                MHSA backward-graph faithfulness (multi-head, heads = hm1 + 1). The per-head fan-in graph denotes the proven mhsa_has_vjp_mat.backward (flattened) at general heads, with the saved per-head dense projections, scaled scores, and post-softmax weights.

                The committed verified_mlir/vit_train_step.mlir ViT-Tiny render uses VECTOR γ/β per LN site, decomposed as (+βv) ∘ layerScale γv ∘ LN(1,0) (layerNormVec, ViTVecLN.lean). The forward/backward MHSA and MLP-body are IDENTICAL to the scalar block; the only difference is the two LN sites. So we REUSE mhsaBackGraphMH and transformerMlpBackGraph verbatim and swap the LN-back fragment to the vec-LN one: apply rowScaleF γv to the incoming cotangent, then lnRowBack at γ=1 (the bias backward is the identity, so β drops out of the input cotangent).

                The new structural facts:

                theorem Proofs.StableHLO.layerNormVec_per_token_backward_eq {N D : } (ε : ) (γv βv : Vec D) ( : 0 < ε) (X dY : Mat N D) :
                (layerNormVec_per_token_has_vjp_mat N D ε γv βv ).backward X dY = (layerNorm_per_token_has_vjp_mat N D ε 1 0 ).backward X fun (r : Fin N) => layerScale γv (dY r)

                The vec-LN per-token backward collapses to normalize-only-of-scaled. The vec-LN VJP (+βv) ∘ layerScale γv ∘ LN(1,0) has, by vjp_comp, backward LN(1,0).backward x (layerScale_has_vjp.backward _ (biasAdd.backward _ dy)); biasAdd.backward = id, layerScale_has_vjp.backward _ dy = (γv · * dy ·) = layerScale γv dy. Rowwise-lifted, this is the normalize-only (layerNorm at γ=1, β=0) per-token backward fed the rowwise layerScale γv of the cotangent.

                theorem Proofs.StableHLO.rowVecLNBack_eq_backward {N D : } (ε : ) (γv βv : Vec D) ( : 0 < ε) (X dY : Mat N D) :

                Vec-LN LN-back bridge (Stage 1 crux). The flat composition lnRowBack(γ=1) of (rowScaleF γv applied to the cotangent) denotes the vec-LN per-token VJP's .backward (flattened) at the saved pre-LN input X. The rowScaleF realizes the rowwise layerScale γv on the incoming cotangent; the lnRowBack at γ=1 is the normalize-only backward; the bias backward (identity) has dropped out.

                noncomputable def Proofs.StableHLO.mlpSublayerVInnerBackGraph {Np1 D mlpDim : } (ε : ) (γ2v : Vec D) (Wfc1 : Mat D mlpDim) (bfc1 : Vec mlpDim) (Wfc2 : Mat mlpDim D) (h : Vec (Np1 * D)) (Y : Mat Np1 D) (e : SHlo (Np1 * D)) :
                SHlo (Np1 * D)

                The vec-LN MLP-sublayer non-trivial arm backward graph (transformerMlp ∘ LNᵥ₂; outermost backward token = earliest forward op = LN₂). REUSES transformerMlpBackGraph verbatim (the MLP body is LN-agnostic), after the vector-LN back fragment lnRowBack(γ=1) ∘ rowScaleF γ2v. Y = LNᵥ₂ h is the saved MLP input.

                Equations
                • One or more equations did not get rendered due to their size.
                Instances For
                  theorem Proofs.StableHLO.mlpSublayerVInnerBackGraph_faithful {Np1 D mlpDim : } (ε : ) (γ2v β2v : Vec D) ( : 0 < ε) (Wfc1 : Mat D mlpDim) (bfc1 : Vec mlpDim) (Wfc2 : Mat mlpDim D) (bfc2 : Vec D) (h dz : Mat Np1 D) (ecot : SHlo (Np1 * D)) (hecot : den ecot = dz.flatten) :
                  den (mlpSublayerVInnerBackGraph ε γ2v Wfc1 bfc1 Wfc2 h.flatten (fun (r : Fin Np1) => layerNormVec D ε γ2v β2v (h r)) ecot) = ((layerNormVec_per_token_has_vjp_mat Np1 D ε γ2v β2v ).backward h ((transformerMlp_has_vjp_mat Np1 D mlpDim Wfc1 bfc1 Wfc2 bfc2).backward (fun (r : Fin Np1) => layerNormVec D ε γ2v β2v (h r)) dz)).flatten

                  Vec-LN MLP-sublayer inner-arm backward-graph faithfulness. Denotes the proven (vjpMat_comp LNᵥ₂ transformerMlp).backward h ·. Y = LNᵥ₂ h.

                  noncomputable def Proofs.StableHLO.mlpSublayerVBackGraph {Np1 D mlpDim : } (ε : ) (γ2v : Vec D) (Wfc1 : Mat D mlpDim) (bfc1 : Vec mlpDim) (Wfc2 : Mat mlpDim D) (h : Vec (Np1 * D)) (Y : Mat Np1 D) (ecot : SHlo (Np1 * D)) :
                  SHlo (Np1 * D)

                  The whole vec-LN MLP-sublayer backward graph (inner arm + identity skip).

                  ⭐ The incoming cotangent is a SUBGRAPH ecot, so this sublayer can sit downstream of another backward graph — which is what the attention sublayer below does with it, and what CertLayer composition needs. The old dz : Vec statement is this one at ecot := .operand "%dz" dz.

                  Equations
                  Instances For
                    theorem Proofs.StableHLO.mlpSublayerVBackGraph_faithfulMH {Np1 hm1 d mlpDim : } (ε : ) (γ2v β2v : Vec ((hm1 + 1) * d)) ( : 0 < ε) (Wfc1 : Mat ((hm1 + 1) * d) mlpDim) (bfc1 : Vec mlpDim) (Wfc2 : Mat mlpDim ((hm1 + 1) * d)) (bfc2 : Vec ((hm1 + 1) * d)) (h dz : Mat Np1 ((hm1 + 1) * d)) (ecot : SHlo (Np1 * ((hm1 + 1) * d))) (hecot : den ecot = dz.flatten) :
                    den (mlpSublayerVBackGraph ε γ2v Wfc1 bfc1 Wfc2 h.flatten (fun (r : Fin Np1) => layerNormVec ((hm1 + 1) * d) ε γ2v β2v (h r)) ecot) = ((transformerMlpSublayerV_has_vjp_mat Np1 (hm1 + 1) d mlpDim ε γ2v β2v Wfc1 bfc1 Wfc2 bfc2).backward h dz).flatten

                    Vec-LN MLP sublayer backward-graph faithfulness (Stage 2 capstone), at general (hm1+1)*d. Denotes the proven transformerMlpSublayerV_has_vjp_mat backward.

                    noncomputable def Proofs.StableHLO.attnSublayerVInnerBackGraphMH {Np1 hm1 d : } (ε : ) (γ1v : Vec ((hm1 + 1) * d)) (Wq Wk Wv Wo : Mat ((hm1 + 1) * d) ((hm1 + 1) * d)) (bq bk bv _bo : Vec ((hm1 + 1) * d)) (x : Vec (Np1 * ((hm1 + 1) * d))) (X : Mat Np1 ((hm1 + 1) * d)) (e : SHlo (Np1 * ((hm1 + 1) * d))) :
                    SHlo (Np1 * ((hm1 + 1) * d))

                    The vec-LN attn-sublayer non-trivial arm (mhsa ∘ LNᵥ₁), multi-head. REUSES mhsaBackGraphMH verbatim, after the vector-LN back fragment lnRowBack(γ=1) ∘ rowScaleF γ1v.

                    Equations
                    • One or more equations did not get rendered due to their size.
                    Instances For
                      theorem Proofs.StableHLO.attnSublayerVInnerBackGraphMH_faithful {Np1 hm1 d : } (ε : ) (γ1v β1v : Vec ((hm1 + 1) * d)) ( : 0 < ε) (Wq Wk Wv Wo : Mat ((hm1 + 1) * d) ((hm1 + 1) * d)) (bq bk bv bo : Vec ((hm1 + 1) * d)) (x dh : Mat Np1 ((hm1 + 1) * d)) (ecot : SHlo (Np1 * ((hm1 + 1) * d))) (hecot : den ecot = dh.flatten) :
                      den (attnSublayerVInnerBackGraphMH ε γ1v Wq Wk Wv Wo bq bk bv bo x.flatten (fun (r : Fin Np1) => layerNormVec ((hm1 + 1) * d) ε γ1v β1v (x r)) ecot) = ((layerNormVec_per_token_has_vjp_mat Np1 ((hm1 + 1) * d) ε γ1v β1v ).backward x ((mhsa_has_vjp_mat Np1 (hm1 + 1) d Wq Wk Wv Wo bq bk bv bo).backward (fun (r : Fin Np1) => layerNormVec ((hm1 + 1) * d) ε γ1v β1v (x r)) dh)).flatten
                      noncomputable def Proofs.StableHLO.attnSublayerVBackGraphMH {Np1 hm1 d : } (ε : ) (γ1v : Vec ((hm1 + 1) * d)) (Wq Wk Wv Wo : Mat ((hm1 + 1) * d) ((hm1 + 1) * d)) (bq bk bv bo : Vec ((hm1 + 1) * d)) (x : Vec (Np1 * ((hm1 + 1) * d))) (X : Mat Np1 ((hm1 + 1) * d)) (ecot : SHlo (Np1 * ((hm1 + 1) * d))) :
                      SHlo (Np1 * ((hm1 + 1) * d))

                      The whole vec-LN attention sublayer backward graph (inner arm + identity skip), over an incoming-cotangent SUBGRAPH ecot (the old dh : Vec statement is this one at ecot := .operand "%dh" dh).

                      Equations
                      Instances For
                        theorem Proofs.transformerAttnSublayerV_backward_decomp {h N dh : } (ε : ) ( : 0 < ε) (γ1 β1 : Vec (h * dh)) (Wq Wk Wv Wo : Mat (h * dh) (h * dh)) (bq bk bv bo : Vec (h * dh)) (A dY : Mat N (h * dh)) :
                        (transformerAttnSublayerV_has_vjp_mat N h dh ε γ1 β1 Wq Wk Wv Wo bq bk bv bo).backward A dY = fun (i : Fin N) (j : Fin (h * dh)) => dY i j + (layerNormVec_per_token_has_vjp_mat N (h * dh) ε γ1 β1 ).backward A ((mhsa_has_vjp_mat N h dh Wq Wk Wv Wo bq bk bv bo).backward (fun (n : Fin N) => layerNormVec (h * dh) ε γ1 β1 (A n)) dY) i j

                        The vector-LN attention sublayer's VJP backward decomposes (biPathMat unfold, rfl): the residual skip passes the cotangent through, and the non-trivial arm is LNᵥ₁-back ∘ mhsa-back at the saved LNᵥ₁ output.

                        theorem Proofs.StableHLO.attnSublayerVBackGraphMH_faithful {Np1 hm1 d : } (ε : ) (γ1v β1v : Vec ((hm1 + 1) * d)) ( : 0 < ε) (Wq Wk Wv Wo : Mat ((hm1 + 1) * d) ((hm1 + 1) * d)) (bq bk bv bo : Vec ((hm1 + 1) * d)) (x dh : Mat Np1 ((hm1 + 1) * d)) (ecot : SHlo (Np1 * ((hm1 + 1) * d))) (hecot : den ecot = dh.flatten) :
                        den (attnSublayerVBackGraphMH ε γ1v Wq Wk Wv Wo bq bk bv bo x.flatten (fun (r : Fin Np1) => layerNormVec ((hm1 + 1) * d) ε γ1v β1v (x r)) ecot) = ((transformerAttnSublayerV_has_vjp_mat Np1 (hm1 + 1) d ε γ1v β1v Wq Wk Wv Wo bq bk bv bo).backward x dh).flatten

                        Vec-LN attention sublayer backward-graph faithfulness (Stage 3 capstone, MH).

                        noncomputable def Proofs.StableHLO.transformerBlockVBackGraphMH {Np1 hm1 d mlpDim : } (ε : ) (γ1v β1v γ2v β2v : Vec ((hm1 + 1) * d)) (Wq Wk Wv Wo : Mat ((hm1 + 1) * d) ((hm1 + 1) * d)) (bq bk bv bo : Vec ((hm1 + 1) * d)) (Wfc1 : Mat ((hm1 + 1) * d) mlpDim) (bfc1 : Vec mlpDim) (Wfc2 : Mat mlpDim ((hm1 + 1) * d)) (A h : Mat Np1 ((hm1 + 1) * d)) (ecot : SHlo (Np1 * ((hm1 + 1) * d))) :
                        SHlo (Np1 * ((hm1 + 1) * d))

                        The whole vec-LN transformer-block backward graph (multi-head). transformerBlockV = mlpSublayerV ∘ attnSublayerV, so block.backward A dY = attn.backward A (mlp.backward (attn A) dY). Saved: A (block input), h = attnSublayerV A.

                        ⭐ The MLP sublayer's graph is now fed to the attention sublayer as a subgraph, not as den (…) re-wrapped as an operand: the two sublayers compose symbolically, and the block itself takes a cotangent subgraph so it can sit downstream of the next block. This is what makes the depth-k tower a real composite term.

                        Equations
                        • One or more equations did not get rendered due to their size.
                        Instances For
                          theorem Proofs.transformerBlockV_backward_unfold {h N dh : } (dff : ) (ε : ) ( : 0 < ε) (γ1 β1 γ2 β2 : Vec (h * dh)) (Wq Wk Wv Wo : Mat (h * dh) (h * dh)) (bq bk bv bo : Vec (h * dh)) (Wfc1 : Mat (h * dh) dff) (bfc1 : Vec dff) (Wfc2 : Mat dff (h * dh)) (bfc2 : Vec (h * dh)) (A dz : Mat N (h * dh)) :
                          (transformerBlockV_has_vjp_mat N h dh dff ε γ1 β1 Wq Wk Wv Wo bq bk bv bo γ2 β2 Wfc1 bfc1 Wfc2 bfc2).backward A dz = (transformerAttnSublayerV_has_vjp_mat N h dh ε γ1 β1 Wq Wk Wv Wo bq bk bv bo).backward A ((transformerMlpSublayerV_has_vjp_mat N h dh dff ε γ2 β2 Wfc1 bfc1 Wfc2 bfc2).backward (transformerAttnSublayerV N h dh ε γ1 β1 Wq Wk Wv Wo bq bk bv bo A) dz)

                          The vector-LN block VJP backward unfolds: block.backward A dz = attn.backward A (mlp.backward (attn A) dz). The outer vjpMat_comp's projection, rfl.

                          theorem Proofs.StableHLO.transformerBlockVBackGraphMH_faithful {Np1 hm1 d mlpDim : } (ε : ) (γ1v β1v γ2v β2v : Vec ((hm1 + 1) * d)) ( : 0 < ε) (Wq Wk Wv Wo : Mat ((hm1 + 1) * d) ((hm1 + 1) * d)) (bq bk bv bo : Vec ((hm1 + 1) * d)) (Wfc1 : Mat ((hm1 + 1) * d) mlpDim) (bfc1 : Vec mlpDim) (Wfc2 : Mat mlpDim ((hm1 + 1) * d)) (bfc2 : Vec ((hm1 + 1) * d)) (A dY : Mat Np1 ((hm1 + 1) * d)) (ecot : SHlo (Np1 * ((hm1 + 1) * d))) (hecot : den ecot = dY.flatten) :
                          den (transformerBlockVBackGraphMH ε γ1v β1v γ2v β2v Wq Wk Wv Wo bq bk bv bo Wfc1 bfc1 Wfc2 A (transformerAttnSublayerV Np1 (hm1 + 1) d ε γ1v β1v Wq Wk Wv Wo bq bk bv bo A) ecot) = ((transformerBlockV_has_vjp_mat Np1 (hm1 + 1) d mlpDim ε γ1v β1v Wq Wk Wv Wo bq bk bv bo γ2v β2v Wfc1 bfc1 Wfc2 bfc2).backward A dY).flatten

                          Whole vec-LN transformer-block backward-graph faithfulness (Stage 4 capstone, MH). The production-parity capstone — multi-head (heads = hm1+1) + vector-LN, matching the committed verified_mlir/vit_train_step.mlir ViT-Tiny config. Wires the vec-LN MLP-sublayer backward (at the saved attn-sublayer output h = attnSublayerV A) into the vec-LN attention-sublayer backward (at the saved block input A), per block.backward A dY = attn.backward A (mlp.backward (attn A) dY).

                          The whole-net vitForwardKV_has_vjp (ViTDepthK.lean) is a Vec → Vec HasVJP built by three vjp_comp steps:

                          classifier_flat ∘ [finalLN] ∘ vitBodyKVFlat(k) ∘ patchEmbed_flat
                          

                          so its .backward x dy chains the four stages in REVERSE (head first, image last):

                          PE.back x (BODY.back (PE x) (LNF.back (BODY (PE x)) (classifier.back (… ) dy)))
                          

                          We mirror this with a backward graph over the ch10 backward tokens. The blocks live in HasVJPMat and are bridged to HasVJP by hasVJPMat_to_hasVJP, so each block-back faithfulness statement is stated through Mat.flatten/Mat.unflatten (exactly the transformerBlockVBackGraphMH_faithful convention). Four stages:

                          noncomputable def Proofs.StableHLO.classifierBackGraph (N D nClasses : ) (Wcls : Mat D nClasses) (ecot : SHlo nClasses) :
                          SHlo ((N + 1) * D)

                          The classifier-head backward graph: clsPadF (dotOut Wcls (%dy)). The dotOut Wcls is the dense head's input-VJP (Mat.mulVec Wcls), scattered by clsPadF into row 0 of a zero [N+1,D] (the CLS-slice's input-VJP).

                          Equations
                          Instances For
                            theorem Proofs.StableHLO.classifierBackGraph_faithful (N D nClasses : ) (Wcls : Mat D nClasses) (bcls : Vec nClasses) (v : Vec ((N + 1) * D)) (ecot : SHlo nClasses) :
                            den (classifierBackGraph N D nClasses Wcls ecot) = (classifier_flat_has_vjp N D nClasses Wcls bcls).backward v (den ecot)

                            Classifier backward-graph faithfulness (Stage 1). Denotes the proven classifier_flat_has_vjp.backward at any input v (dense + CLS-slice are both linear, so the saved activation is irrelevant).

                            ⭐ Over a cotangent SUBGRAPH, like patchEmbedBackGraph_faithful at the other end of the net — the head is the LAST layer of the forward and therefore the FIRST of the backward, so this is the one place where a Vec cotangent was genuinely natural. Generalizing it anyway is what lets the head be a CertLayer and the whole net be one comp chain.

                            noncomputable def Proofs.StableHLO.finalLNBackGraph (N D : ) (ε : ) (γF : Vec D) (X : Vec ((N + 1) * D)) (ecot : SHlo ((N + 1) * D)) :
                            SHlo ((N + 1) * D)

                            The final (pre-head) vector-LN backward graph over (N+1) tokens. REUSES the vec-LN LN-back fragment (lnRowBack(γ=1) ∘ rowScaleF γF). The bias backward (identity) drops out; X is the saved pre-LN input (the body output).

                            This used to bundle the classifier back inside it — it took dy : Vec nClasses and called classifierBackGraph itself, so the final LN and the head were one indivisible thing. They are now separate graphs composed at the call site, which is what lets each be its own CertLayer. Bundling two stages into one node is the same mistake as wrapping a cotangent as an operand: it works exactly until something needs to sit between them.

                            Equations
                            Instances For
                              theorem Proofs.StableHLO.finalLNBackGraph_faithful (N D : ) (ε : ) (γF βF : Vec D) ( : 0 < ε) (X : Mat (N + 1) D) (ecot : SHlo ((N + 1) * D)) :
                              den (finalLNBackGraph N D ε γF X.flatten ecot) = ((layerNormVec_per_token_has_vjp_mat (N + 1) D ε γF βF ).backward X (Mat.unflatten (den ecot))).flatten

                              Final vec-LN backward-graph faithfulness (Stage 2). Denotes the bridged per-token vec-LN VJP back of whatever cotangent subgraph it is fed, at the saved body output X.

                              noncomputable def Proofs.StableHLO.transformerBlockVBackGraphMHP {Np1 hm1 d mlpDim : } (ε : ) (p : BlockParamsV ((hm1 + 1) * d) mlpDim) (A : Mat Np1 ((hm1 + 1) * d)) (ecot : SHlo (Np1 * ((hm1 + 1) * d))) :
                              SHlo (Np1 * ((hm1 + 1) * d))

                              transformerBlockVBackGraphMH at a bundled BlockParamsV block (the backward analogue of vitBlockGraphMHVP). Saved: the block input A and its attn-sublayer output h = attnSublayerV A.

                              Equations
                              • One or more equations did not get rendered due to their size.
                              Instances For
                                noncomputable def Proofs.StableHLO.transformerBlockV_has_vjp_matP {N hm1 d mlpDim : } (ε : ) ( : 0 < ε) (p : BlockParamsV ((hm1 + 1) * d) mlpDim) :
                                HasVJPMat (blockV N (hm1 + 1) d mlpDim ε p)

                                Bundled per-block backward faithfulness. The block back graph at a bundled BlockParamsV block (saved input A, cotangent dY) denotes the flatten of the proven blockV's VJP backward — transformerBlockV_has_vjp_mat.backward, spelled ONCE here over a generic p (so the depth-k induction never re-spells the 16-field tuple). The block VJP is bundled as transformerBlockV_has_vjp_matP.

                                Equations
                                • One or more equations did not get rendered due to their size.
                                Instances For
                                  theorem Proofs.StableHLO.transformerBlockVBackGraphMHP_faithful {Np1 hm1 d mlpDim : } (ε : ) ( : 0 < ε) (p : BlockParamsV ((hm1 + 1) * d) mlpDim) (A dY : Mat Np1 ((hm1 + 1) * d)) (ecot : SHlo (Np1 * ((hm1 + 1) * d))) (hecot : den ecot = dY.flatten) :
                                  noncomputable def Proofs.StableHLO.vitBodyBackGraphKMHV {Np1 hm1 d mlpDim : } (ε : ) (k : ) :
                                  (Fin kBlockParamsV ((hm1 + 1) * d) mlpDim)Mat Np1 ((hm1 + 1) * d)SHlo (Np1 * ((hm1 + 1) * d))SHlo (Np1 * ((hm1 + 1) * d))

                                  Depth-k tower backward graph — the REVERSE fold of transformerBlockVBackGraphMHP. The forward body runs block 0 first (vitBodyKV (k+1) ps = vitBodyKV k (ps∘succ) ∘ blockV (ps 0)), so the backward runs block 0 LAST: the incoming cotangent flows through the tail (blocks 1..k, at the post-block-0 activation blockV (ps 0) A), then through block 0 (at the saved block input A). Mirrors vitBodyKVFlat_has_vjp's vjp_comp chain.

                                  Equations
                                  Instances For
                                    noncomputable def Proofs.StableHLO.patchEmbedBackGraph (ic H W P N D : ) (Wc : Kernel4 D ic P P) (e : SHlo ((N + 1) * D)) :
                                    SHlo (ic * H * W)

                                    The patch-embedding input-backward graph: the patchEmbedBack token (the strided-patchify conv's input-VJP) on the patch-embed-output cotangent.

                                    Equations
                                    Instances For
                                      theorem Proofs.StableHLO.patchEmbedBackGraph_faithful (ic H W P N D : ) (Wc : Kernel4 D ic P P) (bc cls : Vec D) (pos : Mat (N + 1) D) (img : Vec (ic * H * W)) (e : SHlo ((N + 1) * D)) :
                                      den (patchEmbedBackGraph ic H W P N D Wc e) = (patchEmbed_flat_has_vjp ic H W P N D Wc bc cls pos).backward img (den e)

                                      patchEmbed input-backward-graph faithfulness (Stage 4). Denotes the proven patchEmbed_flat_has_vjp.backward at any saved image img (linear — the activation is irrelevant).

                                      noncomputable def Proofs.StableHLO.vitNetBackGraph (ic H W patchSize N mlpDim hm1 d nClasses k : ) (ε : ) (Wc : Kernel4 ((hm1 + 1) * d) ic patchSize patchSize) (ps : Fin kBlockParamsV ((hm1 + 1) * d) mlpDim) (γF : Vec ((hm1 + 1) * d)) (Wcls : Mat ((hm1 + 1) * d) nClasses) (embOut bodyOut : Mat (N + 1) ((hm1 + 1) * d)) (ecot : SHlo nClasses) :
                                      SHlo (ic * H * W)

                                      Whole-net depth-k multi-head vector-LN ViT backward graph. Mirrors the forward vitFwdGraphKMHV in REVERSE: classifier-back → final-vec-LN-back → depth-k tower-back (reverse fold) → patchEmbed-back. Each stage is fed the saved forward activation it differentiates at:

                                      • xin — the saved image (input to patchEmbed; patchEmbed-back is linear).
                                      • bodyOut — the saved body output (input to the final LN).
                                      • the tower-back fold threads each block's saved input internally from the patchEmbed output embOut (= the body input).
                                      Equations
                                      • One or more equations did not get rendered due to their size.
                                      Instances For