Research source · Plain text
Reachability.lean
site/public/formal/persistent-stacks/lean/FPRDTransfer/Theorem16/Reachability.lean
123 lines. Source is displayed for inspection; it is not executed by this page.
File fingerprint
SHA-256: 1510f46fa862b03bc710fd806c71fcc7d85272fe3b3c5d02c942550e4ce40509
import FPRDTransfer.Theorem16.Normalize
namespace FPRD
namespace Scaffold
variable {d : Nat} {Gamma : Type u}
/-- Generated scaffold edges never point above their source. Unlike strict
`Backward`, this includes the self-loop created by `Target.self`. -/
def NonForward (S : Scaffold d Gamma) : Prop :=
∀ v port target, S.edge v port = some target → target ≤ v
theorem base_nonforward (d : Nat) (Gamma : Type u) :
(Scaffold.base d Gamma).NonForward := by
intro v port target h
simp [Scaffold.base] at h
theorem follow_le_nonforward (S : Scaffold d Gamma) (hnf : S.NonForward) :
∀ (path : List (Fin d)) (source target : Nat),
S.follow source path = some target → target ≤ source := by
intro path
induction path with
| nil =>
intro source target h
simp [Scaffold.follow_nil] at h
omega
| cons port path ih =>
intro source target h
rw [Scaffold.follow_cons] at h
cases hedge : S.edge source port with
| none => rw [hedge] at h; simp at h
| some middle =>
rw [hedge] at h
exact Nat.le_trans (ih middle target h) (hnf source port middle hedge)
/-- Appending preserves non-forwardness for old paths, missing targets, and
`SELF`; no self-free side condition is needed. -/
theorem append_nonforward (S : Scaffold d Gamma) (hnf : S.NonForward)
(label : Gamma) (targets : Fin d → Target d) :
(S.append label targets).NonForward := by
intro source port target hedge
by_cases hnew : source = S.top + 1
· subst source
rw [Scaffold.append_edge_new] at hedge
cases htarget : targets port with
| path path =>
rw [htarget] at hedge
simp only [Scaffold.resolve] at hedge
exact Nat.le_trans (follow_le_nonforward S hnf path S.top target hedge)
(Nat.le_succ S.top)
| self =>
rw [htarget] at hedge
simp [Scaffold.resolve] at hedge
omega
| missing =>
rw [htarget] at hedge
simp [Scaffold.resolve] at hedge
· rw [Scaffold.append_edge_old S label targets hnew port] at hedge
exact hnf source port target hedge
end Scaffold
namespace Automaton
/-- Every generated run scaffold is non-forward, including runs whose
transitions emit `SELF`. -/
theorem run_nonforward (A : Automaton Sym Q Gamma d k) (word : List Sym) :
(A.run word).2.NonForward := by
have fold_nonforward : ∀ (suffix : List Sym)
(config : Q × Scaffold d Gamma), config.2.NonForward →
(suffix.foldl A.step config).2.NonForward := by
intro suffix
induction suffix with
| nil => intro config hconfig; exact hconfig
| cons symbol rest ih =>
intro config hconfig
apply ih (A.step config symbol)
unfold Automaton.step
exact Scaffold.append_nonforward _ hconfig _ _
exact fold_nonforward word (A.init, Scaffold.base d Gamma)
(Scaffold.base_nonforward d Gamma)
end Automaton
namespace Theorem16
namespace ReachabilityExamples
def oldPathScaffold : Scaffold 1 Unit :=
(Scaffold.base 1 Unit).append () (fun _ => .path [])
def missingScaffold : Scaffold 1 Unit :=
(Scaffold.base 1 Unit).append () (fun _ => .missing)
def selfScaffold : Scaffold 1 Unit :=
(Scaffold.base 1 Unit).append () (fun _ => .self)
example : oldPathScaffold.edge oldPathScaffold.top 0 = some 0 := by decide
example : missingScaffold.edge missingScaffold.top 0 = none := by decide
example : selfScaffold.edge selfScaffold.top 0 = some selfScaffold.top := by decide
example : oldPathScaffold.NonForward := by
exact Scaffold.append_nonforward _ (Scaffold.base_nonforward 1 Unit) _ _
example : missingScaffold.NonForward := by
exact Scaffold.append_nonforward _ (Scaffold.base_nonforward 1 Unit) _ _
example : selfScaffold.NonForward := by
exact Scaffold.append_nonforward _ (Scaffold.base_nonforward 1 Unit) _ _
def selfMachine : Automaton Bool Unit Unit 1 0 where
delta _ _ _ := ((), (), fun _ => .self)
init := ()
accept _ := true
example (word : List Bool) : (selfMachine.run word).2.NonForward :=
Automaton.run_nonforward selfMachine word
end ReachabilityExamples
end Theorem16
end FPRD