Spec → math (the verification tie), Rung 1: the linear classifier #
The shape #guard beside resnet34Verified in VerifiedNetsCore.lean only checks the
parameter interface
(typechecking). This file is the first rung of connecting a readable VerifiedNetSpec
to the actual math — the proven VJP — on the simplest net, the Chapter-1 linear
classifier (dense 784→10).
The pattern (extends to MLP → conv nets, each rigid/per-net):
denotemaps the spec's layers to the Mathlib math function the proofs are about;- a
rfllemma ties the spec's denotation to that named function (mnistLinear); - the whole-model VJP theorem is stated about the spec's denotation and discharged
by the audited op-level VJP (
dense_has_vjp).
If the spec's layers drifts from [.dense 784 10], step 2/3 stop reducing and the
proofs fail to typecheck — so the readable architecture is provably the verified one,
at the math level, not just the shape level.
Math denotation of the linear spec. The Chapter-1 model is a single dense layer, so
[.dense 784 10] denotes to the Mathlib dense W b. Any other layer list is not the
linear model (0), which makes the tie below drift-sensitive.
Equations
- denoteLinear [VLayer.dense 784 10] W b = Proofs.dense W b
- denoteLinear layers W b = fun (x : Proofs.Vec 784) => 0
Instances For
Spec ≡ the proven model. linearVerified's denotation is exactly mnistLinear
(the function the Chapter-1 VJP capstone is about) — by rfl, so it's checked by the
kernel and breaks if linearVerified.layers changes.
The spec carries the math. The linear spec's denotation has the proven VJP —
discharged by the audited dense_has_vjp. This is the whole-model verification
stated about the readable layer list, not a hand-written function.
Equations
Instances For
…and its correctness headline carries over verbatim (the backward is the
pdiv-contracted Jacobian of the spec's denotation).
Rung 2: the MLP — the first genuine vjp_comp fold #
The linear model was the degenerate case (one layer, no fold). The MLP's denotation is a
chain — dense ∘ relu ∘ dense ∘ relu ∘ dense (mlpForward) — and its VJP is built by
folding vjp_comp_at down that chain (mlp_has_vjp_at). So this is where the spec→math
tie first exercises the chain rule, not just a single op.
Math denotation of the MLP spec: the 5-layer list denotes to mlpForward.
Equations
- denoteMLP [VLayer.dense 784 512, VLayer.relu, VLayer.dense 512 512, VLayer.relu, VLayer.dense 512 10] W₀ b₀ W₁ b₁ W₂ b₂ = Proofs.mlpForward W₀ b₀ W₁ b₁ W₂ b₂
- denoteMLP layers W₀ b₀ W₁ b₁ W₂ b₂ = fun (x : Proofs.Vec 784) => 0
Instances For
Spec ≡ the proven model. mlpVerified's denotation is exactly mlpForward
(dense ∘ relu ∘ dense ∘ relu ∘ dense) — by rfl, drift-sensitive.
The spec carries the math (canonical witness). The MLP spec's denotation has a
VJP — the global pdiv-derived witness (mlp_has_vjp; relu uses the framework
subgradient convention at the kinks, per Proofs/README.md).
Equations
- mlpVerified_has_vjp W₀ b₀ W₁ b₁ W₂ b₂ = Proofs.mlp_has_vjp W₀ b₀ W₁ b₁ W₂ b₂
Instances For
The spec carries the math (the real fold). At a smooth input — the two ReLU
pre-activations avoid zero — the MLP spec's denotation has a VJP built by folding
vjp_comp_at through dense → relu → dense → relu → dense (no rfl escape at the
kinks). This is the chain rule applied to the spec, the step linear couldn't show.
Equations
- mlpVerified_has_vjp_at W₀ b₀ W₁ b₁ W₂ b₂ x h0 h1 = Proofs.mlp_has_vjp_at W₀ b₀ W₁ b₁ W₂ b₂ x h0 h1
Instances For
…correctness headline for the canonical witness carries over to the spec.
Rung 3: the CNN — the fold now runs through conv + maxpool #
The CNN's denotation is mnistCnnNoBnForward — a flat Vec 784 → Vec 10 chain
flatConv → relu → flatConv → relu → maxPoolFlat → dense → relu → dense → relu → dense.
The honest chain-rule fold (via vjp_comp_at through conv/maxpool/dense) is the audited
mnistCnnNoBn_has_vjp_at, conditional on the four ReLU kinks + the maxpool being smooth at
the input. Here we headline the unconditional canonical witness (mlp_has_vjp style); the
spec is exactly the subject of that conditional fold via cnnVerified_denote_eq.
Math denotation of the CNN spec: the 11-layer list denotes to mnistCnnNoBnForward
(c=32, h=w=14, the Chapter-3 MNIST CNN).
Equations
- One or more equations did not get rendered due to their size.
- denoteCNN layers W₁ b₁ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ = fun (x : Proofs.Vec 784) => 0
Instances For
Spec ≡ the proven model. cnnVerified's denotation is exactly mnistCnnNoBnForward
— the function the Chapter-3 fold mnistCnnNoBn_has_vjp_at is about — by rfl.
The spec carries the math. The CNN spec's denotation (conv→relu→conv→relu→maxpool
→dense→…) has a VJP — the canonical pdiv-derived witness. The conditional chain-rule
fold through conv/maxpool is the audited mnistCnnNoBn_has_vjp_at.
Equations
- cnnVerified_has_vjp W₁ b₁ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ = Proofs.HasVJP.canonical (denoteCNN cnnVerified.layers W₁ b₁ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅)
Instances For
Rung E (linear): the spec ↔ the generated MLIR #
The ties above connect the spec to the math (denote = the proven forward, which has
the proven VJP). This connects the spec to the StableHLO the trainer actually compiles
and runs: the generated forward graph fwdGraph (→ verified_mlir/linear_fwd.mlir, the
eval path) and the train-step loss-cotangent graph lossCotGraph (→ linear_train_step.mlir)
denote the spec's forward and its softmax-CE gradient — via the audited faithfulness
theorems (fwdGraph_faithful, lossCotGraph_isCEgrad) composed with denoteLinear = mnistLinear (rfl). So the generated code provably computes the spec's function.
What stays trusted (the codegen boundary, per Proofs/README.md): the text render
linearFwdModuleV = pretty (emit fwdGraph) and that the committed .mlir equals that
text — the pretty-printer + regeneration, NOT the semantics, which are proven here.
Generated forward MLIR ↔ spec. The forward graph (rendered to linear_fwd.mlir,
the eval path) denotes the spec's forward function.
Generated train-step cotangent ↔ spec. The loss-cotangent graph (in
linear_train_step.mlir) denotes ∂(softmax-CE)/∂logits at the spec's logits.
Rung E (MLP): the spec ↔ the generated MLIR — both forward and backward #
The MLP has faithfulness for the whole forward graph (mlpFwdGraph_faithful, the graph
mlp_fwd.mlir prints) AND for a whole backward input-VJP graph (mlpBackGraph_faithful).
Composed with denoteMLP = mlpForward and mlpVerified_has_vjp_at = mlp_has_vjp_at, both
denote the spec: the rendered forward computes the spec's forward, and mlpBackGraph
computes the spec's VJP backward (at a smooth input). mlpBackGraph is a spec-level graph
no committed artifact prints: mlp_train_step.mlir is MlpRender.lean's
mlpTrainStepFaithfulV, whose parameter ops MlpFold ties to the certified step.
Generated MLP forward MLIR ↔ spec. The forward graph (→ mlp_fwd.mlir) denotes
the spec's forward function.
MLP backward graph ↔ spec. mlpBackGraph, the input-VJP graph (spec-level; no
committed artifact prints it, see the section header), denotes the spec's VJP backward
(mlpVerified_has_vjp_at), at a smooth input (the two ReLU pre-activations avoid zero).
Rung E (CNN): the spec ↔ the generated MLIR (forward) #
The generated CNN forward graph (flatConv→relu→flatConv→relu→maxPoolFlat→dense→relu→ dense→relu→dense) denotes the spec's forward. The backward graph faithfulness exists too
(cnnBackGraph_faithful denotes mnistCnnNoBn_has_vjp_at.backward — the VJP of exactly
this spec's forward), but it carries the same five ReLU/maxpool smoothness hypotheses as
the conditional fold, so we headline the unconditional forward tie (matching
cnnVerified_has_vjp, the canonical witness).
Generated CNN forward MLIR ↔ spec. The forward graph (→ cnn_fwd.mlir) denotes
the spec's forward (mnistCnnNoBnForward, c=32 / h=w=14).
Rung 4 + E (CIFAR): completing the ch5 ladder #
The CIFAR-10 net (ic=3, c1=32, c2=64, h=w=8 — spatial 32→16→8) gets the spec→math
denotation (= cifarCnnForward by rfl), the canonical witness VJP, and the forward
spec→generated-MLIR tie (cifarFwdGraph_faithful). The conditional fold is
cifarCnn_has_vjp_at (six ReLU kinks + two maxpools).
Equations
- One or more equations did not get rendered due to their size.
- denoteCifar layers W₁ b₁ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ W₆ b₆ W₇ b₇ = fun (x : Proofs.Vec 3072) => 0
Instances For
The (no-BN) CIFAR spec carries the math.
Equations
- cifarVerified_has_vjp W₁ b₁ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ W₆ b₆ W₇ b₇ = Proofs.HasVJP.canonical (denoteCifar cifarVerified.layers W₁ b₁ W₂ b₂ W₃ b₃ W₄ b₄ W₅ b₅ W₆ b₆ W₇ b₇)
Instances For
Generated (no-BN) CIFAR forward MLIR ↔ spec.
Rung B/C/E (ch7 MobileNetV2, FULL, batched): the committed spec ↔ the batch-BN net #
denoteMobilenetB maps mobilenetv2Verified.layers — the committed 21-entry full-paper
[t,c,n,s] list the trainer runs (stem-s2 3→32 → 17 bottlenecks → 1×1 head 320→1280 → GAP →
dense 1280→10) — to mobilenetv2ForwardB_full (MobileNetV2FullB.lean: batch BN throughout,
the t=1 no-expand first block, 4 stride-2 depthwise downsamples 224→7), at every batch size.
Weights ride in the MNV2BWeights bundle, so the tie stays readable. The rfl is
drift-sensitive: any [t,c,n,s] edit to the spec stops the match reducing — the tripwire the
6→17-block promotion once fired while the per-example twin of this section was orphaned;
certs.yml re-elaborates it on every spec push. (That per-example twin, at the forward of the
retired SGD artifact, was retired on 2026-09-19.)
Math denotation of the committed MobileNetV2 spec at batch BN: the 21-entry full-paper
layer list denotes to mobilenetv2ForwardB_full — the batch-statistics net every shipped
MobileNetV2 artifact runs (MobileNetV2FullB.lean), at every batch size N. Any other
list is not the net (0), so the tie below is drift-sensitive.
Equations
- One or more equations did not get rendered due to their size.
- denoteMobilenetB N layers w = fun (x : Proofs.Vec (N * (3 * 224 * 224))) => 0
Instances For
Spec ≡ the full batch-BN net. mobilenetv2Verified's denotation at batch N is
exactly mobilenetv2ForwardB_full N — by rfl, drift-sensitive.
The committed spec carries the math at batch BN — canonical pdiv witness (relu6 is
kinked; the pointwise whole-net VJP is mobilenetv2ForwardB_full_has_vjp_at_correct).
Equations
Instances For
Rung E at the committed spec, batched. The typed graph the shipped MobileNetV2
artifacts are printed from denotes the committed spec's function at batch BN:
mobilenetv2FwdGraphB_full_faithful composed with the tie.
Rung B/C/E (FULL, unified weight bundles): r34 / enet / convnext / vit #
The mnv2 full-paper pattern applied to the remaining imagenette nets: each committed
spec's ENTIRE layer list (literal dims, drift-sensitive) denotes the full proven
forward, with weights riding a structure bundle so the ties stay readable. Existing
bundles are reused where the Full module already has one (B0Weights,
CnxTWeightsCh, R34BWeights); vit gets its bundle here (ViTTinyWeights, SpecVJP-local so
no proof module's signature changes). Rung E composes each net's
full graph-faithfulness apex with the tie (vit's is vitFwdGraphKMHV_faithful,
ViTDepthK §3 — the depth-k multi-head vector-LN graph). Rung C is the canonical
witness except vit: all-smooth, so vit's rung C is the REAL whole-net VJP
vitForwardKV_has_vjp (only 0 < ε) at the committed spec.
Math denotation of the committed ResNet-34 spec at batch BN: the 8-entry stage-level list
denotes to resnet34ForwardB_full — the batch-statistics net every shipped ResNet-34
artifact runs (ResNet34FullB.lean), at every batch size N. Any other list is not the net
(0), so the tie below is drift-sensitive. (The per-example rung, at the forward of the
retired SGD artifact, was retired with it on 2026-09-19.)
Equations
- One or more equations did not get rendered due to their size.
- denoteR34FullB N layers w = fun (x : Proofs.Vec (N * (3 * 224 * 224))) => 0
Instances For
Spec ≡ the full batch-BN net. resnet34Verified's denotation at batch N is exactly
resnet34ForwardB_full N — by rfl, drift-sensitive.
The committed spec carries the math at batch BN — canonical pdiv witness (relu is
kinked; the pointwise whole-net VJP is resnet34ForwardB_full_has_vjp_at).
Equations
Instances For
Rung E at the committed spec, batched. The typed graph the shipped ResNet-34 artifacts
are printed from denotes the committed spec's function at batch BN:
resnet34FwdGraphB_full_faithful composed with the tie.
Math denotation of the committed EfficientNet-B0 spec at batch N: the 21-entry
[t,c,n,s,k] layer list denotes to efficientnetForwardB_full (all 16 MBConv
blocks, true batch-norm + SE). The spec ties the batched net at EVERY batch size.
Equations
- One or more equations did not get rendered due to their size.
- denoteEfficientnetB0 N layers w = fun (x : Proofs.Vec (N * (3 * 224 * 224))) => 0
Instances For
Spec ≡ the full proven net. efficientnetVerified's denotation is exactly
efficientnetForwardB_full (16 MBConv, batched, per-channel BN + SE) — by rfl.
The committed spec carries the math — canonical pdiv witness (swish/SE are
smooth but relu6 clamps; the per-block differentiability lemmas live in
EfficientNetFullB0.lean).
Equations
Instances For
Rung E at the committed spec (batched). The full 16-MBConv batched graph denotes
the committed spec's function: efficientnetFwdGraphB_full_faithful ∘ the tie.
Math denotation of the committed ConvNeXt-T spec: the 29-entry [3,3,9,3] layer list
denotes to convNextForwardTCh — the channel-LayerNorm net (§2m), whose 23 LN sites
are 1 stem + 18 block + 3 downsample + 1 head, the first 22 reducing over the c channels
at one spatial position with a per-channel [c] affine and the head one over the [768] GAP
output (which is the same function at one spatial position — rowLNVecFlat 1 768).
⚠ The head LN was RESTORED 2026-08-30 (planning/archive/next_session_execution_and_parity.md §7.1).
§2m/§2n had deleted it to match the JAX reference, which was itself missing it against both
the paper and timm; the parameter count was short by exactly 2×768.
⚠ This used to match a .convNextBlock/.bn list and denote the SCALAR-LN net: one mean and
one variance over the whole c·h·w map, two scalars, and no stem LN but a head LN. §2n
deleted that chain outright, so the trap it guarded against — silently re-pointing this at the
scalar function, which would typecheck by rfl and assert that the channel-LN layer list
denotes the scalar-LN one (§2k's own sin, one level down) — is no longer expressible. Keeping
the note because the SHAPE of that mistake is what §2k was about, not the specific symbol.
Equations
- One or more equations did not get rendered due to their size.
- denoteConvnextT layers w = fun (x : Proofs.Vec (3 * 224 * 224)) => 0
Instances For
Spec ≡ the full proven net. convnextVerified's denotation is exactly
convNextForwardTCh ([3,3,9,3] @ [96,192,384,768], channel LN + head LN, 28,589,128 params at
K = 1000 — the JAX reference's own count) — by rfl.
The committed spec carries the math — canonical pdiv witness; the REAL
whole-net VJP exists at full depth (convNextForwardTCh_has_vjp_correct,
all-smooth, the 22 LN positivities only) on the ∘-chain form.
Equations
Instances For
Rung E at the committed spec. The committed-config [3,3,9,3] channel-LN graph denotes
the committed spec's function: convNextFwdGraphTCh_faithful ∘ the tie.
All ViT-Tiny parameters at the committed config (D=192, 3 heads, d_head=64,
mlpDim=768, 12 untied blocks, vector-LN): patch embed + CLS/pos + 12 per-block
BlockParamsV bundles + final LN + CLS head. Shared LN ε rides along.
- ε : ℝ
- ε : ℝ
- Wc : Proofs.Kernel4 192 3 16 16
- Wc : Proofs.Kernel4 192 3 16 16
- bc : Proofs.Vec 192
- bc : Proofs.Vec 192
- cls : Proofs.Vec 192
- cls : Proofs.Vec 192
- pos : Proofs.Mat 197 192
- pos : Proofs.Mat 197 192
- blocks : Fin 12 → Proofs.BlockParamsV 192 768
- blocks : Fin 12 → Proofs.BlockParamsV 192 768
- γF : Proofs.Vec 192
- γF : Proofs.Vec 192
- βF : Proofs.Vec 192
- βF : Proofs.Vec 192
- Wcls : Proofs.Mat 192 10
- Wcls : Proofs.Mat 192 10
- bcls : Proofs.Vec 10
- bcls : Proofs.Vec 10
Instances For
vitForwardKV at the committed ViT-Tiny config (depth 12, 3 heads × 64).
Equations
Instances For
Math denotation of the committed ViT-Tiny spec: the 17-entry layer list (12 untied
.transformerBlocks, per-channel [192] LN, 1D CLS) denotes to vitForwardTiny.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Spec ≡ the full proven net. vitVerified's denotation is exactly
vitForwardKV at the committed config (depth-12 DISTINCT-param multi-head,
per-token vector-LN — ViTDepthK.lean) — by rfl. Retires the rep tie's
weight-shared scalar-LN caveats at the spec level.
The committed spec carries the math — the REAL whole-net VJP. ViT is all-smooth
(GELU/softmax/LN), so unlike the conv nets the honest chain-rule fold applies
globally: vitForwardKV_has_vjp at the committed config, hypothesis 0 < ε only.
The strongest rung C in this file — no canonical-witness fallback needed.
Equations
Instances For
Rung E at the committed spec. The depth-12 3-head vector-LN forward graph
(vitFwdGraphKMHV, ViTDepthK §3 — patch embed → 12 spelled multi-head blocks →
final vector-LN → CLS → head) denotes the committed spec's function:
vitFwdGraphKMHV_faithful composed with the tie. Completes the B/C/E ladder for
all five imagenette nets.