refactor: make CCPO class Prop-valued (#11425)
This PR changes `Lean.Order.CCPO` and `.CompleteLattice` to carry a Prop. This avoids the `CCPO IO` instance from being `noncomputable`.
This commit is contained in:
parent
dd57725244
commit
d60ef53d54
6 changed files with 269 additions and 289 deletions
|
|
@ -64,10 +64,25 @@ This is intended to be used in the construction of `partial_fixpoint`, and not m
|
|||
-/
|
||||
def chain (c : α → Prop) : Prop := ∀ x y , c x → c y → x ⊑ y ∨ y ⊑ x
|
||||
|
||||
def is_sup {α : Sort u} [PartialOrder α] (c : α → Prop) (s : α) : Prop :=
|
||||
∀ x, s ⊑ x ↔ (∀ y, c y → y ⊑ x)
|
||||
|
||||
theorem is_sup_unique {α} [PartialOrder α] {c : α → Prop} {s₁ s₂ : α}
|
||||
(h₁ : is_sup c s₁) (h₂ : is_sup c s₂) : s₁ = s₂ := by
|
||||
apply PartialOrder.rel_antisymm
|
||||
· apply (h₁ s₂).mpr
|
||||
intro y hy
|
||||
apply (h₂ s₂).mp PartialOrder.rel_refl y hy
|
||||
· apply (h₂ s₁).mpr
|
||||
intro y hy
|
||||
apply (h₁ s₁).mp PartialOrder.rel_refl y hy
|
||||
|
||||
end PartialOrder
|
||||
|
||||
section CCPO
|
||||
|
||||
open PartialOrder
|
||||
|
||||
/--
|
||||
A chain-complete partial order (CCPO) is a partial order where every chain has a least upper bound.
|
||||
|
||||
|
|
@ -76,67 +91,75 @@ otherwise.
|
|||
-/
|
||||
class CCPO (α : Sort u) extends PartialOrder α where
|
||||
/--
|
||||
The least upper bound of a chain.
|
||||
|
||||
This is intended to be used in the construction of `partial_fixpoint`, and not meant to be used
|
||||
otherwise.
|
||||
The least upper bound of chains exists.
|
||||
-/
|
||||
csup : (α → Prop) → α
|
||||
/--
|
||||
`csup c` is the least upper bound of the chain `c` when all elements `x` that are at
|
||||
least as large as `csup c` are at least as large as all elements of `c`, and vice versa.
|
||||
-/
|
||||
csup_spec {c : α → Prop} (hc : chain c) : csup c ⊑ x ↔ (∀ y, c y → y ⊑ x)
|
||||
has_csup {c : α → Prop} (hc : chain c) : Exists (is_sup c)
|
||||
|
||||
open PartialOrder CCPO
|
||||
open CCPO
|
||||
|
||||
variable {α : Sort u} [CCPO α]
|
||||
|
||||
theorem csup_le {c : α → Prop} (hchain : chain c) : (∀ y, c y → y ⊑ x) → csup c ⊑ x :=
|
||||
(csup_spec hchain).mpr
|
||||
noncomputable def CCPO.csup {c : α → Prop} (hc : chain c) : α :=
|
||||
Classical.choose (CCPO.has_csup hc)
|
||||
|
||||
theorem le_csup {c : α → Prop} (hchain : chain c) {y : α} (hy : c y) : y ⊑ csup c :=
|
||||
(csup_spec hchain).mp rel_refl y hy
|
||||
theorem CCPO.csup_spec {c : α → Prop} (hc : chain c) : is_sup c (csup hc) :=
|
||||
@fun x => Classical.choose_spec (CCPO.has_csup hc) x
|
||||
|
||||
theorem csup_le {c : α → Prop} (hc : chain c) : (∀ y, c y → y ⊑ x) → csup hc ⊑ x :=
|
||||
(csup_spec hc x).mpr
|
||||
|
||||
theorem le_csup {c : α → Prop} (hc : chain c) {y : α} (hy : c y) : y ⊑ csup hc :=
|
||||
(csup_spec hc (csup hc)).mp rel_refl y hy
|
||||
|
||||
def empty_chain (α) : α → Prop := fun _ => False
|
||||
|
||||
def chain_empty (α : Sort u) [PartialOrder α] : chain (empty_chain α) := by
|
||||
intro x y hx hy; contradiction
|
||||
|
||||
/--
|
||||
The bottom element is the least upper bound of the empty chain.
|
||||
|
||||
This is intended to be used in the construction of `partial_fixpoint`, and not meant to be used otherwise.
|
||||
-/
|
||||
def bot : α := csup (fun _ => False)
|
||||
noncomputable def bot : α := csup (chain_empty α)
|
||||
|
||||
scoped notation "⊥" => bot
|
||||
|
||||
theorem bot_le (x : α) : ⊥ ⊑ x := by
|
||||
apply csup_le
|
||||
· intro x y hx hy; contradiction
|
||||
· intro x hx; contradiction
|
||||
intro x y; contradiction
|
||||
|
||||
end CCPO
|
||||
|
||||
|
||||
section CompleteLattice
|
||||
|
||||
/--
|
||||
A complete lattice is a partial order where every subset has a least upper bound.
|
||||
-/
|
||||
class CompleteLattice (α : Sort u) extends PartialOrder α where
|
||||
/--
|
||||
The least upper bound of an arbitrary subset in the complete_lattice.
|
||||
The least upper bound of an arbitrary subset exists.
|
||||
-/
|
||||
sup : (α → Prop) → α
|
||||
sup_spec {c : α → Prop} : sup c ⊑ x ↔ (∀ y, c y → y ⊑ x)
|
||||
has_sup (c : α → Prop) : Exists (is_sup c)
|
||||
|
||||
open PartialOrder CompleteLattice
|
||||
|
||||
variable {α : Sort u} [CompleteLattice α]
|
||||
|
||||
theorem sup_le {c : α → Prop} : (∀ y, c y → y ⊑ x) → sup c ⊑ x :=
|
||||
(sup_spec).mpr
|
||||
noncomputable def CompleteLattice.sup (c : α → Prop) : α :=
|
||||
Classical.choose (CompleteLattice.has_sup c)
|
||||
|
||||
theorem le_sup {c : α → Prop} {y : α} (hy : c y) : y ⊑ sup c :=
|
||||
sup_spec.mp rel_refl y hy
|
||||
theorem CompleteLattice.sup_spec (c : α → Prop) : is_sup c (sup c) :=
|
||||
@fun x => Classical.choose_spec (CompleteLattice.has_sup c) x
|
||||
|
||||
def inf (c : α → Prop) : α := sup (∀ y, c y → · ⊑ y)
|
||||
theorem sup_le (c : α → Prop) : (∀ y, c y → y ⊑ x) → sup c ⊑ x :=
|
||||
Iff.mpr (sup_spec c x)
|
||||
|
||||
theorem le_sup (c : α → Prop) {y : α} (hy : c y) : y ⊑ sup c :=
|
||||
Iff.mp (sup_spec c (sup c)) rel_refl y hy
|
||||
|
||||
noncomputable def inf (c : α → Prop) : α := sup (∀ y, c y → · ⊑ y)
|
||||
|
||||
theorem inf_spec {c : α → Prop} : x ⊑ inf c ↔ (∀ y, c y → x ⊑ y) where
|
||||
mp := by
|
||||
|
|
@ -204,7 +227,7 @@ from this definition, and `P ⊥` is a separate condition of the induction predi
|
|||
This is intended to be used in the construction of `partial_fixpoint`, and not meant to be used otherwise.
|
||||
-/
|
||||
def admissible (P : α → Prop) :=
|
||||
∀ (c : α → Prop), chain c → (∀ x, c x → P x) → P (csup c)
|
||||
∀ (c : α → Prop) (hc : chain c), (∀ x, c x → P x) → P (csup hc)
|
||||
|
||||
theorem admissible_const_true : admissible (fun (_ : α) => True) :=
|
||||
fun _ _ _ => trivial
|
||||
|
|
@ -220,7 +243,7 @@ theorem chain_conj (c P : α → Prop) (hchain : chain c) : chain (fun x => c x
|
|||
exact hchain x y hcx hcy
|
||||
|
||||
theorem csup_conj (c P : α → Prop) (hchain : chain c) (h : ∀ x, c x → ∃ y, c y ∧ x ⊑ y ∧ P y) :
|
||||
csup c = csup (fun x => c x ∧ P x) := by
|
||||
csup hchain = csup (chain_conj c P hchain) := by
|
||||
apply rel_antisymm
|
||||
· apply csup_le hchain
|
||||
intro x hcx
|
||||
|
|
@ -281,12 +304,12 @@ variable {c : α → Prop}
|
|||
-- Note that monotonicity is not required for the definition of `lfp`
|
||||
-- but it is required to show that `lfp` is a fixpoint of `f`.
|
||||
|
||||
def lfp (f : α → α) : α :=
|
||||
noncomputable def lfp (f : α → α) : α :=
|
||||
inf (fun c => f c ⊑ c)
|
||||
|
||||
set_option linter.unusedVariables false in
|
||||
-- The following definition takes a witness that a function is monotone
|
||||
def lfp_monotone (f : α → α) (hm : monotone f) : α :=
|
||||
noncomputable def lfp_monotone (f : α → α) (hm : monotone f) : α :=
|
||||
lfp f
|
||||
|
||||
-- Showing that `lfp` is a prefixed point makes use of monotonicity
|
||||
|
|
@ -355,7 +378,7 @@ This is intended to be used in the construction of `partial_fixpoint`, and not m
|
|||
-/
|
||||
inductive iterates (f : α → α) : α → Prop where
|
||||
| step : iterates f x → iterates f (f x)
|
||||
| sup {c : α → Prop} (hc : chain c) (hi : ∀ x, c x → iterates f x) : iterates f (csup c)
|
||||
| sup {c : α → Prop} (hc : chain c) (hi : ∀ x, c x → iterates f x) : iterates f (csup hc)
|
||||
|
||||
theorem chain_iterates {f : α → α} (hf : monotone f) : chain (iterates f) := by
|
||||
intro x y hx hy
|
||||
|
|
@ -367,7 +390,7 @@ theorem chain_iterates {f : α → α} (hf : monotone f) : chain (iterates f) :=
|
|||
· left; apply hf; assumption
|
||||
· right; apply hf; assumption
|
||||
case sup c hchain hi ih2 =>
|
||||
change f x ⊑ csup c ∨ csup c ⊑ f x
|
||||
change f x ⊑ csup hchain ∨ csup hchain ⊑ f x
|
||||
by_cases h : ∃ z, c z ∧ f x ⊑ z
|
||||
· left
|
||||
obtain ⟨z, hz, hfz⟩ := h
|
||||
|
|
@ -384,7 +407,7 @@ theorem chain_iterates {f : α → α} (hf : monotone f) : chain (iterates f) :=
|
|||
next => contradiction
|
||||
next => assumption
|
||||
case sup c hchain hi ih =>
|
||||
change rel (csup c) y ∨ rel y (csup c)
|
||||
change rel (csup hchain) y ∨ rel y (csup hchain)
|
||||
by_cases h : ∃ z, c z ∧ rel y z
|
||||
· right
|
||||
obtain ⟨z, hz, hfz⟩ := h
|
||||
|
|
@ -423,7 +446,7 @@ definition is not very meaningful and it simplifies applying theorems like `fix_
|
|||
|
||||
This is intended to be used in the construction of `partial_fixpoint`, and not meant to be used otherwise.
|
||||
-/
|
||||
def fix (f : α → α) (hmono : monotone f) := csup (iterates f)
|
||||
noncomputable def fix (f : α → α) (hmono : monotone f) := csup (chain_iterates hmono)
|
||||
|
||||
/--
|
||||
The main fixpoint theorem for fixed points of monotone functions in chain-complete partial orders.
|
||||
|
|
@ -488,49 +511,66 @@ theorem chain_apply [∀ x, PartialOrder (β x)] {c : (∀ x, β x) → Prop} (h
|
|||
next h => left; apply h x
|
||||
next h => right; apply h x
|
||||
|
||||
def fun_csup [∀ x, CCPO (β x)] (c : (∀ x, β x) → Prop) (x : α) :=
|
||||
CCPO.csup (fun y => ∃ f, c f ∧ f x = y)
|
||||
noncomputable def fun_csup [∀ x, CCPO (β x)] (c : (∀ x, β x) → Prop) (hc : chain c) (x : α) :=
|
||||
CCPO.csup (chain_apply hc x)
|
||||
|
||||
def fun_sup [∀ x, CompleteLattice (β x)] (c : (∀ x, β x) → Prop) (x : α) :=
|
||||
CompleteLattice.sup (fun y => ∃ f, c f ∧ f x = y)
|
||||
theorem fun_csup_is_sup [∀ x, CCPO (β x)] (c : (∀ x, β x) → Prop) (hc : chain c) :
|
||||
is_sup c (fun_csup c hc) := by
|
||||
intro f
|
||||
constructor
|
||||
next =>
|
||||
intro hf g hg x
|
||||
apply rel_trans _ (hf x); clear hf
|
||||
apply le_csup (chain_apply hc x)
|
||||
exact ⟨g, hg, rfl⟩
|
||||
next =>
|
||||
intro h x
|
||||
apply csup_le (chain_apply hc x)
|
||||
intro y ⟨z, hz, hyz⟩
|
||||
subst y
|
||||
apply h z hz
|
||||
|
||||
instance instCCPOPi [∀ x, CCPO (β x)] : CCPO (∀ x, β x) where
|
||||
csup := fun_csup
|
||||
csup_spec := by
|
||||
intro f c hc
|
||||
constructor
|
||||
next =>
|
||||
intro hf g hg x
|
||||
apply rel_trans _ (hf x); clear hf
|
||||
apply le_csup (chain_apply hc x)
|
||||
exact ⟨g, hg, rfl⟩
|
||||
next =>
|
||||
intro h x
|
||||
apply csup_le (chain_apply hc x)
|
||||
intro y ⟨z, hz, hyz⟩
|
||||
subst y
|
||||
apply h z hz
|
||||
has_csup hc := ⟨fun_csup _ hc, fun_csup_is_sup _ hc⟩
|
||||
|
||||
theorem fun_csup_eq [∀ x, CCPO (β x)] (c : (∀ x, β x) → Prop) (hc : chain c) :
|
||||
fun_csup c hc = CCPO.csup hc := by
|
||||
apply is_sup_unique (c := c)
|
||||
· apply fun_csup_is_sup
|
||||
· apply CCPO.csup_spec
|
||||
|
||||
noncomputable def fun_sup [∀ x, CompleteLattice (β x)] (c : (∀ x, β x) → Prop) (x : α) :=
|
||||
CompleteLattice.sup (fun y => ∃ f, c f ∧ f x = y)
|
||||
|
||||
theorem fun_sup_is_sup [∀ x, CompleteLattice (β x)] (c : (∀ x, β x) → Prop) :
|
||||
is_sup c (fun_sup c) := by
|
||||
intro f
|
||||
constructor
|
||||
case mp =>
|
||||
intro hf g hg x
|
||||
apply rel_trans _ (hf x)
|
||||
apply le_sup
|
||||
exact ⟨g, hg, rfl⟩
|
||||
case mpr =>
|
||||
intro h x
|
||||
apply sup_le
|
||||
intro y ⟨z, hz, hyz⟩
|
||||
subst y
|
||||
apply h z hz
|
||||
|
||||
instance instCompleteLatticePi [∀ x, CompleteLattice (β x)] : CompleteLattice (∀ x, β x) where
|
||||
sup := fun_sup
|
||||
sup_spec := by
|
||||
intro f c
|
||||
constructor
|
||||
case mp =>
|
||||
intro hf g hg x
|
||||
apply rel_trans _ (hf x)
|
||||
apply le_sup
|
||||
exact ⟨g, hg, rfl⟩
|
||||
case mpr =>
|
||||
intro h x
|
||||
apply sup_le
|
||||
intro y ⟨z, hz, hyz⟩
|
||||
subst y
|
||||
apply h z hz
|
||||
has_sup c := ⟨fun_sup c, fun_sup_is_sup c⟩
|
||||
|
||||
theorem fun_sup_eq [∀ x, CompleteLattice (β x)] (c : (∀ x, β x) → Prop) :
|
||||
fun_sup c = CompleteLattice.sup c := by
|
||||
apply is_sup_unique (c := c)
|
||||
· apply fun_sup_is_sup
|
||||
· apply CompleteLattice.sup_spec
|
||||
|
||||
def admissible_apply [∀ x, CCPO (β x)] (P : ∀ x, β x → Prop) (x : α)
|
||||
(hadm : admissible (P x)) : admissible (fun (f : ∀ x, β x) => P x (f x)) := by
|
||||
intro c hchain h
|
||||
rw [← fun_csup_eq]
|
||||
apply hadm _ (chain_apply hchain x)
|
||||
rintro _ ⟨f, hcf, rfl⟩
|
||||
apply h _ hcf
|
||||
|
|
@ -622,67 +662,84 @@ theorem PProd.chain.chain_snd [CCPO α] [CCPO β] {c : α ×' β → Prop} (hcha
|
|||
case inl h => left; exact h.2
|
||||
case inr h => right; exact h.2
|
||||
|
||||
instance instCompleteLatticePProd [CompleteLattice α] [CompleteLattice β] : CompleteLattice (α ×' β) where
|
||||
sup c := ⟨CompleteLattice.sup (PProd.fst c), CompleteLattice.sup (PProd.snd c)⟩
|
||||
sup_spec := by
|
||||
intro ⟨a, b⟩ c
|
||||
constructor
|
||||
case mp =>
|
||||
intro ⟨h₁, h₂⟩ ⟨a', b'⟩ cab
|
||||
constructor <;> dsimp only at *
|
||||
· apply rel_trans ?_ h₁
|
||||
unfold PProd.fst at *
|
||||
apply le_sup
|
||||
apply Exists.intro b'
|
||||
exact cab
|
||||
. apply rel_trans ?_ h₂
|
||||
apply le_sup
|
||||
unfold PProd.snd at *
|
||||
apply Exists.intro a'
|
||||
exact cab
|
||||
case mpr =>
|
||||
intro h
|
||||
constructor <;> dsimp only
|
||||
. apply sup_le
|
||||
unfold PProd.fst
|
||||
intro y' ex
|
||||
apply Exists.elim ex
|
||||
intro b' hc
|
||||
apply (h ⟨y', b' ⟩ hc).1
|
||||
. apply sup_le
|
||||
unfold PProd.snd
|
||||
intro b' ex
|
||||
apply Exists.elim ex
|
||||
intro y' hc
|
||||
apply (h ⟨y', b' ⟩ hc).2
|
||||
noncomputable def prod_csup [CCPO α] [CCPO β] (c : α ×' β → Prop) (hchain : chain c) : α ×' β :=
|
||||
⟨CCPO.csup (PProd.chain.chain_fst hchain), CCPO.csup (PProd.chain.chain_snd hchain)⟩
|
||||
|
||||
theorem prod_csup_is_sup [CCPO α] [CCPO β] (c : α ×' β → Prop) (hchain : chain c) :
|
||||
is_sup c (prod_csup c hchain) := by
|
||||
intro ⟨a, b⟩
|
||||
constructor
|
||||
next =>
|
||||
intro ⟨h₁, h₂⟩ ⟨a', b'⟩ cab
|
||||
constructor <;> dsimp at *
|
||||
· apply rel_trans ?_ h₁
|
||||
apply le_csup (PProd.chain.chain_fst hchain)
|
||||
exact ⟨b', cab⟩
|
||||
· apply rel_trans ?_ h₂
|
||||
apply le_csup (PProd.chain.chain_snd hchain)
|
||||
exact ⟨a', cab⟩
|
||||
next =>
|
||||
intro h
|
||||
constructor <;> dsimp
|
||||
· apply csup_le (PProd.chain.chain_fst hchain)
|
||||
intro a' ⟨b', hcab⟩
|
||||
apply (h _ hcab).1
|
||||
· apply csup_le (PProd.chain.chain_snd hchain)
|
||||
intro b' ⟨a', hcab⟩
|
||||
apply (h _ hcab).2
|
||||
|
||||
instance instCCPOPProd [CCPO α] [CCPO β] : CCPO (α ×' β) where
|
||||
csup c := ⟨CCPO.csup (PProd.chain.fst c), CCPO.csup (PProd.chain.snd c)⟩
|
||||
csup_spec := by
|
||||
intro ⟨a, b⟩ c hchain
|
||||
constructor
|
||||
next =>
|
||||
intro ⟨h₁, h₂⟩ ⟨a', b'⟩ cab
|
||||
constructor <;> dsimp at *
|
||||
· apply rel_trans ?_ h₁
|
||||
apply le_csup (PProd.chain.chain_fst hchain)
|
||||
exact ⟨b', cab⟩
|
||||
· apply rel_trans ?_ h₂
|
||||
apply le_csup (PProd.chain.chain_snd hchain)
|
||||
exact ⟨a', cab⟩
|
||||
next =>
|
||||
intro h
|
||||
constructor <;> dsimp
|
||||
· apply csup_le (PProd.chain.chain_fst hchain)
|
||||
intro a' ⟨b', hcab⟩
|
||||
apply (h _ hcab).1
|
||||
· apply csup_le (PProd.chain.chain_snd hchain)
|
||||
intro b' ⟨a', hcab⟩
|
||||
apply (h _ hcab).2
|
||||
has_csup hchain := ⟨prod_csup _ hchain, prod_csup_is_sup _ hchain⟩
|
||||
|
||||
theorem prod_csup_eq [CCPO α] [CCPO β] (c : α ×' β → Prop) (hchain : chain c) :
|
||||
prod_csup c hchain = CCPO.csup hchain := by
|
||||
apply is_sup_unique (c := c)
|
||||
· apply prod_csup_is_sup
|
||||
· apply CCPO.csup_spec
|
||||
|
||||
noncomputable def prod_sup [CompleteLattice α] [CompleteLattice β] (c : α ×' β → Prop) : α ×' β :=
|
||||
⟨CompleteLattice.sup (PProd.fst c), CompleteLattice.sup (PProd.snd c)⟩
|
||||
|
||||
theorem prod_sup_is_sup [CompleteLattice α] [CompleteLattice β] (c : α ×' β → Prop) :
|
||||
is_sup c (prod_sup c) := by
|
||||
intro ⟨a, b⟩
|
||||
constructor
|
||||
case mp =>
|
||||
intro ⟨h₁, h₂⟩ ⟨a', b'⟩ cab
|
||||
constructor <;> dsimp only at *
|
||||
· apply rel_trans ?_ h₁
|
||||
unfold prod_sup PProd.fst at *
|
||||
apply le_sup
|
||||
apply Exists.intro b'
|
||||
exact cab
|
||||
. apply rel_trans ?_ h₂
|
||||
apply le_sup
|
||||
unfold PProd.snd at *
|
||||
apply Exists.intro a'
|
||||
exact cab
|
||||
case mpr =>
|
||||
intro h
|
||||
constructor <;> dsimp only
|
||||
. apply sup_le
|
||||
unfold PProd.fst
|
||||
intro y' ex
|
||||
apply Exists.elim ex
|
||||
intro b' hc
|
||||
apply (h ⟨y', b' ⟩ hc).1
|
||||
. apply sup_le
|
||||
unfold PProd.snd
|
||||
intro b' ex
|
||||
apply Exists.elim ex
|
||||
intro y' hc
|
||||
apply (h ⟨y', b' ⟩ hc).2
|
||||
|
||||
instance instCompleteLatticePProd [CompleteLattice α] [CompleteLattice β] : CompleteLattice (α ×' β) where
|
||||
has_sup c := ⟨prod_sup c, prod_sup_is_sup c⟩
|
||||
|
||||
theorem admissible_pprod_fst {α : Sort u} {β : Sort v} [CCPO α] [CCPO β] (P : α → Prop)
|
||||
(hadm : admissible P) : admissible (fun (x : α ×' β) => P x.1) := by
|
||||
intro c hchain h
|
||||
rw [<- prod_csup_eq]
|
||||
apply hadm _ (PProd.chain.chain_fst hchain)
|
||||
intro x ⟨y, hxy⟩
|
||||
apply h ⟨x,y⟩ hxy
|
||||
|
|
@ -690,6 +747,7 @@ theorem admissible_pprod_fst {α : Sort u} {β : Sort v} [CCPO α] [CCPO β] (P
|
|||
theorem admissible_pprod_snd {α : Sort u} {β : Sort v} [CCPO α] [CCPO β] (P : β → Prop)
|
||||
(hadm : admissible P) : admissible (fun (x : α ×' β) => P x.2) := by
|
||||
intro c hchain h
|
||||
rw [<- prod_csup_eq]
|
||||
apply hadm _ (PProd.chain.chain_snd hchain)
|
||||
intro y ⟨x, hxy⟩
|
||||
apply h ⟨x,y⟩ hxy
|
||||
|
|
@ -736,49 +794,57 @@ noncomputable def flat_csup (c : FlatOrder b → Prop) : FlatOrder b := by
|
|||
· exact Classical.choose h
|
||||
· exact b
|
||||
|
||||
noncomputable instance FlatOrder.instCCPO : CCPO (FlatOrder b) where
|
||||
csup := flat_csup
|
||||
csup_spec := by
|
||||
intro x c hc
|
||||
unfold flat_csup
|
||||
split
|
||||
next hex =>
|
||||
apply Classical.some_spec₂ (q := (· ⊑ x ↔ (∀ y, c y → y ⊑ x)))
|
||||
clear hex
|
||||
intro z ⟨hz, hnb⟩
|
||||
constructor
|
||||
· intro h y hy
|
||||
apply PartialOrder.rel_trans _ h; clear h
|
||||
cases hc y z hy hz
|
||||
next => assumption
|
||||
next h =>
|
||||
cases h
|
||||
· contradiction
|
||||
· constructor
|
||||
· intro h
|
||||
cases h z hz
|
||||
theorem flat_csup_is_sup (c : FlatOrder b → Prop) (hc : chain c) :
|
||||
is_sup c (flat_csup c) := by
|
||||
intro x
|
||||
unfold flat_csup
|
||||
split
|
||||
next hex =>
|
||||
apply Classical.some_spec₂ (q := (· ⊑ x ↔ (∀ y, c y → y ⊑ x)))
|
||||
clear hex
|
||||
intro z ⟨hz, hnb⟩
|
||||
constructor
|
||||
· intro h y hy
|
||||
apply PartialOrder.rel_trans _ h; clear h
|
||||
cases hc y z hy hz
|
||||
next => assumption
|
||||
next h =>
|
||||
cases h
|
||||
· contradiction
|
||||
· constructor
|
||||
next hnotex =>
|
||||
constructor
|
||||
· intro h y hy; clear h
|
||||
suffices y = b by rw [this]; exact rel.bot
|
||||
rw [not_exists] at hnotex
|
||||
specialize hnotex y
|
||||
rw [not_and] at hnotex
|
||||
specialize hnotex hy
|
||||
rw [@Classical.not_not] at hnotex
|
||||
assumption
|
||||
· intro; exact rel.bot
|
||||
· intro h
|
||||
cases h z hz
|
||||
· contradiction
|
||||
· constructor
|
||||
next hnotex =>
|
||||
constructor
|
||||
· intro h y hy; clear h
|
||||
suffices y = b by rw [this]; exact FlatOrder.rel.bot
|
||||
rw [not_exists] at hnotex
|
||||
specialize hnotex y
|
||||
rw [not_and] at hnotex
|
||||
specialize hnotex hy
|
||||
rw [@Classical.not_not] at hnotex
|
||||
assumption
|
||||
· intro; exact FlatOrder.rel.bot
|
||||
|
||||
instance FlatOrder.instCCPO : CCPO (FlatOrder b) where
|
||||
has_csup hchain := ⟨flat_csup _ , flat_csup_is_sup _ hchain⟩
|
||||
|
||||
theorem flat_csup_eq (c : FlatOrder b → Prop) (hchain : chain c) :
|
||||
flat_csup c = CCPO.csup hchain := by
|
||||
apply is_sup_unique (c := c)
|
||||
· apply flat_csup_is_sup _ hchain
|
||||
· apply CCPO.csup_spec
|
||||
|
||||
theorem admissible_flatOrder (P : FlatOrder b → Prop) (hnot : P b) : admissible P := by
|
||||
intro c hchain h
|
||||
by_cases h' : ∃ (x : FlatOrder b), c x ∧ x ≠ b
|
||||
· simp [CCPO.csup, flat_csup, h']
|
||||
· simp [← flat_csup_eq, flat_csup, h']
|
||||
apply Classical.some_spec₂ (q := (P ·))
|
||||
intro x ⟨hcx, hneb⟩
|
||||
apply h x hcx
|
||||
· simp [CCPO.csup, flat_csup, h', hnot]
|
||||
· simp [← flat_csup_eq, flat_csup, h', hnot]
|
||||
|
||||
end flat_order
|
||||
|
||||
|
|
@ -809,8 +875,8 @@ theorem monotone_bind
|
|||
· apply MonoBind.bind_mono_right (fun y => monotone_apply y _ hmono₂ _ _ hx₁₂)
|
||||
|
||||
instance : PartialOrder (Option α) := inferInstanceAs (PartialOrder (FlatOrder none))
|
||||
noncomputable instance : CCPO (Option α) := inferInstanceAs (CCPO (FlatOrder none))
|
||||
noncomputable instance : MonoBind Option where
|
||||
instance : CCPO (Option α) := inferInstanceAs (CCPO (FlatOrder none))
|
||||
instance : MonoBind Option where
|
||||
bind_mono_left h := by
|
||||
cases h
|
||||
· exact FlatOrder.rel.bot
|
||||
|
|
@ -921,12 +987,22 @@ theorem monotone_stateTRun [PartialOrder γ]
|
|||
monotone (fun (x : γ) => StateT.run (f x) s) :=
|
||||
monotone_apply s _ hmono
|
||||
|
||||
-- TODO: axiomatize these instances (ideally without `Nonempty ε`) when EIO and friends are opaque
|
||||
noncomputable def EST.bot [Nonempty ε] : EST ε σ α :=
|
||||
fun s => .error Classical.ofNonempty (Classical.choice ⟨s⟩)
|
||||
|
||||
noncomputable instance [Nonempty ε] : CCPO (EST ε σ α) :=
|
||||
inferInstanceAs (CCPO ((s : _) → FlatOrder (.error Classical.ofNonempty (Classical.choice ⟨s⟩))))
|
||||
-- Essentially
|
||||
-- instance [Nonempty ε] : CCPO (EST ε σ α) :=
|
||||
-- inferInstanceAs (CCPO ((s : _) → FlatOrder (EST.bot s)))
|
||||
-- but hat would incur a noncomputable on the instance
|
||||
|
||||
noncomputable instance [Nonempty ε] : MonoBind (EST ε σ) where
|
||||
instance [Nonempty ε] : CCPO (EST ε σ α) where
|
||||
rel := PartialOrder.rel (α := ∀ s, FlatOrder (EST.bot s))
|
||||
rel_refl := PartialOrder.rel_refl
|
||||
rel_antisymm := PartialOrder.rel_antisymm
|
||||
rel_trans := PartialOrder.rel_trans
|
||||
has_csup hchain := CCPO.has_csup (α := ∀ s, FlatOrder (EST.bot s)) hchain
|
||||
|
||||
instance [Nonempty ε] : MonoBind (EST ε σ) where
|
||||
bind_mono_left {_ _ a₁ a₂ f} h₁₂ := by
|
||||
intro s
|
||||
specialize h₁₂ s
|
||||
|
|
@ -944,18 +1020,18 @@ noncomputable instance [Nonempty ε] : MonoBind (EST ε σ) where
|
|||
· apply h₁₂
|
||||
· exact .refl
|
||||
|
||||
noncomputable instance [Nonempty α] : CCPO (ST σ α) :=
|
||||
inferInstanceAs (CCPO ((s : _) → FlatOrder (.mk Classical.ofNonempty (Classical.choice ⟨s⟩))))
|
||||
|
||||
noncomputable instance [Nonempty α] : CCPO (BaseIO α) :=
|
||||
inferInstanceAs (CCPO (ST IO.RealWorld α))
|
||||
|
||||
noncomputable instance [Nonempty ε] : CCPO (EIO ε α) :=
|
||||
instance [Nonempty ε] : CCPO (EIO ε α) :=
|
||||
inferInstanceAs (CCPO (EST ε IO.RealWorld α))
|
||||
|
||||
noncomputable instance [Nonempty ε] : MonoBind (EIO ε) :=
|
||||
instance [Nonempty ε] : MonoBind (EIO ε) :=
|
||||
inferInstanceAs (MonoBind (EST ε IO.RealWorld))
|
||||
|
||||
instance : CCPO (IO α) :=
|
||||
inferInstanceAs (CCPO (EIO IO.Error α))
|
||||
|
||||
instance : MonoBind IO :=
|
||||
inferInstanceAs (MonoBind (EIO IO.Error))
|
||||
|
||||
end mono_bind
|
||||
|
||||
section implication_order
|
||||
|
|
@ -970,9 +1046,9 @@ instance ImplicationOrder.instOrder : PartialOrder ImplicationOrder where
|
|||
|
||||
-- This defines a complete lattice on `Prop`, used to define inductive predicates
|
||||
instance ImplicationOrder.instCompleteLattice : CompleteLattice ImplicationOrder where
|
||||
sup c := ∃ p, c p ∧ p
|
||||
sup_spec := by
|
||||
intro x c
|
||||
has_sup c := by
|
||||
exists ∃ p, c p ∧ p
|
||||
intro x
|
||||
constructor
|
||||
case mp =>
|
||||
intro h y cy hy
|
||||
|
|
@ -1032,9 +1108,9 @@ instance ReverseImplicationOrder.instOrder : PartialOrder ReverseImplicationOrde
|
|||
|
||||
-- This defines a complete lattice on `Prop`, used to define coinductive predicates
|
||||
instance ReverseImplicationOrder.instCompleteLattice : CompleteLattice ReverseImplicationOrder where
|
||||
sup c := ∀ p, c p → p
|
||||
sup_spec := by
|
||||
intro x c
|
||||
has_sup c := by
|
||||
exists ∀ p, c p → p
|
||||
intro x
|
||||
constructor
|
||||
case mp =>
|
||||
intro h y cy l
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
set_option warn.sorry false
|
||||
|
||||
open Lean.Order
|
||||
|
||||
def A : Type := Prop
|
||||
|
|
@ -16,12 +18,10 @@ instance : Lean.Order.PartialOrder B where
|
|||
rel_antisymm := sorry
|
||||
|
||||
instance : Lean.Order.CCPO A where
|
||||
csup := sorry
|
||||
csup_spec := sorry
|
||||
has_csup := sorry
|
||||
|
||||
instance : Lean.Order.CCPO B where
|
||||
csup := sorry
|
||||
csup_spec := sorry
|
||||
has_csup := sorry
|
||||
|
||||
/--
|
||||
error: Could not prove 'tick' to be monotone in its recursive calls:
|
||||
|
|
|
|||
|
|
@ -1,97 +0,0 @@
|
|||
/-!
|
||||
Johannes Hölzl pointed out that the `partial_fixpoint` machinery can be applied to `Prop` to define
|
||||
inductive or (when using the dual order) coinductive predicates.
|
||||
|
||||
Without an induction principle this isn't so useful, though.
|
||||
-/
|
||||
|
||||
open Lean.Order
|
||||
|
||||
instance : PartialOrder Prop where
|
||||
rel x y := y → x -- NB: Dual
|
||||
rel_refl := fun x => x
|
||||
rel_trans h₁ h₂ := fun x => h₁ (h₂ x)
|
||||
rel_antisymm h₁ h₂ := propext ⟨h₂, h₁⟩
|
||||
|
||||
instance : CCPO Prop where
|
||||
csup c := ∀ p, c p → p
|
||||
csup_spec := fun _ =>
|
||||
⟨fun h y hcy hx => h hx y hcy, fun h hx y hcy => h y hcy hx ⟩
|
||||
|
||||
@[partial_fixpoint_monotone] theorem monotone_exists
|
||||
{α} [PartialOrder α] {β} (f : α → β → Prop)
|
||||
(h : monotone f) :
|
||||
monotone (fun x => Exists (f x)) :=
|
||||
fun x y hxy ⟨w, hw⟩ => ⟨w, monotone_apply w f h x y hxy hw⟩
|
||||
|
||||
@[partial_fixpoint_monotone] theorem monotone_and
|
||||
{α} [PartialOrder α] (f₁ : α → Prop) (f₂ : α → Prop)
|
||||
(h₁ : monotone f₁) (h₂ : monotone f₂) :
|
||||
monotone (fun x => f₁ x ∧ f₂ x) :=
|
||||
fun x y hxy ⟨hfx₁, hfx₂⟩ => ⟨h₁ x y hxy hfx₁, h₂ x y hxy hfx₂⟩
|
||||
|
||||
def univ (n : Nat) : Prop :=
|
||||
univ (n + 1)
|
||||
partial_fixpoint
|
||||
|
||||
/-
|
||||
The following models a coinductive predicate defined as
|
||||
```
|
||||
coinductive infinite_chain step : α → Prop where
|
||||
| intro : ∀ y x, step x = some y → infinite_chain step y → infinite_chain step
|
||||
```
|
||||
-/
|
||||
def infinite_chain {α} (step : α → Option α) (x : α) : Prop :=
|
||||
∃ y, step x = some y ∧ infinite_chain step y
|
||||
partial_fixpoint
|
||||
|
||||
theorem infinite_chain.intro {α} (step : α → Option α) (y x : α) :
|
||||
step x = some y → infinite_chain step y → infinite_chain step x := by
|
||||
intros; unfold infinite_chain; simp [*]
|
||||
|
||||
theorem infinite_chain.coinduct {α} (P : α → Prop) (step : α → Option α)
|
||||
(h : ∀ (x : α), P x → ∃ y, step x = some y ∧ P y) :
|
||||
∀ x, P x → infinite_chain step x := by
|
||||
apply infinite_chain.fixpoint_induct step
|
||||
(motive := fun i => ∀ (x : α), P x → i x)
|
||||
case adm =>
|
||||
clear h step
|
||||
apply admissible_pi
|
||||
intro a
|
||||
intro c hchain h hPa Q ⟨f, hcf, hfaQ⟩
|
||||
subst Q
|
||||
apply h f hcf hPa
|
||||
case h =>
|
||||
intro ic hPic x hPx
|
||||
obtain ⟨y, hstepx, h⟩ := h x hPx
|
||||
exact ⟨y, hstepx, hPic y h⟩
|
||||
|
||||
/--
|
||||
Isabelle generates a stronger coinduction theorem from
|
||||
```
|
||||
coinductive infinite_chain :: "('a ⇒ 'a option) ⇒ 'a ⇒ bool" for step :: "'a ⇒ 'a option" where
|
||||
intro: "infinite_chain step x" if "step x = Some y" and "infinite_chain step y"
|
||||
```
|
||||
Note the occurrence of `infinite_chain` in the step:
|
||||
```
|
||||
Scratch.infinite_chain.coinduct:
|
||||
?X ?x ⟹
|
||||
(⋀x. ?X x ⟹ ∃xa y. x = xa ∧ ?step xa = Some y ∧ (?X y ∨ infinite_chain ?step y)) ⟹
|
||||
infinite_chain ?step ?x
|
||||
```
|
||||
We can prove that from the one above.
|
||||
-/
|
||||
theorem infinite_chain.coinduct_strong {α} (P : α → Prop) (step : α → Option α)
|
||||
(h : ∀ (x : α), P x → ∃ y, step x = some y ∧ (P y ∨ infinite_chain step y)) :
|
||||
∀ x, P x → infinite_chain step x := by
|
||||
suffices ∀ x, (P x ∨ infinite_chain step x) → infinite_chain step x by
|
||||
intro x hPx
|
||||
exact this x (.inl hPx)
|
||||
apply infinite_chain.coinduct
|
||||
intro x hor
|
||||
cases hor
|
||||
next hPx => exact h _ hPx
|
||||
next hicx =>
|
||||
unfold infinite_chain at hicx
|
||||
obtain ⟨y, hstepx, h⟩ := hicx
|
||||
exact ⟨y, hstepx, .inr h⟩
|
||||
|
|
@ -9,7 +9,7 @@ Using an `Option`-based monad
|
|||
abbrev M1 := ReaderT String (StateT String.Pos.Raw Option)
|
||||
|
||||
def parseAll1 (x : M1 α) : M1 (List α) := do
|
||||
if (← read).atEnd (← get) then
|
||||
if String.Pos.Raw.atEnd (← read) (← get) then
|
||||
return []
|
||||
let val ← x
|
||||
let list ← parseAll1 x
|
||||
|
|
@ -26,7 +26,7 @@ theorem parseAll1.eq_1 : ∀ {α : Type} (x : M1 α),
|
|||
let val ← x
|
||||
let list ← parseAll1 x
|
||||
pure (val :: list)
|
||||
if __do_lift.atEnd __do_lift_1 = true then pure []
|
||||
if String.Pos.Raw.atEnd __do_lift __do_lift_1 = true then pure []
|
||||
else do
|
||||
let y ← pure PUnit.unit
|
||||
__do_jp y
|
||||
|
|
@ -40,7 +40,7 @@ Using an `IO`-based monad
|
|||
abbrev M2 := ReaderT String (StateRefT String.Pos.Raw IO)
|
||||
|
||||
def parseAll2 (x : M2 α) : M2 (List α) := do
|
||||
if (← read).atEnd (← get) then
|
||||
if String.Pos.Raw.atEnd (← read) (← get) then
|
||||
return []
|
||||
let val ← x
|
||||
let list ← parseAll2 x
|
||||
|
|
@ -57,7 +57,7 @@ theorem parseAll2.eq_1 : ∀ {α : Type} (x : M2 α),
|
|||
let val ← x
|
||||
let list ← parseAll2 x
|
||||
pure (val :: list)
|
||||
if __do_lift.atEnd __do_lift_1 = true then pure []
|
||||
if String.Pos.Raw.atEnd __do_lift __do_lift_1 = true then pure []
|
||||
else do
|
||||
let y ← pure PUnit.unit
|
||||
__do_jp y
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
set_option warn.sorry false
|
||||
|
||||
axiom A : Type
|
||||
axiom B : Type
|
||||
|
||||
|
|
@ -10,12 +12,10 @@ instance : PartialOrder A := sorry
|
|||
-- It’s important that the CCPO instance isn't completely axiomatic, so that
|
||||
-- `instCCPO.toOrder` is defeq to `instOrder`
|
||||
instance : CCPO A where
|
||||
csup := sorry
|
||||
csup_spec := sorry
|
||||
has_csup := sorry
|
||||
instance : PartialOrder B := sorry
|
||||
instance : CCPO B where
|
||||
csup := sorry
|
||||
csup_spec := sorry
|
||||
has_csup := sorry
|
||||
|
||||
@[partial_fixpoint_monotone] axiom monotone_toA :
|
||||
∀ {α} [PartialOrder α] (f : α → B), monotone f → monotone (fun x => B.toA (f x))
|
||||
|
|
|
|||
|
|
@ -67,9 +67,10 @@ noncomputable instance : PartialOrder (Distr α) where
|
|||
rel_antisymm h1 h2 := funext (fun _ => ENNReal.le_antisymm (h1 _) (h2 _))
|
||||
|
||||
noncomputable instance : CCPO (Distr α) where
|
||||
csup c x := ENNReal.sup fun (Distr : Subtype c) => Distr.val x
|
||||
csup_spec := by
|
||||
intro d₁ c hchain
|
||||
has_csup := by
|
||||
intro c hchain
|
||||
exists fun x => ENNReal.sup fun (Distr : Subtype c) => Distr.val x
|
||||
intro d₁
|
||||
constructor
|
||||
next =>
|
||||
intro h d₂ hd₂ x
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue