From NNF formulas to alternating Büchi automata #
We construct, for every negation normal form formula, an alternating Büchi
automaton (ABW) accepting the same language, establishing exists_ABW_lang_for_LTL.
The inclusion of LeanModelChecking.Iic x into LeanModelChecking.Iic y
induced by a bound x ≤ y. Lives in the Subtype namespace so that dot notation
v.embedLe hle works on subtype elements.
Equations
- Subtype.embedLe hle v = ⟨↑v, ⋯⟩
Instances For
f.repeatAndNext g n is the formula f ∧ X (f ∧ X (… ∧ X g)) with n nested
next operators, used to unfold f until g to depth n.
Equations
- f.repeatAndNext g 0 = g
- f.repeatAndNext g n.succ = f.and (f.repeatAndNext g n).next
Instances For
Functorial action on positive Boolean formulas: rename the atoms of ψ along
f, leaving the Boolean structure unchanged.
Equations
- LeanModelChecking.PositiveBool.map f (LeanModelChecking.PositiveBool.atom q) = LeanModelChecking.PositiveBool.atom (f q)
- LeanModelChecking.PositiveBool.map f LeanModelChecking.PositiveBool.true = LeanModelChecking.PositiveBool.true
- LeanModelChecking.PositiveBool.map f LeanModelChecking.PositiveBool.false = LeanModelChecking.PositiveBool.false
- LeanModelChecking.PositiveBool.map f (ψ₁.and ψ₂) = (LeanModelChecking.PositiveBool.map f ψ₁).and (LeanModelChecking.PositiveBool.map f ψ₂)
- LeanModelChecking.PositiveBool.map f (ψ₁.or ψ₂) = (LeanModelChecking.PositiveBool.map f ψ₁).or (LeanModelChecking.PositiveBool.map f ψ₂)
Instances For
Equations
- LeanModelChecking.PositiveBool.instFunctor = { map := fun {α β : Type} => LeanModelChecking.PositiveBool.map }
ψ.Forall p holds when every atom occurring in the positive Boolean formula
ψ satisfies the predicate p.
Equations
- LeanModelChecking.PositiveBool.Forall p (LeanModelChecking.PositiveBool.atom q) = p q
- LeanModelChecking.PositiveBool.Forall p LeanModelChecking.PositiveBool.true = True
- LeanModelChecking.PositiveBool.Forall p LeanModelChecking.PositiveBool.false = True
- LeanModelChecking.PositiveBool.Forall p (ψ₁.and ψ₂) = (LeanModelChecking.PositiveBool.Forall p ψ₁ ∧ LeanModelChecking.PositiveBool.Forall p ψ₂)
- LeanModelChecking.PositiveBool.Forall p (ψ₁.or ψ₂) = (LeanModelChecking.PositiveBool.Forall p ψ₁ ∧ LeanModelChecking.PositiveBool.Forall p ψ₂)
Instances For
Refine the atoms of ψ to the subtype Subtype p, given a proof pf that
every atom of ψ satisfies p.
Equations
- (LeanModelChecking.PositiveBool.atom q).mapSubtype h = LeanModelChecking.PositiveBool.atom ⟨q, h⟩
- LeanModelChecking.PositiveBool.true.mapSubtype x = LeanModelChecking.PositiveBool.true
- LeanModelChecking.PositiveBool.false.mapSubtype x = LeanModelChecking.PositiveBool.false
- (ψ₁.and ψ₂).mapSubtype pf_2 = (ψ₁.mapSubtype ⋯).and (ψ₂.mapSubtype ⋯)
- (ψ₁.or ψ₂).mapSubtype pf_2 = (ψ₁.mapSubtype ⋯).or (ψ₂.mapSubtype ⋯)
Instances For
Weaken the atom subtype of ψ from Subtype p to Subtype q along an
implication p x → q x.
Instances For
Equations
- One or more equations did not get rendered due to their size.
Underlying vertex/edge data of the replaceRoot construction: the DAG G
re-rooted, with its root r₁ relabelled to r₂ and embedded into Iic φ₂.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The replaceRoot.base data assembled into a DAG.
Equations
- LeanModelChecking.replaceRoot.dag hle r₁ r₂ G = { toBase := LeanModelChecking.replaceRoot.base hle r₁ r₂ G, edge_closure := ⋯ }
Instances For
Transport a run DAG of M to a run DAG of M' along the replaceRoot
construction, given that the transitions of M' extend those of M.
Equations
- LeanModelChecking.replaceRoot.runDag hle G h_delta_root h_delta_eq = { toDAG := LeanModelChecking.replaceRoot.dag hle M.q₀ M'.q₀ G.toDAG, p_root := ⋯, p_sat := ⋯ }
Instances For
If the source run DAG G is accepting and the embedding embedLe hle reflects
the acceptance condition (hF), then the transported replaceRoot.runDag is
accepting too.
Shift the DAG G down by one level and prepend a fresh root r₂ at level 0
pointing to the old root r₁, embedding everything into Iic φ₂.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Turn a run DAG of M on the shifted word into a run DAG of M' on the
original word, by shiftDag.dag with the old root threaded through the new one.
Equations
- LeanModelChecking.shiftDag.runDag hle G h_root h_delta_eq = { toDAG := LeanModelChecking.shiftDag.dag hle M.q₀ M'.q₀ G.toDAG ⋯, p_root := ⋯, p_sat := ⋯ }
Instances For
Vertex/edge data conjoining two DAGs G₁ and G₂ under a common fresh root
R on level 0, embedding their states into the shared bound Iic Φ.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The conjoinDag.base data assembled into a DAG.
Equations
- LeanModelChecking.conjoinDag.dag leφ₁ leφ₂ r₁ r₂ R G₁ G₂ = { toBase := LeanModelChecking.conjoinDag.base leφ₁ leφ₂ r₁ r₂ R G₁ G₂, edge_closure := ⋯ }
Instances For
The p_sat obligation of conjoinDag.runDag, extracted as a standalone
lemma: every vertex of the conjoined DAG has a satisfying set of successors.
Conjoin run DAGs of M₁ and M₂ into a run DAG of M, witnessing that M
runs both component automata in parallel from the shared root.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Conjoin a run DAG of M₁ on the current word with a run DAG of M₂ on the
shifted word into a single run DAG, the construction underlying the until/
release "next" steps.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Extract from G the sub-DAG of states below φ, restarting it from a fresh
root rφ at the given shift and re-embedding into Iic φ.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Build a run DAG of M' (the sub-automaton below φ) from a run DAG of M,
restricting to the descendants of a chosen vertex (rΦ, shift).
Equations
- LeanModelChecking.filterDag.runDag leφ G rΦ shift h_root h_delta_eq = { toDAG := LeanModelChecking.filterDag.dag leφ G.toDAG rΦ M'.q₀ shift, p_root := ⋯, p_sat := ⋯ }
Instances For
The "below" vertex set: the union over k of the k-th DAG G k with its
levels shifted up by k, used to stitch the family G into one run.
Equations
Instances For
The vertex set of the combined always DAG: the persistent root at Φ on
every level, together with the embedded vertices of Vb.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The least shift i ≤ v.2 for which the vertex v already appears in G i;
this is the DAG of the family that first "owns" v.
Instances For
The edge set of the combined always DAG: the root Φ loops on itself and
spawns a fresh copy of each G l at every level, while non-root vertices follow
the edges of the DAG G (mini …) that owns them.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The vertex/edge data of the always construction.
Equations
- LeanModelChecking.alwaysDag.base ltφ G = { V := LeanModelChecking.alwaysDag.V ltφ G, E := LeanModelChecking.alwaysDag.E G }
Instances For
The alwaysDag.base data assembled into a DAG.
Equations
- LeanModelChecking.alwaysDag.dag ltφ G = { toBase := LeanModelChecking.alwaysDag.base ltφ G, edge_closure := ⋯ }
Instances For
Combine the family of run DAGs G i of M' on every shifted word into one
run DAG of M, realising the release/always semantics where the obligation
is restarted at each level.
Equations
- LeanModelChecking.alwaysDag.runDag ltφ G h_M_root h_M'_root h_delta_root h_delta_eq = { toDAG := LeanModelChecking.alwaysDag.dag ltφ fun (i : ℕ) => (G i).toDAG, p_root := ⋯, p_sat := ⋯ }
Instances For
Subformula relation: φ ≤ ψ means φ is a subformula of ψ
- refl {AP : Type} {φ : NNF AP} : sub φ φ
- and_left {AP : Type} {φ f g : NNF AP} : sub φ f → sub φ (f.and g)
- and_right {AP : Type} {φ f g : NNF AP} : sub φ g → sub φ (f.and g)
- or_left {AP : Type} {φ f g : NNF AP} : sub φ f → sub φ (f.or g)
- or_right {AP : Type} {φ f g : NNF AP} : sub φ g → sub φ (f.or g)
- next {AP : Type} {φ f : NNF AP} : sub φ f → sub φ f.next
- until_left {AP : Type} {φ f g : NNF AP} : sub φ f → sub φ (f.until g)
- until_right {AP : Type} {φ f g : NNF AP} : sub φ g → sub φ (f.until g)
- release_left {AP : Type} {φ f g : NNF AP} : sub φ f → sub φ (f.release g)
- release_right {AP : Type} {φ f g : NNF AP} : sub φ g → sub φ (f.release g)
Instances For
Equations
A structural size measure on NNF formulas, used to bound the subformula order and prove finiteness of the state space.
Equations
- LeanModelChecking.size (LeanModelChecking.NNF.atom p) = 1
- LeanModelChecking.size (LeanModelChecking.NNF.not_atom p) = 1
- LeanModelChecking.size φ₁.next = LeanModelChecking.size φ₁ + 1
- LeanModelChecking.size (φ₁.and φ₂) = max (LeanModelChecking.size φ₁) (LeanModelChecking.size φ₂) + 1
- LeanModelChecking.size (φ₁.or φ₂) = max (LeanModelChecking.size φ₁) (LeanModelChecking.size φ₂) + 1
- LeanModelChecking.size (φ₁.until φ₂) = max (LeanModelChecking.size φ₁) (LeanModelChecking.size φ₂) + 1
- LeanModelChecking.size (φ₁.release φ₂) = max (LeanModelChecking.size φ₁) (LeanModelChecking.size φ₂) + 1
Instances For
Equations
- One or more equations did not get rendered due to their size.
The finite set of subformulas of an NNF formula (including the formula itself), witnessing that the subformula order has a finite carrier.
Equations
- LeanModelChecking.subFinset (LeanModelChecking.NNF.atom p) = {LeanModelChecking.NNF.atom p}
- LeanModelChecking.subFinset (LeanModelChecking.NNF.not_atom p) = {LeanModelChecking.NNF.not_atom p}
- LeanModelChecking.subFinset φ₁.next = insert φ₁.next (LeanModelChecking.subFinset φ₁)
- LeanModelChecking.subFinset (φ₁.and φ₂) = insert (φ₁.and φ₂) (LeanModelChecking.subFinset φ₁ ∪ LeanModelChecking.subFinset φ₂)
- LeanModelChecking.subFinset (φ₁.or φ₂) = insert (φ₁.or φ₂) (LeanModelChecking.subFinset φ₁ ∪ LeanModelChecking.subFinset φ₂)
- LeanModelChecking.subFinset (φ₁.until φ₂) = insert (φ₁.until φ₂) (LeanModelChecking.subFinset φ₁ ∪ LeanModelChecking.subFinset φ₂)
- LeanModelChecking.subFinset (φ₁.release φ₂) = insert (φ₁.release φ₂) (LeanModelChecking.subFinset φ₁ ∪ LeanModelChecking.subFinset φ₂)
Instances For
The one-step transition formula of the alternating automaton for φ on the
letter σ: a positive Boolean formula over subformulas describing which
obligations the successors must satisfy.
Equations
- LeanModelChecking.delta (LeanModelChecking.NNF.atom p) σ = if p ∈ σ then LeanModelChecking.PositiveBool.true else LeanModelChecking.PositiveBool.false
- LeanModelChecking.delta (LeanModelChecking.NNF.not_atom p) σ = if p ∈ σ then LeanModelChecking.PositiveBool.false else LeanModelChecking.PositiveBool.true
- LeanModelChecking.delta (φ₁.and φ₂) σ = (LeanModelChecking.delta φ₁ σ).and (LeanModelChecking.delta φ₂ σ)
- LeanModelChecking.delta (φ₁.or φ₂) σ = (LeanModelChecking.delta φ₁ σ).or (LeanModelChecking.delta φ₂ σ)
- LeanModelChecking.delta φ₁.next σ = LeanModelChecking.PositiveBool.atom φ₁
- LeanModelChecking.delta (φ₁.until φ₂) σ = (LeanModelChecking.delta φ₂ σ).or ((LeanModelChecking.delta φ₁ σ).and (LeanModelChecking.PositiveBool.atom (φ₁.until φ₂)))
- LeanModelChecking.delta (φ₁.release φ₂) σ = (LeanModelChecking.delta φ₂ σ).and ((LeanModelChecking.delta φ₁ σ).or (LeanModelChecking.PositiveBool.atom (φ₁.release φ₂)))
Instances For
The alternating Büchi automaton recognising the language of the NNF formula
ψ: its states are the subformulas of ψ, its initial state is ψ, and its
transitions are given by delta.
Equations
- One or more equations did not get rendered due to their size.