Documentation

LeanMlir.Proofs.Nets.MobileNet.MobileNetV4BackB0

MobileNetV4 — the batched UIB backward, and the four families as ONE chain #

MNv4 was the last net with no backward of any kind (planning/archive/mnv4_verified.md §8): the strongest empirical evidence in the repo — forward tied at 1.423e-06, gradient at 0/147 — and nothing in Lean beyond the render. This file is its phase 1–3, and the fold falls out with it.

⭐⭐ THE ANSWER TO §8's OPEN QUESTION: the four families COLLAPSE #

§8 asked whether MNv4's four block families — ExtraDW / IB / ConvNeXt-like / FFN — "collapse to one parameterised theorem or need a case split", and called it "the difference between a small file and a large one". They collapse, and the mechanism is CertLayer.id'.

The UIB body is preDW? → expand → postDW? → project, and k = 0 omits a depthwise. Crucially both depthwise positions are channel- and shape-preservingpreDW : ic → ic, postDW : mid → mid — so an absent one is not a different composition, it is the identity layer in the same slot:

familyprepostas a chain
ExtraDWchain [preDW, expand, postDW, project]
ConvNeXt-likechain [preDW, expand, id', project]
IB / MBConvchain [id', expand, postDW, project]
FFNchain [id', expand, id', project]

⭐ One mnv4UibBody takes the two depthwise slots as CertLayer arguments; the caller passes id' where the table says k = 0. No case split, no four proofs — and no dispatch that could silently disagree with the forward's, which is §3's trap ("a wrong k = 0 dispatch is silent… produces a valid net that trains and descends and is not MobileNetV4").

⚠ This is exactly the §6 claim — "a family from one constructor" — landing on the proof side, the way §3i records it landing on the backward render.

What was genuinely new: a depthwise-bn-RELU stage #

Measured before building: the repo had batched depthwise stages at relu6 (dwbrB, MobileNetV2) and at swish (dwbsB, EfficientNet), and none at plain relu. MNv4 is relu throughout its 21 UIB blocks (⚠ not relu6 — MobileNetV4RenderB flags this explicitly, and mnv2 sitting one file over makes it an easy thing to get wrong).

⭐ It cost almost nothing, because bnReluStage_has_vjp_at (ResNet34BackB0) is generic in the op: it takes any differentiable op with a HasVJP and builds relu ∘ bnBatchLA ∘ batchMap op. cbReluB is that at flatConv; dwbReluB is the same lemma at depthwiseFlat. Zero new analytic content — one instantiation, plus the backward graph's .selectPos (relu's one-sided mask) where mnv2's uses .selectMid.

Scope #

⚠⚠ This paragraph was WRONG from the day it was written, and a planning row copied it. It said the fused stage, the head and the strided body assembly were not built. All three landed on 2026-08-10, the same day, in the three commits that follow the one carrying this header — e25a011 (stride-2 blocks), 61eb512 (fused stage) and 411b1a5, whose own message reads "the head — MNv4 complete at stage level". Nobody came back to the header, so for four weeks the file asserted a gap its own commit log had already closed, and proofs_tier_to_paper_nets.md §3.6 priced a session against it (planning/archive/mnv4_proofs_tier.md §0 — seventh instance of that pattern, and the cheapest: the declaration list was one grep away). ▶ When a session lands a piece, edit the header that said it was missing, in the same commit.

Built here — everything at the BLOCK and STAGE level, which is this file's whole remit: the two depthwise-relu stages (stride-1 + strided) and their backward graphs; the four stage CertLayers; the family-collapsing body and the skip block; the stride-2 form (mnv4UibPreStridedBody; Conv-M has no post-strided row); the fused stage (swish, stage 0) with stemBackBatchedGraph — the symmetric-padding strided conv-bn-swish backward that closed EfficientNet's stem hole at the same time; the head (mnv4Head, its GAP and dense layers both tying by rfl); the table-driven k = 0 dispatch; and UibParams, the row-typed weight record. Nine of these are in tests/AuditAxioms.lean, 3-axiom clean.

Not built here — the NET level, which is four other files as of 2026-09-07. T1 (the whole-net forward and its input-VJP) is Nets/MobileNet/MobileNetV4FullB.lean + MobileNetV4FullBVJP.lean, T2 (the typed forward graph at mnv4FwdChainB's tokens) is in the first of those, T3 (the tie at the emitted gradient nodes, all 233) is MobileNetV4StepTieB.lean, and T6 (the certified whole-net backward tie) is MobileNetV4WholeBackCertifiedTieB.lean + its float chain. Each of them consumes what is built here, block by block. planning/archive/mnv4_proofs_tier.md is the record; ResNet-50 — which was in exactly this position, block-level only with no per-example legacy — was the file-by-file precedent, closed over 2026-09-06/07.

Two things this file's certificates do NOT give you. (i) The head models ONE conv stage; Conv-M's render has two (%h1W 256→960, then %hW 960→1280), so a whole-net use composes cbReluLayer twice. (ii) The stem is not here and cannot be a CertLayer: no render emits a gradient into %x, so there is no convStridedXlaBackBatched token and hence no backward graph to be faithful to. That is B0's situation exactly, and a net-level forward must compose the stem's VJP by vjp_comp_at rather than by CertLayer.comp.

@[reducible]
noncomputable def Proofs.StableHLO.dwbReluB (N : ) {c h w kH kW : } (W : DepthwiseKernel c kH kW) (b : Vec c) (ε : ) (γ β : Vec c) :
Vec (N * (c * h * w))Vec (N * (c * h * w))

Batched depthwise → bn → relu stage. ⚠ Plain relu, not relu6: MNv4's UIB blocks use relu where MobileNetV2's use relu6, and dwbrB (one file over) is the relu6 one.

Equations
Instances For
    @[reducible]
    noncomputable def Proofs.StableHLO.dwbReluBstrided (N : ) {c h w kH kW : } (W : DepthwiseKernel c kH kW) (b : Vec c) (ε : ) (γ β : Vec c) :
    Vec (N * (c * (2 * h) * (2 * w)))Vec (N * (c * h * w))

    Batched STRIDE-2 depthwise → bn → relu stage — the depthwise that consumes a UIB block's stride.

    Equations
    Instances For
      noncomputable def Proofs.StableHLO.dwbReluB_has_vjp_at (N : ) {c h w kH kW : } (W : DepthwiseKernel c kH kW) (b : Vec c) (ε : ) ( : 0 < ε) (γ β : Vec c) (x : Vec (N * (c * h * w))) (h_smooth : ∀ (k : Fin (N * (c * h * w))), bnBatchLA N c h w ε γ β (batchMap N (depthwiseFlat W b) x) k 0) :
      HasVJPAt (dwbReluB N W b ε γ β) x

      dwbReluB's _at VJP — ⭐ one instantiation of bnReluStage_has_vjp_at at depthwiseFlat. The same lemma cbReluB_has_vjp_at uses at flatConv; nothing analytic is new.

      Equations
      Instances For
        theorem Proofs.StableHLO.dwbReluB_differentiableAt (N : ) {c h w kH kW : } (W : DepthwiseKernel c kH kW) (b : Vec c) (ε : ) ( : 0 < ε) (γ β : Vec c) (x : Vec (N * (c * h * w))) (h_smooth : ∀ (k : Fin (N * (c * h * w))), bnBatchLA N c h w ε γ β (batchMap N (depthwiseFlat W b) x) k 0) :
        DifferentiableAt (dwbReluB N W b ε γ β) x
        noncomputable def Proofs.StableHLO.dwbReluBstrided_has_vjp_at (N : ) {c h w kH kW : } (W : DepthwiseKernel c kH kW) (b : Vec c) (ε : ) ( : 0 < ε) (γ β : Vec c) (x : Vec (N * (c * (2 * h) * (2 * w)))) (h_smooth : ∀ (k : Fin (N * (c * h * w))), bnBatchLA N c h w ε γ β (batchMap N (depthwiseStride2Flat W b) x) k 0) :
        HasVJPAt (dwbReluBstrided N W b ε γ β) x
        Equations
        • One or more equations did not get rendered due to their size.
        Instances For
          theorem Proofs.StableHLO.dwbReluBstrided_differentiableAt (N : ) {c h w kH kW : } (W : DepthwiseKernel c kH kW) (b : Vec c) (ε : ) ( : 0 < ε) (γ β : Vec c) (x : Vec (N * (c * (2 * h) * (2 * w)))) (h_smooth : ∀ (k : Fin (N * (c * h * w))), bnBatchLA N c h w ε γ β (batchMap N (depthwiseStride2Flat W b) x) k 0) :
          noncomputable def Proofs.StableHLO.dwbReluBackBatchedGraph {N c h w kH kW : } (W : DepthwiseKernel c kH kW) (b : Vec c) (ε : ) (γ β : Vec c) (x : Vec (N * (c * h * w))) (e : SHlo (N * (c * h * w))) :
          SHlo (N * (c * h * w))

          dwbReluB's backward graph. ⚠ .selectPos (relu's ONE-sided mask) where dwbrBackBatchedGraph uses .selectMid (relu6's two-sided one) — that token is the whole relu-vs-relu6 difference at the backward, and swapping them is well-typed.

          Equations
          • One or more equations did not get rendered due to their size.
          Instances For
            theorem Proofs.StableHLO.dwbReluBackBatchedGraph_faithful {N c h w kH kW : } (W : DepthwiseKernel c kH kW) (b : Vec c) (ε : ) ( : 0 < ε) (γ β : Vec c) (x : Vec (N * (c * h * w))) (e : SHlo (N * (c * h * w))) (h_smooth : ∀ (k : Fin (N * (c * h * w))), bnBatchLA N c h w ε γ β (batchMap N (depthwiseFlat W b) x) k 0) :
            den (dwbReluBackBatchedGraph W b ε γ β x e) = (dwbReluB_has_vjp_at N W b ε γ β x h_smooth).backward (den e)
            noncomputable def Proofs.StableHLO.dwbReluBstridedBackBatchedGraph {N c h w kH kW : } (W : DepthwiseKernel c kH kW) (b : Vec c) (ε : ) (γ β : Vec c) (x : Vec (N * (c * (2 * h) * (2 * w)))) (e : SHlo (N * (c * h * w))) :
            SHlo (N * (c * (2 * h) * (2 * w)))

            The strided depthwise-relu stage's backward graph.

            Equations
            • One or more equations did not get rendered due to their size.
            Instances For
              theorem Proofs.StableHLO.dwbReluBstridedBackBatchedGraph_faithful {N c h w kH kW : } (W : DepthwiseKernel c kH kW) (b : Vec c) (ε : ) ( : 0 < ε) (γ β : Vec c) (x : Vec (N * (c * (2 * h) * (2 * w)))) (e : SHlo (N * (c * h * w))) (h_smooth : ∀ (k : Fin (N * (c * h * w))), bnBatchLA N c h w ε γ β (batchMap N (depthwiseStride2Flat W b) x) k 0) :
              den (dwbReluBstridedBackBatchedGraph W b ε γ β x e) = (dwbReluBstrided_has_vjp_at N W b ε γ β x h_smooth).backward (den e)
              noncomputable def Proofs.StableHLO.mnv4DWReluLayer (N : ) {c h w kH kW : } (W : DepthwiseKernel c kH kW) (b : Vec c) (ε : ) ( : 0 < ε) (γ β : Vec c) :
              CertLayer (N * (c * h * w)) (N * (c * h * w))

              A depthwise-bn-relu stage as a CertLayer. Used at BOTH UIB depthwise positions — pre (c := ic) and post (c := mid) — because the op is channel-parameterised. ⭐ That single fact is what §2 records as retiring MNv4's one supposedly-new primitive: a leading depthwise is the same constructor at a different channel count.

              Equations
              • One or more equations did not get rendered due to their size.
              Instances For
                noncomputable def Proofs.StableHLO.mnv4UibBody (N : ) {ic mid oc h w : } (preDW : CertLayer (N * (ic * h * w)) (N * (ic * h * w))) (expand : CertLayer (N * (ic * h * w)) (N * (mid * h * w))) (postDW : CertLayer (N * (mid * h * w)) (N * (mid * h * w))) (project : CertLayer (N * (mid * h * w)) (N * (oc * h * w))) :
                CertLayer (N * (ic * h * w)) (N * (oc * h * w))

                ⭐⭐ The UIB body, for ALL FOUR families at once.

                preDW and postDW are CertLayer arguments, so the caller passes mnv4DWReluLayer where the block table has k > 0 and CertLayer.id' where it has k = 0. ExtraDW, IB, ConvNeXt-like and FFN are then four applications of this one definition, not four proofs.

                This is only possible because both depthwise positions are shape-preserving: an absent depthwise leaves the chain's types unchanged, so id' slots in without a case split.

                Equations
                Instances For

                  ⚠⚠ The stride-1 collapse does not extend here, and the reason is the TYPE.

                  At stride 1 an absent depthwise is id' because the slot is shape-preserving. At stride 2 the depthwise that carries the stride maps (2h, 2w) ↦ (h, w) — a different type — so it cannot be replaced by an identity, and which depthwise carries it decides the resolution every later stage runs at. That is not a dispatch detail; it is two genuinely different compositions:

                  formblockswho eats the strideexpand runs at
                  pre-strided1 (48→80), 11 (160→256)the pre-DWh (already reduced)
                  post-strided3 (80→160)the post-DW2h (not yet reduced)

                  ⭐ This mirrors the render exactly — uibFwdPreStridedB / uibFwdPostStridedB are two functions for the same reason (MobileNetV4RenderB: "a stride-polymorphic block cannot typecheck"). The proof side reproducing that split independently is a small piece of evidence that the split is real and not a renderer artifact.

                  ⚠ All three stride-2 blocks change channels (ic ≠ oc), so none has a skip: the block IS the body, with no CertLayer.residual wrapper. Adding one would not typecheck, which is the good case.

                  noncomputable def Proofs.StableHLO.mnv4DWReluStridedLayer (N : ) {c h w kH kW : } (W : DepthwiseKernel c kH kW) (b : Vec c) (ε : ) ( : 0 < ε) (γ β : Vec c) :
                  CertLayer (N * (c * (2 * h) * (2 * w))) (N * (c * h * w))

                  The STRIDE-2 depthwise-bn-relu stage as a CertLayer — the depthwise that carries a UIB block's stride. Not an endomorphism (that is the whole point), so it composes via comp.

                  Equations
                  • One or more equations did not get rendered due to their size.
                  Instances For
                    noncomputable def Proofs.StableHLO.mnv4UibPreStridedBody (N : ) {ic mid oc h w : } (preDW : CertLayer (N * (ic * (2 * h) * (2 * w))) (N * (ic * h * w))) (expand : CertLayer (N * (ic * h * w)) (N * (mid * h * w))) (postDW : CertLayer (N * (mid * h * w)) (N * (mid * h * w))) (project : CertLayer (N * (mid * h * w)) (N * (oc * h * w))) :
                    CertLayer (N * (ic * (2 * h) * (2 * w))) (N * (oc * h * w))

                    Pre-strided UIB body — MNv4 blocks 1 and 11. The pre-DW carries the stride, so everything downstream of it runs at the REDUCED resolution h.

                    postDW is still a slot: blocks 1 and 11 both have postDWk > 0, but passing id' here is well-typed and expresses a pre-strided ConvNeXt-family block, so the collapse still applies to the stride-1 slot even though it cannot apply to the strided one.

                    Equations
                    Instances For

                      MNv4's stage 0 is .fusedMbConv 32 48 4 3 2 1 false: a regular k×k conv (not a depthwise) doing expansion and downsampling at once, then a 1×1 project. 32 → mid = 32·4 = 128 → 48, stride 2, and ⚠ swish, not relu — a deliberate paper deviation that both emitters behind the 84.58% share (§1b).

                      ⭐ Swish is smooth, so this whole stage is the globally-certified kind: ok = True, no smoothness side conditions, and the VJPs are global HasVJPs rather than _at. That makes stage 0 the cheapest part of MNv4's backward despite being the part §1b records as missed by the original scoping.

                      ⭐⭐ The forward stage is fusedConvB, EfficientNet's stemB shape at SYMMETRIC padding. Until 2026-09-05 the two nets shared stemB (EfficientNetRenderPC) outright. B0's stem then moved to the XLA-SAME phase (flatConvStride2Xla, the TF-origin convention its render has shipped since 2026-08-08), while MNv4's fused 3×3/s2 stays symmetric — the reference's fused_ib passes an explicit (p,p) tuple and scripts/convention_audit.py reads the render at sym there — so the stage gets its own name with the same bnSwishStage_* lemmas. What was missing repo-wide was the backward graph: stemBackBatchedGraph below, at the symmetric convStridedBackBatched. ⚠ It serves MNv4's fused stage only; B0's XLA stem has no batched input-VJP token (no render emits a gradient into the image), so B0's stem stays un-graph-certified — recorded in planning/archive/proofs_tier_to_paper_nets.md.

                      noncomputable def Proofs.StableHLO.fusedConvB (N : ) {ic oc h w kH kW : } (W : Kernel4 oc ic kH kW) (b : Vec oc) (ε : ) (γ β : Vec oc) :
                      Vec (N * (ic * (2 * h) * (2 * w)))Vec (N * (oc * h * w))

                      MNv4's fused stage forward: symmetric strided k×k conv → bn → swish.

                      Equations
                      Instances For
                        theorem Proofs.StableHLO.fusedConvB_differentiable (N : ) {ic oc h w kH kW : } (W : Kernel4 oc ic kH kW) (b : Vec oc) (ε : ) ( : 0 < ε) (γ β : Vec oc) :
                        Differentiable (fusedConvB N W b ε γ β)
                        noncomputable def Proofs.StableHLO.fusedConvB_has_vjp (N : ) {ic oc h w kH kW : } (W : Kernel4 oc ic kH kW) (b : Vec oc) (ε : ) ( : 0 < ε) (γ β : Vec oc) :
                        HasVJP (fusedConvB N W b ε γ β)
                        Equations
                        Instances For
                          noncomputable def Proofs.StableHLO.stemBackBatchedGraph {N ic oc h w kH kW : } (W : Kernel4 oc ic kH kW) (b : Vec oc) (ε : ) (γ β : Vec oc) (x : Vec (N * (ic * (2 * h) * (2 * w)))) (e : SHlo (N * (oc * h * w))) :
                          SHlo (N * (ic * (2 * h) * (2 * w)))

                          Batched strided conv → bn → swish backward graph — the cbsBackBatchedGraph sibling with convStridedBackBatched for convBackBatched, at symmetric padding: MNv4's fused stage.

                          Equations
                          • One or more equations did not get rendered due to their size.
                          Instances For
                            theorem Proofs.StableHLO.stemBackBatchedGraph_faithful {N ic oc h w kH kW : } (W : Kernel4 oc ic kH kW) (b : Vec oc) (ε : ) ( : 0 < ε) (γ β : Vec oc) (x : Vec (N * (ic * (2 * h) * (2 * w)))) (e : SHlo (N * (oc * h * w))) :
                            den (stemBackBatchedGraph W b ε γ β x e) = (fusedConvB_has_vjp N W b ε γ β).backward x (den e)
                            noncomputable def Proofs.StableHLO.mnv4FusedConvLayer (N : ) {ic mid h w kH kW : } (W : Kernel4 mid ic kH kW) (b : Vec mid) (ε : ) ( : 0 < ε) (γ β : Vec mid) :
                            CertLayer (N * (ic * (2 * h) * (2 * w))) (N * (mid * h * w))

                            The fused stage's k×k strided conv → bn → swish as a CertLayer. ⚠ Globally certified (ok = True) — swish has no kink, so unlike every UIB stage this one carries no hypothesis.

                            Equations
                            • One or more equations did not get rendered due to their size.
                            Instances For
                              noncomputable def Proofs.StableHLO.mnv4FusedStage (N : ) {ic mid oc h w : } (fusedConv : CertLayer (N * (ic * (2 * h) * (2 * w))) (N * (mid * h * w))) (project : CertLayer (N * (mid * h * w)) (N * (oc * h * w))) :
                              CertLayer (N * (ic * (2 * h) * (2 * w))) (N * (oc * h * w))

                              MNv4's fused stage (stage 0) — the strided k×k conv-bn-swish, then the 1×1 project. No skip: ic = 32 ≠ 48 = oc and stride 2, so the stage IS the body.

                              Equations
                              Instances For

                                MNv4's head is 1×1 conv (256 → 1280) → BN → relu → GAP(7×7) → dense. The conv stage is cbReluLayer again (conv-bn-relu is conv-bn-relu, and the kernel extent is a binder), so only GAP and the classifier are new.

                                Both tie by rfl. den of .gapBackBatched is definitionally the row-wise GAP VJP, and den of .denseRowBack is rowDenseBackFlat — which is what batchMap_has_vjp reduces to. The batchMap_has_vjp route goes through a transported equality (batchMap_eq_rowwiseFlat ▸ …), so this was worth probing rather than assuming; it discharges definitionally.

                                GAP's VJP is input-independent and den .gapBackBatched exploits that — it evaluates the backward at the point fun _ => 0. That is sound because GAP is linear, and it is why the tie holds for any x. A stage whose VJP did depend on its input could not be rendered this way.

                                noncomputable def Proofs.StableHLO.mnv4GapLayer (N : ) {c h w : } :
                                CertLayer (N * (c * h * w)) (N * c)

                                Batched global average pool as a CertLayer. Globally certified — GAP is linear.

                                Equations
                                • One or more equations did not get rendered due to their size.
                                Instances For
                                  theorem Proofs.StableHLO.mnv4GapLayer_fwd_apply (N : ) {c h w : } (v : Vec (N * (c * h * w))) :

                                  The GAP layer's forward is the batched global average pool.

                                  noncomputable def Proofs.StableHLO.mnv4DenseLayer (N : ) {a nC : } (W : Mat a nC) (b : Vec nC) :
                                  CertLayer (N * a) (N * nC)

                                  Batched dense classifier as a CertLayer. Globally certified — dense is affine.

                                  Equations
                                  • One or more equations did not get rendered due to their size.
                                  Instances For
                                    theorem Proofs.StableHLO.mnv4DenseLayer_fwd_apply (N : ) {a nC : } (W : Mat a nC) (b : Vec nC) (v : Vec (N * a)) :
                                    (mnv4DenseLayer N W b).fwd v = batchMap N (dense W b) v

                                    The classifier layer's forward is the batched dense.

                                    noncomputable def Proofs.StableHLO.mnv4Head (N : ) {c oc h w nC : } (headConv : CertLayer (N * (c * h * w)) (N * (oc * h * w))) (gap : CertLayer (N * (oc * h * w)) (N * oc)) (cls : CertLayer (N * oc) (N * nC)) :
                                    CertLayer (N * (c * h * w)) (N * nC)

                                    MNv4's head: the 1×1 conv-bn-relu, then GAP, then the classifier.

                                    ⚠ Only the conv stage carries a smoothness condition (its relu); GAP and dense are global. So (mnv4Head …).ok reduces to the head conv's relu condition alone.

                                    Equations
                                    Instances For

                                      What this section fixes. Above, mnv4UibBody takes its depthwise slots as arguments, so passing id' where block 4's real pre-DW belongs is well-typed and still certified — graph and VJP both move with the caller's arguments, so the theorem stays true about the wrong net. Types catch the stride split (resolution is in the type); they catch nothing about k = 0 vs k > 0, because that slot is shape-preserving — the very property that made the collapse possible. That is §3's trap, one level up from the render.

                                      ⭐ The fix is to make the slot a function of the block table's k, so the proof side runs the same k = 0 dispatch the render does, off the same mnv4Blocks list — one table, not two readings. mnv4-fwd-smoke already pins the render against that table; these #guards pin the table's own shape, so a bad edit fails at lake env lean rather than becoming a silent net.

                                      noncomputable def Proofs.StableHLO.mnv4PreDWSlot (N : ) {c h w kH kW : } (preDWk : ) (W : DepthwiseKernel c kH kW) (b : Vec c) (ε : ) ( : 0 < ε) (γ β : Vec c) :
                                      CertLayer (N * (c * h * w)) (N * (c * h * w))

                                      The pre-depthwise slot, dispatched on the table's preDWk. ⭐ k = 0id' — the same rule uibFwdSkipB emits, computed rather than chosen.

                                      Equations
                                      Instances For
                                        noncomputable def Proofs.StableHLO.mnv4PostDWSlot (N : ) {c h w kH kW : } (postDWk : ) (W : DepthwiseKernel c kH kW) (b : Vec c) (ε : ) ( : 0 < ε) (γ β : Vec c) :
                                        CertLayer (N * (c * h * w)) (N * (c * h * w))

                                        The post-depthwise slot, same dispatch on postDWk.

                                        Equations
                                        Instances For

                                          The four families, named — read off the two kernel slots by exactly the rule the slots dispatch on and the render emits.

                                          Instances For
                                            @[instance_reducible]
                                            Equations
                                            Equations
                                            • One or more equations did not get rendered due to their size.
                                            Instances For

                                              Which family a table row denotes.

                                              Equations
                                              • One or more equations did not get rendered due to their size.
                                              Instances For

                                                The gap this closes. A block builder that reads the dispatch from the table but takes its weights as separate arguments lets a caller pair row 4's ks with row 7's widths. The dispatch was table-driven; the wiring was not.

                                                Fix: index the parameter record by the row. Every width in UibParams s is a projection of ss.ic, s.oc, s.ic * s.expand, s.preDWk, s.postDWk. A record with widths that disagree with its row cannot be constructed, so the block builder needs no side conditions and no #guard: it is impossible by typing rather than checked after the fact.

                                                What this still does not pin, stated precisely so the next reader does not overclaim: rows 4, 5 and 10 are all 160 → 160, expand 4, and 4/10 share k = 3,3. Their records are therefore the same type, so swapping those two blocks' weights typechecks. Typing pins shape (channels, expand ratio, kernel extents, resolution); it cannot pin identity between rows that are shape-identical. Closing that needs the weights to come from one indexed array — a renderer concern, since the render already folds mnv4Blocks in order.

                                                One UIB block's parameters, typed by its table row. Every width is a projection of s, so a record whose widths disagree with the row is not constructible. Bias-free convs still carry a b because the stage vocabulary takes one; the render binds it to %zb{c}.

                                                Instances For
                                                  noncomputable def Proofs.StableHLO.mnv4BodyOfRow (N : ) (s : UibSpec) (p : UibParams s) :
                                                  CertLayer (N * (s.ic * s.h * s.h)) (N * (s.oc * s.h * s.h))

                                                  ⭐⭐ A UIB body built ENTIRELY from its table row. Dispatch from s.preDWk/s.postDWk, widths and resolution from s, weights from a record that cannot disagree with s. Nothing here is a free argument: given s, the only freedom left is the numeric values.

                                                  ⚠ This is the BODY (ic -> oc). The identity skip is CertLayer.residual on top and needs oc = ic, which holds for exactly the eighteen non-stride2 rows (guarded below) — applied by the caller at a concrete row, where it is rfl and needs no transport.

                                                  Equations
                                                  • One or more equations did not get rendered due to their size.
                                                  Instances For
                                                    noncomputable def Proofs.StableHLO.mnv4PreStridedBodyOfRow (N : ) (s : UibSpec) (p : UibParams s) :
                                                    CertLayer (N * (s.ic * (2 * s.h) * (2 * s.h))) (N * (s.oc * s.h * s.h))

                                                    A PRE-STRIDED body built entirely from its table rowmnv4BodyOfRow's sibling for the three stride-2 rows (1, 3, 11), and the row-typed section's third member.

                                                    ⚠ The pre-DW is NOT a slot here: it carries the stride, so it maps (2h, 2w) ↦ (h, w) and cannot be id' — that is the whole reason the collapse stops at stride 2. The POST-DW still is a slot, dispatched on s.postDWk off the same table row, even though all three Conv-M rows happen to fill it.

                                                    ⛔ There is deliberately no mnv4PostStridedBodyOfRow: Conv-M has no post-strided row (Conv-S had one), so a row-typed wrapper for that arm would have no possible argument.

                                                    Equations
                                                    • One or more equations did not get rendered due to their size.
                                                    Instances For