End-to-end IBP soundness (graph dialect, over ℝ) #
NN.MLTheory.CROWN.Proofs.GraphCertSoundness proves:
If a per-node IBP certificate is locally consistent (
CertLocalOK) and the value semantics is locally consistent (SemLocalOK), then each certified box encloses the corresponding value.
This file supplies a concrete, total evaluator and a concrete, total IBP propagation and proves
they satisfy the local-consistency predicates under the TopoSorted assumption (parents have
smaller ids). Combining these results yields an end-to-end theorem.
The final section connects the proof-side pass runIBP? to the engine's executable runIBP
(runIBP_eq_runIBP?) and derives the end-to-end theorem for the engine
(runIBP_encloses_evalGraphRec).
Array helper lemmas (getElem! after setIfInBounds) #
Total evaluators (Nat-recursive, prefix semantics) #
We define fold-by-id evaluators using Nat.rec rather than List.foldl to keep proofs small and
stable. The resulting arrays coincide with the intended “evaluate in node-id order” semantics.
Evaluate the first n nodes of g in id order, leaving the rest none.
Instances For
Evaluate all nodes of g in id order, returning the final value array.
Instances For
Prefix evaluator for the safe IBP checker step (certStepNode?).
Instances For
Run the safe IBP checker step across the full graph, producing a per-node certificate array.
Instances For
Prefix size facts.
Prefix stability: later writes do not change earlier entries.
Congruence of the step functions under TopoSorted #
If two arrays agree on all parent ids of node id, then the step function at id evaluates to the
same result.
Local consistency of the total evaluators #
Under topological order, the certificate produced by runIBP? satisfies CertLocalOK.
End-to-end theorem #
The engine pass runIBP #
runIBP (in NN.MLTheory.CROWN.Graph.Engine.IBP) is the executable pass that checkers call.
It differs from the proof-side runIBP? above in the following ways.
- It folds
propagateIBPNodeoverList.finRangeinstead of recursing on a prefix length. propagateIBPNodereads parent boxes withget!, so a missing parent box is replaced by the default box instead of producingnone.- It returns an all-
nonearray whencrownGraphSemanticsSupportedrejects the graph. - For
tanh,sigmoid,sin, andcosit uses theNonlinearBoundOpsenclosures, whereascertStepNode?uses theRuntime.Ops.IBPboxes. Forsinandcosthese are different boxes (both sound), so the two passes do not agree on those ops.
The first three differences are inessential. We identify the two passes on the op set where the
per-node steps coincide (EngineCore), under the hypothesis that the proof-side pass produced a
box at every node (IBPCovers), which rules out the get! default path. The engine's behaviour is
not changed.
Node kinds on which propagateIBPNode and certStepNode? compute the same box.
Instances For
The engine-core op set is contained in the op set of the IBP soundness theorem.
Prefix of the engine's fold, by recursion on the number of processed nodes.
Instances For
runIBP is the engine prefix recursion when the semantic guard accepts the graph.
runIBP is all none when the semantic guard rejects the graph.
The engine's runIBP computes exactly the proof-side runIBP? on engine-core graphs, provided the
semantic guard accepts the graph and the proof-side pass produced a box at every node.
Coverage is needed because propagateIBPNode reads parents with get!: at a node whose parent
box is missing, the engine would compute from a default box while certStepNode? returns none.
End-to-end soundness of the engine's IBP pass: every box computed by runIBP encloses the value
computed by the total evaluator evalGraphRec at the same node.
The statement quantifies over node ids at which the engine produced a box B and the evaluator a
value v, so it cannot hold through a missing entry. The semantic guard needs no hypothesis: if
crownGraphSemanticsSupported rejects the graph, runIBP produces no boxes and there is nothing
to prove. Coverage of the proof-side pass is needed for the reason given at runIBP_eq_runIBP?.