Skip to content

Commit 9f30a23

Browse files
committed
refactor: make CCPO class Prop-valued
This PR changes Lean.Order.CCPO to carry a Prop. This way fewer instances have to be noncomputable.
1 parent a4f9a79 commit 9f30a23

File tree

1 file changed

+147
-98
lines changed

1 file changed

+147
-98
lines changed

src/Init/Internal/Order/Basic.lean

Lines changed: 147 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -68,49 +68,68 @@ end PartialOrder
6868

6969
section CCPO
7070

71+
open PartialOrder
72+
73+
def is_csup {α : Sort u} [PartialOrder α] (c : α → Prop) (s : α) : Prop :=
74+
∀ x, s ⊑ x ↔ (∀ y, c y → y ⊑ x)
75+
76+
theorem is_csup_unique {α} [PartialOrder α] {c : α → Prop} {s₁ s₂ : α}
77+
(h₁ : is_csup c s₁) (h₂ : is_csup c s₂) : s₁ = s₂ := by
78+
apply rel_antisymm
79+
· apply (h₁ s₂).mpr
80+
intro y hy
81+
apply (h₂ s₂).mp rel_refl y hy
82+
· apply (h₂ s₁).mpr
83+
intro y hy
84+
apply (h₁ s₁).mp rel_refl y hy
85+
86+
7187
/--
7288
A chain-complete partial order (CCPO) is a partial order where every chain has a least upper bound.
7389
7490
This is intended to be used in the construction of `partial_fixpoint`, and not meant to be used
7591
otherwise.
7692
-/
7793
class CCPO (α : Sort u) extends PartialOrder α where
78-
/--
79-
The least upper bound of a chain.
80-
81-
This is intended to be used in the construction of `partial_fixpoint`, and not meant to be used
82-
otherwise.
83-
-/
84-
csup : (α → Prop) → α
8594
/--
8695
`csup c` is the least upper bound of the chain `c` when all elements `x` that are at
8796
least as large as `csup c` are at least as large as all elements of `c`, and vice versa.
8897
-/
89-
csup_spec {c : α → Prop} (hc : chain c) : csup c ⊑ x ↔ (∀ y, c y → y ⊑ x)
98+
has_csup {c : α → Prop} (hc : chain c) : Exists (is_csup c)
9099

91-
open PartialOrder CCPO
100+
open CCPO
92101

93102
variable {α : Sort u} [CCPO α]
94103

95-
theorem csup_le {c : α → Prop} (hchain : chain c) : (∀ y, c y → y ⊑ x) → csup c ⊑ x :=
96-
(csup_spec hchain).mpr
104+
noncomputable def CCPO.csup {c : α → Prop} (hc : chain c) : α :=
105+
Classical.choose (CCPO.has_csup hc)
106+
107+
theorem CCPO.csup_spec {c : α → Prop} (hc : chain c) : is_csup c (csup hc) :=
108+
@fun x => Classical.choose_spec (CCPO.has_csup hc) x
109+
110+
theorem csup_le {c : α → Prop} (hc : chain c) : (∀ y, c y → y ⊑ x) → csup hc ⊑ x :=
111+
(csup_spec hc x).mpr
112+
113+
theorem le_csup {c : α → Prop} (hc : chain c) {y : α} (hy : c y) : y ⊑ csup hc :=
114+
(csup_spec hc (csup hc)).mp rel_refl y hy
97115

98-
theorem le_csup {c : α → Prop} (hchain : chain c) {y : α} (hy : c y) : y ⊑ csup c :=
99-
(csup_spec hchain).mp rel_refl y hy
116+
def empty_chain (α) : α → Prop := fun _ => False
117+
118+
def chain_empty (α : Sort u) [PartialOrder α] : chain (empty_chain α) := by
119+
intro x y hx hy; contradiction
100120

101121
/--
102122
The bottom element is the least upper bound of the empty chain.
103123
104124
This is intended to be used in the construction of `partial_fixpoint`, and not meant to be used otherwise.
105125
-/
106-
def bot : α := csup (fun _ => False)
126+
noncomputable def bot : α := csup (chain_empty α)
107127

108128
scoped notation "" => bot
109129

110130
theorem bot_le (x : α) : ⊥ ⊑ x := by
111131
apply csup_le
112-
· intro x y hx hy; contradiction
113-
· intro x hx; contradiction
132+
intro x y; contradiction
114133

115134
end CCPO
116135

@@ -204,7 +223,7 @@ from this definition, and `P ⊥` is a separate condition of the induction predi
204223
This is intended to be used in the construction of `partial_fixpoint`, and not meant to be used otherwise.
205224
-/
206225
def admissible (P : α → Prop) :=
207-
∀ (c : α → Prop), chain c(∀ x, c x → P x) → P (csup c)
226+
∀ (c : α → Prop) (hc : chain c), (∀ x, c x → P x) → P (csup hc)
208227

209228
theorem admissible_const_true : admissible (fun (_ : α) => True) :=
210229
fun _ _ _ => trivial
@@ -220,7 +239,7 @@ theorem chain_conj (c P : α → Prop) (hchain : chain c) : chain (fun x => c x
220239
exact hchain x y hcx hcy
221240

222241
theorem csup_conj (c P : α → Prop) (hchain : chain c) (h : ∀ x, c x → ∃ y, c y ∧ x ⊑ y ∧ P y) :
223-
csup c = csup (fun x => c x ∧ P x) := by
242+
csup hchain = csup (chain_conj c P hchain) := by
224243
apply rel_antisymm
225244
· apply csup_le hchain
226245
intro x hcx
@@ -355,7 +374,7 @@ This is intended to be used in the construction of `partial_fixpoint`, and not m
355374
-/
356375
inductive iterates (f : α → α) : α → Prop where
357376
| step : iterates f x → iterates f (f x)
358-
| sup {c : α → Prop} (hc : chain c) (hi : ∀ x, c x → iterates f x) : iterates f (csup c)
377+
| sup {c : α → Prop} (hc : chain c) (hi : ∀ x, c x → iterates f x) : iterates f (csup hc)
359378

360379
theorem chain_iterates {f : α → α} (hf : monotone f) : chain (iterates f) := by
361380
intro x y hx hy
@@ -367,7 +386,7 @@ theorem chain_iterates {f : α → α} (hf : monotone f) : chain (iterates f) :=
367386
· left; apply hf; assumption
368387
· right; apply hf; assumption
369388
case sup c hchain hi ih2 =>
370-
change f x ⊑ csup c ∨ csup c ⊑ f x
389+
change f x ⊑ csup hchain ∨ csup hchain ⊑ f x
371390
by_cases h : ∃ z, c z ∧ f x ⊑ z
372391
· left
373392
obtain ⟨z, hz, hfz⟩ := h
@@ -384,7 +403,7 @@ theorem chain_iterates {f : α → α} (hf : monotone f) : chain (iterates f) :=
384403
next => contradiction
385404
next => assumption
386405
case sup c hchain hi ih =>
387-
change rel (csup c) y ∨ rel y (csup c)
406+
change rel (csup hchain) y ∨ rel y (csup hchain)
388407
by_cases h : ∃ z, c z ∧ rel y z
389408
· right
390409
obtain ⟨z, hz, hfz⟩ := h
@@ -423,7 +442,7 @@ definition is not very meaningful and it simplifies applying theorems like `fix_
423442
424443
This is intended to be used in the construction of `partial_fixpoint`, and not meant to be used otherwise.
425444
-/
426-
def fix (f : α → α) (hmono : monotone f) := csup (iterates f)
445+
noncomputable def fix (f : α → α) (hmono : monotone f) := csup (chain_iterates hmono)
427446

428447
/--
429448
The main fixpoint theorem for fixed points of monotone functions in chain-complete partial orders.
@@ -488,28 +507,36 @@ theorem chain_apply [∀ x, PartialOrder (β x)] {c : (∀ x, β x) → Prop} (h
488507
next h => left; apply h x
489508
next h => right; apply h x
490509

491-
def fun_csup [∀ x, CCPO (β x)] (c : (∀ x, β x) → Prop) (x : α) :=
492-
CCPO.csup (fun y => ∃ f, c f ∧ f x = y)
510+
noncomputable def fun_csup [∀ x, CCPO (β x)] (c : (∀ x, β x) → Prop) (hc : chain c) (x : α) :=
511+
CCPO.csup (chain_apply hc x)
512+
513+
theorem fun_csup_is_csup [∀ x, CCPO (β x)] (c : (∀ x, β x) → Prop) (hc : chain c) :
514+
is_csup c (fun_csup c hc) := by
515+
intro f
516+
constructor
517+
next =>
518+
intro hf g hg x
519+
apply rel_trans _ (hf x); clear hf
520+
apply le_csup (chain_apply hc x)
521+
exact ⟨g, hg, rfl⟩
522+
next =>
523+
intro h x
524+
apply csup_le (chain_apply hc x)
525+
intro y ⟨z, hz, hyz⟩
526+
subst y
527+
apply h z hz
493528

494529
def fun_sup [∀ x, CompleteLattice (β x)] (c : (∀ x, β x) → Prop) (x : α) :=
495530
CompleteLattice.sup (fun y => ∃ f, c f ∧ f x = y)
496531

497532
instance instCCPOPi [∀ x, CCPO (β x)] : CCPO (∀ x, β x) where
498-
csup := fun_csup
499-
csup_spec := by
500-
intro f c hc
501-
constructor
502-
next =>
503-
intro hf g hg x
504-
apply rel_trans _ (hf x); clear hf
505-
apply le_csup (chain_apply hc x)
506-
exact ⟨g, hg, rfl⟩
507-
next =>
508-
intro h x
509-
apply csup_le (chain_apply hc x)
510-
intro y ⟨z, hz, hyz⟩
511-
subst y
512-
apply h z hz
533+
has_csup hc := ⟨fun_csup _ hc, fun_csup_is_csup _ hc⟩
534+
535+
theorem fun_csup_eq [∀ x, CCPO (β x)] (c : (∀ x, β x) → Prop) (hc : chain c) :
536+
fun_csup c hc = CCPO.csup hc := by
537+
apply is_csup_unique (c := c)
538+
· apply fun_csup_is_csup
539+
· apply CCPO.csup_spec
513540

514541
instance instCompleteLatticePi [∀ x, CompleteLattice (β x)] : CompleteLattice (∀ x, β x) where
515542
sup := fun_sup
@@ -531,6 +558,7 @@ instance instCompleteLatticePi [∀ x, CompleteLattice (β x)] : CompleteLattice
531558
def admissible_apply [∀ x, CCPO (β x)] (P : ∀ x, β x → Prop) (x : α)
532559
(hadm : admissible (P x)) : admissible (fun (f : ∀ x, β x) => P x (f x)) := by
533560
intro c hchain h
561+
rw [← fun_csup_eq]
534562
apply hadm _ (chain_apply hchain x)
535563
rintro _ ⟨f, hcf, rfl⟩
536564
apply h _ hcf
@@ -656,40 +684,53 @@ instance instCompleteLatticePProd [CompleteLattice α] [CompleteLattice β] : Co
656684
intro y' hc
657685
apply (h ⟨y', b' ⟩ hc).2
658686

687+
noncomputable def prod_csup [CCPO α] [CCPO β] (c : α ×' β → Prop) (hchain : chain c) : α ×' β :=
688+
⟨CCPO.csup (PProd.chain.chain_fst hchain), CCPO.csup (PProd.chain.chain_snd hchain)⟩
689+
690+
theorem prod_csup_is_csup [CCPO α] [CCPO β] (c : α ×' β → Prop) (hchain : chain c) :
691+
is_csup c (prod_csup c hchain) := by
692+
intro ⟨a, b⟩
693+
constructor
694+
next =>
695+
intro ⟨h₁, h₂⟩ ⟨a', b'⟩ cab
696+
constructor <;> dsimp at *
697+
· apply rel_trans ?_ h₁
698+
apply le_csup (PProd.chain.chain_fst hchain)
699+
exact ⟨b', cab⟩
700+
· apply rel_trans ?_ h₂
701+
apply le_csup (PProd.chain.chain_snd hchain)
702+
exact ⟨a', cab⟩
703+
next =>
704+
intro h
705+
constructor <;> dsimp
706+
· apply csup_le (PProd.chain.chain_fst hchain)
707+
intro a' ⟨b', hcab⟩
708+
apply (h _ hcab).1
709+
· apply csup_le (PProd.chain.chain_snd hchain)
710+
intro b' ⟨a', hcab⟩
711+
apply (h _ hcab).2
712+
659713
instance instCCPOPProd [CCPO α] [CCPO β] : CCPO (α ×' β) where
660-
csup c := ⟨CCPO.csup (PProd.chain.fst c), CCPO.csup (PProd.chain.snd c)⟩
661-
csup_spec := by
662-
intro ⟨a, b⟩ c hchain
663-
constructor
664-
next =>
665-
intro ⟨h₁, h₂⟩ ⟨a', b'⟩ cab
666-
constructor <;> dsimp at *
667-
· apply rel_trans ?_ h₁
668-
apply le_csup (PProd.chain.chain_fst hchain)
669-
exact ⟨b', cab⟩
670-
· apply rel_trans ?_ h₂
671-
apply le_csup (PProd.chain.chain_snd hchain)
672-
exact ⟨a', cab⟩
673-
next =>
674-
intro h
675-
constructor <;> dsimp
676-
· apply csup_le (PProd.chain.chain_fst hchain)
677-
intro a' ⟨b', hcab⟩
678-
apply (h _ hcab).1
679-
· apply csup_le (PProd.chain.chain_snd hchain)
680-
intro b' ⟨a', hcab⟩
681-
apply (h _ hcab).2
714+
has_csup hchain := ⟨prod_csup _ hchain, prod_csup_is_csup _ hchain⟩
715+
716+
theorem prod_csup_eq [CCPO α] [CCPO β] (c : α ×' β → Prop) (hchain : chain c) :
717+
prod_csup c hchain = CCPO.csup hchain := by
718+
apply is_csup_unique (c := c)
719+
· apply prod_csup_is_csup
720+
· apply CCPO.csup_spec
682721

683722
theorem admissible_pprod_fst {α : Sort u} {β : Sort v} [CCPO α] [CCPO β] (P : α → Prop)
684723
(hadm : admissible P) : admissible (fun (x : α ×' β) => P x.1) := by
685724
intro c hchain h
725+
rw [<- prod_csup_eq]
686726
apply hadm _ (PProd.chain.chain_fst hchain)
687727
intro x ⟨y, hxy⟩
688728
apply h ⟨x,y⟩ hxy
689729

690730
theorem admissible_pprod_snd {α : Sort u} {β : Sort v} [CCPO α] [CCPO β] (P : β → Prop)
691731
(hadm : admissible P) : admissible (fun (x : α ×' β) => P x.2) := by
692732
intro c hchain h
733+
rw [<- prod_csup_eq]
693734
apply hadm _ (PProd.chain.chain_snd hchain)
694735
intro y ⟨x, hxy⟩
695736
apply h ⟨x,y⟩ hxy
@@ -736,49 +777,57 @@ noncomputable def flat_csup (c : FlatOrder b → Prop) : FlatOrder b := by
736777
· exact Classical.choose h
737778
· exact b
738779

739-
noncomputable instance FlatOrder.instCCPO : CCPO (FlatOrder b) where
740-
csup := flat_csup
741-
csup_spec := by
742-
intro x c hc
743-
unfold flat_csup
744-
split
745-
next hex =>
746-
apply Classical.some_spec₂ (q := (· ⊑ x ↔ (∀ y, c y → y ⊑ x)))
747-
clear hex
748-
intro z ⟨hz, hnb⟩
749-
constructor
750-
· intro h y hy
751-
apply PartialOrder.rel_trans _ h; clear h
752-
cases hc y z hy hz
753-
next => assumption
754-
next h =>
755-
cases h
756-
· contradiction
757-
· constructor
758-
· intro h
759-
cases h z hz
780+
theorem flat_csup_is_csup (c : FlatOrder b → Prop) (hc : chain c) :
781+
is_csup c (flat_csup c) := by
782+
intro x
783+
unfold flat_csup
784+
split
785+
next hex =>
786+
apply Classical.some_spec₂ (q := (· ⊑ x ↔ (∀ y, c y → y ⊑ x)))
787+
clear hex
788+
intro z ⟨hz, hnb⟩
789+
constructor
790+
· intro h y hy
791+
apply PartialOrder.rel_trans _ h; clear h
792+
cases hc y z hy hz
793+
next => assumption
794+
next h =>
795+
cases h
760796
· contradiction
761797
· constructor
762-
next hnotex =>
763-
constructor
764-
· intro h y hy; clear h
765-
suffices y = b by rw [this]; exact rel.bot
766-
rw [not_exists] at hnotex
767-
specialize hnotex y
768-
rw [not_and] at hnotex
769-
specialize hnotex hy
770-
rw [@Classical.not_not] at hnotex
771-
assumption
772-
· intro; exact rel.bot
798+
· intro h
799+
cases h z hz
800+
· contradiction
801+
· constructor
802+
next hnotex =>
803+
constructor
804+
· intro h y hy; clear h
805+
suffices y = b by rw [this]; exact FlatOrder.rel.bot
806+
rw [not_exists] at hnotex
807+
specialize hnotex y
808+
rw [not_and] at hnotex
809+
specialize hnotex hy
810+
rw [@Classical.not_not] at hnotex
811+
assumption
812+
· intro; exact FlatOrder.rel.bot
813+
814+
instance FlatOrder.instCCPO : CCPO (FlatOrder b) where
815+
has_csup hchain := ⟨flat_csup _ , flat_csup_is_csup _ hchain⟩
816+
817+
theorem flat_csup_eq (c : FlatOrder b → Prop) (hchain : chain c) :
818+
flat_csup c = CCPO.csup hchain := by
819+
apply is_csup_unique (c := c)
820+
· apply flat_csup_is_csup _ hchain
821+
· apply CCPO.csup_spec
773822

774823
theorem admissible_flatOrder (P : FlatOrder b → Prop) (hnot : P b) : admissible P := by
775824
intro c hchain h
776825
by_cases h' : ∃ (x : FlatOrder b), c x ∧ x ≠ b
777-
· simp [CCPO.csup, flat_csup, h']
826+
· simp [← flat_csup_eq, flat_csup, h']
778827
apply Classical.some_spec₂ (q := (P ·))
779828
intro x ⟨hcx, hneb⟩
780829
apply h x hcx
781-
· simp [CCPO.csup, flat_csup, h', hnot]
830+
· simp [← flat_csup_eq, flat_csup, h', hnot]
782831

783832
end flat_order
784833

@@ -809,8 +858,8 @@ theorem monotone_bind
809858
· apply MonoBind.bind_mono_right (fun y => monotone_apply y _ hmono₂ _ _ hx₁₂)
810859

811860
instance : PartialOrder (Option α) := inferInstanceAs (PartialOrder (FlatOrder none))
812-
noncomputable instance : CCPO (Option α) := inferInstanceAs (CCPO (FlatOrder none))
813-
noncomputable instance : MonoBind Option where
861+
instance : CCPO (Option α) := inferInstanceAs (CCPO (FlatOrder none))
862+
instance : MonoBind Option where
814863
bind_mono_left h := by
815864
cases h
816865
· exact FlatOrder.rel.bot
@@ -926,7 +975,7 @@ theorem monotone_stateTRun [PartialOrder γ]
926975
noncomputable instance [Nonempty ε] : CCPO (EST ε σ α) :=
927976
inferInstanceAs (CCPO ((s : _) → FlatOrder (.error Classical.ofNonempty (Classical.choice ⟨s⟩))))
928977

929-
noncomputable instance [Nonempty ε] : MonoBind (EST ε σ) where
978+
instance [Nonempty ε] : MonoBind (EST ε σ) where
930979
bind_mono_left {_ _ a₁ a₂ f} h₁₂ := by
931980
intro s
932981
specialize h₁₂ s

0 commit comments

Comments
 (0)