This PR adds missing monotonicity lemmas for universal quantifiers, that are used in defining (co)inductive predicates.
178 lines
5.5 KiB
Text
178 lines
5.5 KiB
Text
-- Coinductive predicate definition
|
||
def infseq {α} (R : α → α → Prop) : α → Prop :=
|
||
λ x : α => ∃ y, R x y ∧ infseq R y
|
||
greatest_fixpoint
|
||
|
||
-- Application of the rewrite rule
|
||
def infseq_fixpoint {α} (R : α → α → Prop) (x : α) :
|
||
infseq R x = ∃ y, R x y ∧ infseq R y := by
|
||
rw [infseq]
|
||
|
||
-- The associated coinduction principle
|
||
theorem infseq.coind {α} (h : α → Prop) (R : α → α → Prop)
|
||
(prem : ∀ (x : α), h x → ∃ y, R x y ∧ h y) : ∀ x, h x → infseq R x := by
|
||
apply infseq.fixpoint_induct
|
||
exact prem
|
||
/--
|
||
info: infseq.fixpoint_induct.{u_1} {α : Sort u_1} (R : α → α → Prop) (x : α → Prop)
|
||
(y : ∀ (x_1 : α), x x_1 → ∃ y, R x_1 y ∧ x y) (x✝ : α) : x x✝ → infseq R x✝
|
||
-/
|
||
#guard_msgs in #check infseq.fixpoint_induct
|
||
|
||
-- Simple proof by coinduction
|
||
theorem cycle_infseq {R : α → α → Prop} (x : α) : R x x → infseq R x := by
|
||
apply @infseq.fixpoint_induct α R (λ m => R m m)
|
||
intro x _
|
||
apply Exists.intro x
|
||
trivial
|
||
|
||
-- Inductive predicate, as a inductive definition
|
||
inductive star (R : α → α → Prop) : α → α → Prop where
|
||
| star_refl : ∀ x : α, star R x x
|
||
| star_step : ∀ x y z, R x y → star R y z → star R x z
|
||
|
||
-- Inductive predicate, as a least fixpoint
|
||
def star_ind (tr : α → α → Prop) (q₁ q₂ : α) : Prop :=
|
||
∃ (z : α), q₁ = q₂ ∨ (tr q₁ z ∧ star_ind tr z q₂)
|
||
least_fixpoint
|
||
|
||
/--
|
||
info: star_ind.fixpoint_induct.{u_1} {α : Sort u_1} (tr : α → α → Prop) (q₂ : α) (x : α → Prop)
|
||
(y : ∀ (x_1 : α), (∃ z, x_1 = q₂ ∨ tr x_1 z ∧ x z) → x x_1) (x✝ : α) : (fun q₁ => star_ind tr q₁ q₂) x✝ → x x✝
|
||
-/
|
||
#guard_msgs in #check star_ind.fixpoint_induct
|
||
|
||
-- From one you can prove the other
|
||
theorem star_implies_star' (R : α → α → Prop) : ∀ a b : α, star R a b → star_ind R a b := by
|
||
intro a b s
|
||
induction s
|
||
case star_refl x =>
|
||
unfold star_ind
|
||
apply Exists.intro x
|
||
left
|
||
trivial
|
||
case star_step x y z rel s2 ih =>
|
||
unfold star_ind
|
||
apply Exists.intro y
|
||
right
|
||
trivial
|
||
|
||
-- More elaborate example from Xavier Leroy's compiler verification course
|
||
theorem star_one (R : α → α → Prop) : ∀ a b : α, R a b → star R a b := by
|
||
intros a b Rab
|
||
apply star.star_step
|
||
exact Rab
|
||
apply star.star_refl
|
||
|
||
theorem star_trans {α} (R : α → α → Prop) : ∀ (a b : α), star R a b → ∀ c : α, star R b c → star R a c := by
|
||
intros a b sab
|
||
intro c
|
||
intro sbc
|
||
induction sab
|
||
case star_refl => exact sbc
|
||
case star_step rel m ih =>
|
||
apply star.star_step
|
||
exact rel
|
||
apply ih
|
||
trivial
|
||
|
||
inductive plus (R : α → α → Prop) : α → α → Prop where
|
||
| plus_left : ∀ a b c, R a b → star R b c → plus R a c
|
||
|
||
theorem plus_one : ∀ a b, R a b → plus R a b := by
|
||
intro a b Rab
|
||
apply plus.plus_left
|
||
exact Rab
|
||
apply star.star_refl
|
||
|
||
theorem plus_star : ∀ a b, plus R a b → star R a b := by
|
||
intro a b h
|
||
cases h
|
||
case plus_left h₁ h₂ h₃ =>
|
||
apply star.star_step
|
||
exact h₂
|
||
exact h₃
|
||
|
||
theorem plus_star_trans (R : α → α → Prop) : ∀ (a b c : α), star R a b → plus R b c → plus R a c := by
|
||
intro a b c s p
|
||
induction s
|
||
case star_refl d =>
|
||
exact p
|
||
case star_step d e f rel s2 ih =>
|
||
apply plus.plus_left
|
||
exact rel
|
||
apply plus_star
|
||
apply ih
|
||
exact p
|
||
|
||
def all_seq_inf (R : α → α → Prop) (x : α) : Prop :=
|
||
∀ y : α, star R x y → ∃ z, R y z
|
||
|
||
def infseq_if_all_seq_inf (R : α → α → Prop) : ∀ x, all_seq_inf R x → infseq R x := by
|
||
apply infseq.fixpoint_induct
|
||
intro x H
|
||
unfold all_seq_inf at H
|
||
have H' := H x (by simp [star.star_refl])
|
||
apply Exists.elim H'
|
||
intro y Rxy
|
||
apply Exists.intro y
|
||
apply And.intro
|
||
exact Rxy
|
||
unfold all_seq_inf
|
||
intro y'
|
||
intro Ryy'
|
||
apply H y'
|
||
apply star.star_step
|
||
exact Rxy
|
||
trivial
|
||
|
||
theorem infseq_coinduction_principle_2:
|
||
∀ (x : α → Prop),
|
||
(∀ (a : α), x a → ∃ b, plus R a b ∧ x b) →
|
||
∀ (a : α), x a → infseq R a := by
|
||
intro X
|
||
intro h₁ a rel
|
||
apply @infseq.fixpoint_induct _ _ (fun a => ∃ b, star R a b ∧ X b)
|
||
case x =>
|
||
apply Exists.elim (h₁ a rel)
|
||
intro a' ⟨h₁, h₂⟩
|
||
apply Exists.intro a'
|
||
apply And.intro
|
||
apply plus_star
|
||
exact h₁
|
||
exact h₂
|
||
case y =>
|
||
intro a0 h₂
|
||
apply Exists.elim h₂
|
||
intro a1 ⟨ h₃ , h₄ ⟩
|
||
have h₁' := h₁ a1 h₄
|
||
apply Exists.elim h₁'
|
||
intro mid ⟨ h₅, h₆⟩
|
||
have t := plus_star_trans R a0 a1 mid h₃ h₅
|
||
cases t
|
||
case plus_left mid2 rel2 s =>
|
||
apply Exists.intro mid2
|
||
apply And.intro
|
||
exact rel2
|
||
apply Exists.intro mid
|
||
exact ⟨ s, h₆ ⟩
|
||
|
||
-- Automata theory example that involves forall quantifier
|
||
def DFA (Q : Type) (A : Type) : Type := Q → (Bool × (A → Q))
|
||
|
||
def language_equivalent (automaton : DFA Q A) (q₁ q₂ : Q) : Prop :=
|
||
let ⟨o₁, t₁⟩ := automaton q₁
|
||
let ⟨o₂, t₂⟩ := automaton q₂
|
||
o₁ = o₂ ∧ (∀ a : A, language_equivalent automaton (t₁ a) (t₂ a))
|
||
greatest_fixpoint
|
||
|
||
/--
|
||
info: language_equivalent.fixpoint_induct {Q A : Type} (automaton : DFA Q A) (x : Q → Q → Prop)
|
||
(y :
|
||
∀ (x_1 x_2 : Q),
|
||
x x_1 x_2 →
|
||
(automaton x_1).fst = (automaton x_2).fst ∧ ∀ (a : A), x ((automaton x_1).snd a) ((automaton x_2).snd a))
|
||
(x✝ x✝¹ : Q) : x x✝ x✝¹ → language_equivalent automaton x✝ x✝¹
|
||
-/
|
||
#guard_msgs in
|
||
#check language_equivalent.fixpoint_induct
|