pub enum GraphProof {
Whole {
graph: MarkedGraph,
liveness: LivenessWitness,
cases: Vec<TripCase>,
case_witnesses: Vec<LivenessWitness>,
},
PerSection {
sections: Vec<SectionProof>,
witnesses: Vec<LivenessWitness>,
places: usize,
transitions: usize,
},
}Expand description
HOW THE LIVENESS PROOF IS CARRIED.
★ WHY THERE ARE TWO FORMS. The unrolled event graph of a four-layer Qwen3.8 forward is 196,211,828 places and 102,936,753 transitions — 35 GB, two thirds of peak, and the reason the sixty-four-layer model did not fit on a 125 GB box. The graph is not irreducibly that big: it is a DISJOINT UNION of one subgraph per section joined only by the program-counter chain, because on the composed forward NO buffer, semaphore or multicast group is touched by two sections. Proving one section at a time and keeping only the witnesses turns a 35 GB artifact into per-section orders, and peak from the sum of the sections into the largest of them.
★ WHY THE CUT IS SOUND, AND WHERE IT REFUSES. Commoner’s condition asks that every directed cycle
carry a token. Cutting the program-counter arcs between sections only REMOVES arcs, so it can invent
no cycle; it could only HIDE one that runs backwards from a later section to an earlier one — and a
backwards arc is exactly a place produced in one section and consumed in another. section_ranges
checks for that and hands back None when it finds one, so a program that does not decompose is
proved whole, at the old cost, rather than proved wrongly.
Variants§
Whole
One graph for the whole choreography. The form every single-section program takes, and the
fallback whenever a place crosses a section boundary. The graph itself is carried, so recheck
compares it structurally.
Fields
graph: MarkedGraphliveness: LivenessWitnesscases: Vec<TripCase>The graph at every count of the program’s trips’ windows, ordered by case_witnesses.
case_witnesses: Vec<LivenessWitness>PerSection
One proof per section, plus the totals. The graphs are rebuilt by recheck from the schedule and
matched against the carried digests.
★ THE WITNESSES ARE A TABLE, BECAUSE A DECODER REPEATS ITSELF. Sections with the same dataflow
build the same graph up to resource names, and so the same topological order. Measured on the
composed Qwen3.8 forward: 117 sections carry 11 DISTINCT witnesses at 4 layers, and 232 sections
carry the SAME 11 at 8 — the table is constant in depth, while one witness per section grows with
it (3,923 entries at 4 layers, 7,759 at 8; the real-width certificate was 810 MB at 2 layers).
Sharing is safe by construction: recheck still rebuilds EVERY section’s own graph and verifies
the witness it references against that graph, so a shared witness that does not fit a section is
a refusal, never an acceptance.
Implementations§
Source§impl GraphProof
impl GraphProof
pub fn places(&self) -> usize
pub fn transitions(&self) -> usize
Sourcepub fn whole_graph(&self) -> Option<&MarkedGraph>
pub fn whole_graph(&self) -> Option<&MarkedGraph>
The whole graph, when one is carried. None is not “no proof”: it is the per-section form, whose
graphs are rebuilt on demand by ChoreographyCertificate::recheck.
Sourcepub fn whole_graph_mut(&mut self) -> Option<&mut MarkedGraph>
pub fn whole_graph_mut(&mut self) -> Option<&mut MarkedGraph>
The whole graph, mutably — the seam a mutation probe needs to corrupt a carried graph.
Sourcepub fn witnesses(&self) -> Vec<&LivenessWitness>
pub fn witnesses(&self) -> Vec<&LivenessWitness>
Every witness this proof carries, in section order (one entry for the whole form).
Sourcepub fn witness_of_section(&self) -> Option<Vec<usize>>
pub fn witness_of_section(&self) -> Option<Vec<usize>>
For the per-section form, the witness-table index each section uses, in section order.
Trait Implementations§
Source§impl Clone for GraphProof
impl Clone for GraphProof
Source§fn clone(&self) -> GraphProof
fn clone(&self) -> GraphProof
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read moreSource§impl Debug for GraphProof
impl Debug for GraphProof
Source§impl<'de> Deserialize<'de> for GraphProof
impl<'de> Deserialize<'de> for GraphProof
Source§fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>where
__D: Deserializer<'de>,
Source§impl PartialEq for GraphProof
impl PartialEq for GraphProof
Source§impl Serialize for GraphProof
impl Serialize for GraphProof
impl Eq for GraphProof
impl StructuralPartialEq for GraphProof
Auto Trait Implementations§
impl Freeze for GraphProof
impl RefUnwindSafe for GraphProof
impl Send for GraphProof
impl Sync for GraphProof
impl Unpin for GraphProof
impl UnsafeUnpin for GraphProof
impl UnwindSafe for GraphProof
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Downcast for Twhere
T: Any,
impl<T> Downcast for Twhere
T: Any,
§fn into_any(self: Box<T>) -> Box<dyn Any>
fn into_any(self: Box<T>) -> Box<dyn Any>
Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can
then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.§fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>
Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be
further downcast into Rc<ConcreteType> where ConcreteType implements Trait.§fn as_any(&self) -> &(dyn Any + 'static)
fn as_any(&self) -> &(dyn Any + 'static)
&Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &Any’s vtable from &Trait’s.§fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)
&mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot
generate &mut Any’s vtable from &mut Trait’s.§impl<T> DowncastSync for T
impl<T> DowncastSync for T
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.