MobileNetV4-Conv-M at TRUE BATCH-NORM — the whole net's forward and graph (T1-forward, T2) #
MobileNetV4 was the last net in planning/archive/proofs_tier_to_paper_nets.md §2's table with nothing at
the net level. MobileNetV4BackB0.lean is complete at the BLOCK and STAGE level — every UIB
family, both stride-2 forms, the fused stage, the head, the table-driven k = 0 dispatch and the
row-typed UibParams — and this file is the tier above: a net-level ℝ forward at the 21-row
Conv-M table, and the typed StableHLO graph over it at mnv4FwdChainB's own tokens.
planning/archive/mnv4_proofs_tier.md is the plan; ResNet-50 closed the same two tiers on 2026-09-06 and
ResNet50FullB.lean is the file this one mirrors.
⚠⚠ NO ACCURACY IS QUOTED FOR THIS NET. Conv-M has no Imagenette run and no verified ImageNet
run; historical/RESULTS.md's 84.58% belongs to the SUPERSEDED Conv-S table. What the artifacts under this
tier are pinned to is the reference's function: the forward tie measures max |Δ| = 3.770e-06
against jax/.lake/build/generated_mobilenet_v4.py on shared weights and the gradient tie puts 0
of 232 live parameters outside the reference's own fp32 noise floor (both re-run at the Conv-M
table on 2026-09-07, planning/archive/mnv4_convm_ties_todo.md). That is what makes the tiers below
statements about MobileNetV4 rather than about a net.
⭐⭐ The trunk is FIVE CertLayer groups — and the reason it is not ONE is the finding here #
ResNet-50's T1 needed sixteen r50Pre_k prefix definitions and a hand-written bottom-up have
chain for its apex, because its CertLayer trunk predated the tie files' needs. MNv4 has no such
legacy, so each resolution group — the fused stage, rows 1–2, 3–6, 7–10, 11–15, 16–21, the head —
is assembled with CertLayer.comp and CertLayer.residual directly, and inside a group:
.fwdis that group's forward — no second definition to keep in step;.okis its smoothness hypothesis, conjoined at exactly the right activations bycomprather than written out (~60 relu clauses across the net, none of them written here);.vjpis itsHasVJPAt(MobileNetV4FullBVJP.leanchains seven of them); and.faithfulis its BACKWARD-graph faithfulness, for free.
⛔⛔ But composing the groups into ONE CertLayer does not work, and this cost a day to
establish, so it is recorded rather than re-discovered. fused.comp (res28.comp (… .comp head))
elaborates fine and reads beautifully. Every later statement then has to peel CertLayer.comp to
reach .fwd, and at MNv4's LITERAL resolutions that peel is fatal: (L₁.comp L₂).fwd = L₂.fwd ∘ L₁.fwd is rfl, and discharging it at these instances — by rfl, by
simp only [CertLayer.comp_fwd], inside the T2 capstone or in a standalone lemma — costs ten
minutes of elaboration and then a (kernel) deterministic timeout. Every one of those four
spellings was measured. ⚠ The groups' own five-stage comp chains are completely fine; it is
composing the compositions, under something that can start unfolding den, that is not.
⭐ So the top level is seven named prefixes (mnv4Pre0 … mnv4Pre6) and the forward is their
nest. What it costs is the hypothesis bundle: Mnv4SmoothAt binds one .ok per group, eight
fields rather than two. What it keeps is everything that mattered — R50's apex binds 33, and MNv4
binds no 0 < ε hypothesis at all, because those live inside the weight records.
▶ The general lesson, and it is not MNv4-specific: a net whose resolutions are LITERALS cannot
afford the proof idioms a net with a resolution BINDER can. ResNet-50's q keeps den stuck;
MNv4's 224/112/56/28/14/7 let it run. Three separate blow-ups in this file trace to exactly that —
this one, the graph builders that had to be made generic in their widths, and the whole-net
capstone that had to become rw instead of simp only.
⚠⚠ The stem sits OUTSIDE the chain, and this is EfficientNet-B0's situation exactly.
CertLayer demands a backward graph, and no render emits a gradient into %x — there is no
convStridedXlaBackBatched token, because the artifact's backward ends at the stem conv's WEIGHT
gradient. B0's stem sits outside its chain for the same reason. So mnv4StemB is a
plain function here, its VJP is bnReluStage_has_vjp_at at flatConvStride2Xla, and the net-level
VJP composes the two with vjp_comp_at.
Conventions this net runs at #
| depth | 21 UIB blocks + the fused stage; 13 ExtraDW / 4 ConvNeXt-like / 4 FFN, and no IB |
| ladder | 224 →(stem s2) 112 →(fused s2) 56 →(blk1) 28 →(blk3) 14 →(blk11) 7 → GAP |
| channels | 32 → 48 → 80 → 160 → 256, head 256 → 960 → 1280 |
| BatchNorm | batch (bnBatchLA, reduce [0,2,3], width N·h·w) at all 77 sites |
| activation | relu, not relu6 (MobileNetV2 sits one file over and uses relu6); the fused stage alone is swish |
| padding | ⚠ TWO phases in one net: the stem is XLA-SAME (flatConvStride2Xla), the fused stage and all three strided depthwises are SYMMETRIC. Both correct; scripts/convention_audit.py reads them. Do not tidy one to match the other. |
| stride | all three stride-2 UIB rows (1, 3, 11) are PRE-strided; Conv-M has no post-strided row at all |
| census | 233 parameter slots at nCls = 10 (8,447,322 scalars; 9,715,512 at 1000), bias-free by construction |
| artifacts | mnv4_fwd, mnv4_fwd_eval, mnv4_adam_train_step, and the five mnv4in* ImageNet twins |
⚠ N stays a binder throughout, as at r34/R50: this tier carries no batch numeral. On the
data-parallel artifacts the render's N is the PER-REPLICA batch; since 2026-09-21 their
BatchNorm is synchronised, and MobileNetV4SyncB.lean is this file's twin for them: replica r's
forward graph denotes shard r of mobilenetv4ForwardB_full (R * N), this file's forward at the
global batch. Unlike R50 there is no q binder — MNv4 ships one resolution.
⚠ Rows 4/5/10, 12/18 and 15/19/20 are shape-identical, so their UibParams records have the
same TYPE and swapping their weights typechecks. Typing pins shape, not identity; what pins
identity is the SSA NAMES the T2 graph writes (%u4qW vs %u10qW), which is why the graph reads
its names from s.p off the table rather than taking them as arguments.
✅ Checked against the committed bytes: verified_mlir/mnv4_fwd.mlir's signature is 234
arguments = %x + 233 parameters, and every name this file writes appears there.
⚠ These are abbrevs, and the rows are NAMED rather than indexed. UibParams (mnv4Blocks[3]!)
in a type would force whnf through List.get! at every use; a named reducible constant reduces
to its projections directly, which is what lets CertLayer.comp line up 2 * 28 with 56 across
a stride join without a single transport.
⭐ The #guard below is the whole safety of that move: these 21 constants are pinned to
mnv4Blocks — the ONE table mnv4FwdChainB, the backward, the parameter signature and the BN stat
list all fold over — so a typo here is a build failure rather than a proof about a different net.
Equations
- Proofs.StableHLO.mnv4Row1 = { p := "1", ic := 48, oc := 80, expand := 4, preDWk := 3, postDWk := 5, h := 28, stride2 := true }
Instances For
Equations
- Proofs.StableHLO.mnv4Row2 = { p := "2", ic := 80, oc := 80, expand := 2, preDWk := 3, postDWk := 3, h := 28, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row3 = { p := "3", ic := 80, oc := 160, expand := 6, preDWk := 3, postDWk := 5, h := 14, stride2 := true }
Instances For
Equations
- Proofs.StableHLO.mnv4Row4 = { p := "4", ic := 160, oc := 160, expand := 4, preDWk := 3, postDWk := 3, h := 14, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row5 = { p := "5", ic := 160, oc := 160, expand := 4, preDWk := 3, postDWk := 3, h := 14, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row6 = { p := "6", ic := 160, oc := 160, expand := 4, preDWk := 3, postDWk := 5, h := 14, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row7 = { p := "7", ic := 160, oc := 160, expand := 4, preDWk := 3, postDWk := 3, h := 14, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row8 = { p := "8", ic := 160, oc := 160, expand := 4, preDWk := 3, postDWk := 0, h := 14, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row9 = { p := "9", ic := 160, oc := 160, expand := 2, preDWk := 0, postDWk := 0, h := 14, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row10 = { p := "10", ic := 160, oc := 160, expand := 4, preDWk := 3, postDWk := 0, h := 14, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row11 = { p := "11", ic := 160, oc := 256, expand := 6, preDWk := 5, postDWk := 5, h := 7, stride2 := true }
Instances For
Equations
- Proofs.StableHLO.mnv4Row12 = { p := "12", ic := 256, oc := 256, expand := 4, preDWk := 5, postDWk := 5, h := 7, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row13 = { p := "13", ic := 256, oc := 256, expand := 4, preDWk := 3, postDWk := 5, h := 7, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row14 = { p := "14", ic := 256, oc := 256, expand := 4, preDWk := 3, postDWk := 5, h := 7, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row15 = { p := "15", ic := 256, oc := 256, expand := 4, preDWk := 0, postDWk := 0, h := 7, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row16 = { p := "16", ic := 256, oc := 256, expand := 4, preDWk := 3, postDWk := 0, h := 7, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row17 = { p := "17", ic := 256, oc := 256, expand := 2, preDWk := 3, postDWk := 5, h := 7, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row18 = { p := "18", ic := 256, oc := 256, expand := 4, preDWk := 5, postDWk := 5, h := 7, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row19 = { p := "19", ic := 256, oc := 256, expand := 4, preDWk := 0, postDWk := 0, h := 7, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row20 = { p := "20", ic := 256, oc := 256, expand := 4, preDWk := 0, postDWk := 0, h := 7, stride2 := false }
Instances For
Equations
- Proofs.StableHLO.mnv4Row21 = { p := "21", ic := 256, oc := 256, expand := 2, preDWk := 5, postDWk := 0, h := 7, stride2 := false }
Instances For
Every MobileNetV4-Conv-M parameter, generic in the class count so one statement covers the
10-class Imagenette artifacts and the 1000-class mnv4in ones.
⭐ The 21 block fields are UibParams mnv4Row{k} — a record whose every width is a projection
of its row, so a record that disagrees with its row cannot be constructed and the forward
below needs no side conditions on widths. That is strictly stronger than ResNet-50's
R50IdW/R50ProjW, which are typed by loose {mid oc} binders. ⚠ It still does not pin
IDENTITY between shape-identical rows (4/5/10, 12/18, 15/19/20) — see the header.
⭐ The 0 < ε obligations live INSIDE the records (UibParams's hq he hd hz), so the stem,
the fused stage and the head carry theirs as fields too. R50 keeps a separate R50IdPos
bundle; matching UibParams here means the whole-net VJP binds no epsilon hypotheses at all.
⚠ Every conv is bias-free — both renders bake convBias := false and bind each bias to the
%zb{c} zero the prelude declares — but the records still carry a b slot because the stage
vocabulary takes one. Those fields are ∀-quantified over; bias = 0 is one instance. Field
names are the render's own SSA prefixes, so a reader can match a parameter to its emitted name
without a table.
- sW : Kernel4 32 3 3 3
stem
%sW/%sg/%sbt: 3×3/s2 at the XLA-SAMEphase, 3 → 32, 224 → 112. - sb : Vec 32
- sE : ℝ
- sg : Vec 32
- sbt : Vec 32
- f0cW : Kernel4 128 32 3 3
fused stage
%f0cW: 3×3/s2 symmetric, 32 → 128, 112 → 56, then swish. - f0cb : Vec 128
- f0cE : ℝ
- f0cg : Vec 128
- f0cbt : Vec 128
- f0pW : Kernel4 48 128 1 1
fused stage
%f0pW: the 1×1 project, 128 → 48, no activation. - f0pb : Vec 48
- f0pE : ℝ
- f0pg : Vec 48
- f0pbt : Vec 48
block 1:
%u1*, 48 → 80, expand 4, dw 3/5, at 28×28.block 2:
%u2*, 80 → 80, expand 2, dw 3/3, at 28×28.block 3:
%u3*, 80 → 160, expand 6, dw 3/5, at 14×14.block 4:
%u4*, 160 → 160, expand 4, dw 3/3, at 14×14.block 5:
%u5*, 160 → 160, expand 4, dw 3/3, at 14×14.block 6:
%u6*, 160 → 160, expand 4, dw 3/5, at 14×14.block 7:
%u7*, 160 → 160, expand 4, dw 3/3, at 14×14.block 8:
%u8*, 160 → 160, expand 4, dw 3/0, at 14×14.block 9:
%u9*, 160 → 160, expand 2, dw 0/0, at 14×14.block 10:
%u10*, 160 → 160, expand 4, dw 3/0, at 14×14.block 11:
%u11*, 160 → 256, expand 6, dw 5/5, at 7×7.block 12:
%u12*, 256 → 256, expand 4, dw 5/5, at 7×7.block 13:
%u13*, 256 → 256, expand 4, dw 3/5, at 7×7.block 14:
%u14*, 256 → 256, expand 4, dw 3/5, at 7×7.block 15:
%u15*, 256 → 256, expand 4, dw 0/0, at 7×7.block 16:
%u16*, 256 → 256, expand 4, dw 3/0, at 7×7.block 17:
%u17*, 256 → 256, expand 2, dw 3/5, at 7×7.block 18:
%u18*, 256 → 256, expand 4, dw 5/5, at 7×7.block 19:
%u19*, 256 → 256, expand 4, dw 0/0, at 7×7.block 20:
%u20*, 256 → 256, expand 4, dw 0/0, at 7×7.block 21:
%u21*, 256 → 256, expand 2, dw 5/0, at 7×7.- h1W : Kernel4 960 256 1 1
head conv 1
%h1W: 1×1, 256 → 960, at 7×7. - h1b : Vec 960
- h1E : ℝ
- h1g : Vec 960
- h1bt : Vec 960
- hW : Kernel4 1280 960 1 1
head conv 2
%hW: 1×1, 960 → 1280. ⚠ Conv-M's head has TWO convs;mnv4Headmodels one. - hb : Vec 1280
- hE : ℝ
- hg : Vec 1280
- hbt : Vec 1280
- Wd : Mat 1280 nCls
classifier
%Wd/%bd, after GAP(7×7). - bd : Vec nCls
Instances For
MNv4's stem forward: 3×3/s2 conv at the XLA-SAME phase → batch BN → relu.
⚠⚠ This is the ONE XLA-padded site in the net, and the reason .convStridedXla exists at all:
XLA 'SAME' on a 3×3/s2 at 224 pads (0,1), not (1,1). Both give 112×112, so no shape
check, #guard, op count or arity audit can see the difference — the forward tie is the only
thing that can, and it measured 6.16e-2 with the symmetric token against 1.79e-6 with the
reference patched to match (planning/archive/mnv4_verified.md §3b). Every OTHER stride-2 site in this
net is genuinely symmetric.
⚠ Plain relu, and it is relu6 one file over in MobileNetV2FullB.lean at the same XLA
padding — the two stems differ in exactly one token.
Equations
- Proofs.StableHLO.mnv4StemB N h w Ws bs εs γs βs = Proofs.relu (N * (oc * h * w)) ∘ Proofs.StableHLO.bnBatchLA N oc h w εs γs βs ∘ Proofs.StableHLO.batchMap N (Proofs.flatConvStride2Xla Ws bs)
Instances For
The fused stage (stage 0): 3×3/s2 SYMMETRIC conv-bn-swish 32 → 128 at 112 → 56, then
the 1×1 project 128 → 48. ⭐ The only globally-certified stage in the net — swish has no kink,
so ok = True and this stage discharges nothing.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The head: 1×1 256 → 960 conv-bn-relu, 1×1 960 → 1280 conv-bn-relu, GAP(7×7), classifier.
⚠ mnv4Head models ONE conv stage and Conv-M's render emits two (%h1W then %hW), so
the first is composed on the outside as a second cbReluLayer — conv-bn-relu is
conv-bn-relu and the kernel extent is a binder, so 1×1 is an argument. ⭐ GAP and dense are
both globally certified and both tie by rfl; only the two relus carry a condition.
Equations
- One or more equations did not get rendered due to their size.
Instances For
⚠⚠ The trunk is built in GROUPS, and that is a proof-engineering requirement. One 24-stage
CertLayer elaborates fine — it is the T2 faithfulness proof over it that does not: the whole-net
rewrite chain produces a term whose KERNEL check exceeds any reasonable budget (measured: the
elaboration succeeds after ~9 minutes and the kernel then reports a deterministic timeout). Split
at the net's own resolution boundaries, each group's proof is small, and the whole-net theorem is
six rewrites over them. ⭐ The grouping is the ladder a reader already knows — 56, 28, 14, 7 — so
it costs nothing in readability and buys a bounded proof.
Trunk group Res28 — rows 1–2: the 56→28 reduction and the block that follows it.
Equations
Instances For
Trunk group Res14a — rows 3–6: the 28→14 reduction, then three ExtraDW blocks.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Trunk group Res14b — rows 7–10 at 14×14: ExtraDW, ConvNeXt, FFN, ConvNeXt — three families in four blocks.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Trunk group Res7a — rows 11–15: the last reduction (14→7), then four blocks at 7×7.
Equations
- One or more equations did not get rendered due to their size.
Instances For
⛔⛔ The seven groups are composed by a PREFIX CHAIN, not by one more CertLayer.comp, and
this is the single hardest thing this file learned.
A mnv4NetLayer := fused.comp (res28.comp (… .comp head)) elaborates fine and reads beautifully.
But every downstream statement then has to peel CertLayer.comp to get at .fwd, and at MNv4's
LITERAL resolutions that peel is fatal: (L₁.comp L₂).fwd = L₂.fwd ∘ L₁.fwd is rfl, yet
discharging it at these instances — by rfl, by simp only [CertLayer.comp_fwd], inside the T2
capstone or in a standalone lemma — costs ten minutes of elaboration and then a (kernel) deterministic timeout. ⚠ The groups' OWN five-stage comp chains are fine; it is composing the
compositions, under something that can start unfolding, that is not.
⭐ So the top level is seven named prefixes and the forward is their nest — ResNet-50's shape at
seven stages instead of eighteen. What that costs is the hypothesis bundle: Mnv4SmoothAt binds
one .ok per group (seven) rather than one for the whole trunk. What it keeps is everything that
mattered — each group's .ok is still the conjunction CertLayer.comp assembled from its blocks'
conditions at their own activations, so ~60 relu clauses are still never written down, and no
0 < ε hypothesis appears at all. R50's apex binds 33.
Prefix 0: the stem's output.
Equations
- Proofs.StableHLO.mnv4Pre0 N w x = Proofs.StableHLO.mnv4StemB N 112 112 w.sW w.sb w.sE w.sg w.sbt x
Instances For
Prefix 1: through the fused stage, at 56×56.
Equations
- Proofs.StableHLO.mnv4Pre1 N w x = (Proofs.StableHLO.mnv4FusedStack N w).fwd (Proofs.StableHLO.mnv4Pre0 N w x)
Instances For
Prefix 2: through rows 1–2, at 28×28.
Equations
- Proofs.StableHLO.mnv4Pre2 N w x = (Proofs.StableHLO.mnv4Res28Layer N w).fwd (Proofs.StableHLO.mnv4Pre1 N w x)
Instances For
Prefix 3: through rows 3–6, at 14×14.
Equations
- Proofs.StableHLO.mnv4Pre3 N w x = (Proofs.StableHLO.mnv4Res14aLayer N w).fwd (Proofs.StableHLO.mnv4Pre2 N w x)
Instances For
Prefix 4: through rows 7–10, still at 14×14.
Equations
- Proofs.StableHLO.mnv4Pre4 N w x = (Proofs.StableHLO.mnv4Res14bLayer N w).fwd (Proofs.StableHLO.mnv4Pre3 N w x)
Instances For
Prefix 5: through rows 11–15, at 7×7.
Equations
- Proofs.StableHLO.mnv4Pre5 N w x = (Proofs.StableHLO.mnv4Res7aLayer N w).fwd (Proofs.StableHLO.mnv4Pre4 N w x)
Instances For
Prefix 6: through rows 16–21 — the whole trunk below the head.
Equations
- Proofs.StableHLO.mnv4Pre6 N w x = (Proofs.StableHLO.mnv4Res7bLayer N w).fwd (Proofs.StableHLO.mnv4Pre5 N w x)
Instances For
T1's forward half: the full batch-BN MobileNetV4-Conv-M, N*(3*224*224) → N*nCls.
The stem, the fused stage, the five resolution groups, the head. Every block inside those
groups is mnv4BodyOfRow at its own row, so the k = 0 dispatch is READ from mnv4Blocks
rather than chosen here — the property MobileNetV4BackB0.lean's dispatch section exists to
establish, now carried to the net. The eighteen skips are CertLayer.residual, which
typechecks with no transport because s.oc and s.ic reduce to the same literal at every
stride-1 row (guarded there).
Equations
Instances For
Stem graph: 3×3/s2 XLA-SAME conv → batch BN → relu.
⚠⚠ GENERIC in the widths, and that is a correctness-of-elaboration requirement, not style.
Pinning ic := 3, oc := 32, h := 112 here makes the conv's den_batchOp rfl a claim
about concrete 150528- and 401408-element tensors, and the KERNEL tries to reduce it: the
lemma takes over a minute and then fails with (kernel) deterministic timeout. Proven at
binders it takes two seconds, and applying it at the net's literals is free — instantiating a
proven lemma, not proving one. mnv2StemGraphB and r50StemGraphB are generic for the same
reason, which is easy to read as a stylistic habit and is not.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Fused stage graph: 3×3/s2 SYMMETRIC conv → BN → swish → 1×1 project → BN. No skip.
⚠ Generic in the widths, for the reason mnv4StemGraphB records.
Equations
- One or more equations did not get rendered due to their size.
Instances For
ExtraDW body graph — both depthwises present, 13 of Conv-M's 21 rows (and all three
stride-2 ones, whose own builder is below). The BODY only: the identity skip is .addVB'd on
at the call site, which is what keeps the whole-net graph LINEAR instead of duplicating each
skip's entire input subtree.
Equations
- One or more equations did not get rendered due to their size.
Instances For
⭐ The ExtraDW body graph denotes the row-typed body's forward — generic in the row, so one
theorem serves all thirteen. The two hypotheses are exactly the dispatch conditions
mnv4PreDWSlot/mnv4PostDWSlot branch on, discharged by decide at each concrete row.
ConvNeXt-like body graph — pre-DW only, postDWk = 0, four of Conv-M's rows (8, 10, 16,
21). ⛔ The absent depthwise emits NO tokens, exactly as mnv4PostDWSlot inserts id': the
UibParams record still carries a degenerate DepthwiseKernel _ 0 0 in that slot and this
graph simply does not read it. A token stated for an absent depthwise would be a den of a
node the artifact does not have.
Equations
- One or more equations did not get rendered due to their size.
Instances For
FFN body graph — neither depthwise, four of Conv-M's rows (9, 15, 19, 20): expand,
project, and nothing else. Both slots are id'.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Pre-strided block graph — rows 1, 3 and 11, the only stride-2 rows Conv-M has, and all
three PRE-strided. The leading depthwise carries the stride (.depthwiseStrided, SYMMETRIC
padding), so everything after it runs at the reduced h. ⚠ No skip: ic ≠ oc at all three,
so the block IS the body and there is no .addVB.
Equations
- One or more equations did not get rendered due to their size.
Instances For
⭐⭐ One skip row's graph: its body's, plus the identity skip. Trivial as a definition and load-bearing as a barrier.
⚠⚠ This is why it is a named combinator and not an inline .addVB. The residual add needs
the block's input subtree TWICE, and MNv4 has eighteen of them. Written inline — or hidden
behind a let in the whole-net graph, which is what this file did first — the term doubles at
every skip the moment anything unfolds it, and simp only [mnv4FwdGraphB_full] ZETA-EXPANDS
lets, so the let form bought nothing at all: the whole-net faithfulness proof elaborated and
then died in the KERNEL with a deterministic timeout.
⭐ Kept folded, with mnv4SkipGraphB_faithful rewriting den (mnv4SkipGraphB body e) in ONE
step, den e occurs once and the whole-net term stays linear in the depth. R50 never met this:
its r50IdGraphB takes e as a binder and duplicates it inside the builder, which has the
same effect for the same reason.
Equations
- Proofs.StableHLO.mnv4SkipGraphB body e = (body e).addVB e
Instances For
⭐ A skip row denotes residual of whatever its body denotes — generic in both, so one
theorem covers all eighteen and the body's own faithfulness lemma is the only input.
Head graph: 1×1 conv-BN-relu, a SECOND 1×1 conv-BN-relu, GAP, dense — Conv-M's head has
two convs where mnv4Head models one. ⚠ Generic in the widths, for the reason
mnv4StemGraphB records.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Trunk group Res28's graph — rows 1–2: the 56→28 reduction and the block that follows it.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Trunk group Res14a's graph — rows 3–6: the 28→14 reduction, then three ExtraDW blocks.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Trunk group Res14b's graph — rows 7–10 at 14×14: ExtraDW, ConvNeXt, FFN, ConvNeXt — three families in four blocks.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Trunk group Res7a's graph — rows 11–15: the last reduction (14→7), then four blocks at 7×7.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Trunk group Res7b's graph — rows 16–21 at 7×7: the net's tail.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The fused stage's graph faithfulness, restated at mnv4FusedStack itself.
⚠ This corollary exists so the whole-net proof never has to UNFOLD mnv4FusedStack. It looks
redundant and is not: at MNv4's literal resolutions, letting anything unfold far enough for
den to start recursing turns the kernel's check into an evaluation of the whole graph, which
is the failure the group split above already had to work around once. Seven rewrites all of
the shape den <subgraph> = <subLayer>.fwd (den ·) keep every stage opaque.
The head's graph faithfulness, restated at mnv4HeadStack itself. Same reason.
The stem's, likewise, at the net's own widths.
⭐⭐ The full batch-BN MobileNetV4-Conv-M forward graph, at mnv4FwdChainB's own tokens
and its own SSA names, so the typed graph diffs against mnv4_fwd.mlir and its five ImageNet
twins name for name. ✅ Checked against the committed bytes: all 247 names this writes appear
in that file, and between them they cover all 233 of its declared parameters.
⚠ The eighteen skip rows go through mnv4SkipGraphB, which is what keeps this term LINEAR in
the depth — see that combinator's docstring for the failure mode it exists to prevent.
Equations
- One or more equations did not get rendered due to their size.
Instances For
⭐⭐ T2 for MobileNetV4-Conv-M at batch BatchNorm: the typed graph denotes the whole-net forward. Seven rewrites — the stem, the fused stage, the five resolution groups and the head — each of which was itself proved one block at a time. The first graph-level tier this net has ever had.
⚠ Each group's proof discharges its blocks' dispatch hypotheses by decide at the concrete
row, so what selects ExtraDW / ConvNeXt / FFN is the TABLE, not this file. A row wired to the
wrong builder fails to elaborate rather than proving something about a different net.
Trunk group Res28 — rows 1–2, at 56 → 28 — as its own blocks, each at its table row (mnv4Row1, mnv4Row2).
Trunk group Res14a — rows 3–6, at 28 → 14 — as its own blocks, each at its table row (mnv4Row3, mnv4Row4, mnv4Row5, mnv4Row6).
Trunk group Res14b — rows 7–10, at 14×14 — as its own blocks, each at its table row (mnv4Row7, mnv4Row8, mnv4Row9, mnv4Row10).
Trunk group Res7a — rows 11–15, at 14 → 7 — as its own blocks, each at its table row (mnv4Row11, mnv4Row12, mnv4Row13, mnv4Row14, mnv4Row15).
Trunk group Res7b — rows 16–21, at 7×7 — as its own blocks, each at its table row (mnv4Row16, mnv4Row17, mnv4Row18, mnv4Row19, mnv4Row20, mnv4Row21).