Skip to content

Commit f50080b

Browse files
Greatest fixpoints and coinduction (#161)
1 parent 54081c6 commit f50080b

2 files changed

Lines changed: 137 additions & 4 deletions

File tree

PORTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,9 @@ Some porting tasks will require other tasks as dependencies, the GitHub issues p
236236
- [ ] `lib/core.v`
237237
- [ ] `lib/counterexamples.v`
238238
- [ ] `lib/fixpoint_banach.v`
239-
- [ ] `lib/fixpoint_mono.v`
239+
- [x] `lib/fixpoint_mono.v`
240240
- [x] Least fixpoints + induction
241-
- [ ] Greatest fixpoints + coinduction
241+
- [x] Greatest fixpoints + coinduction
242242
- [ ] `lib/fractional.v`
243243
- [ ] `lib/laterable.v`
244244
- [ ] `lib/relations.v`

src/Iris/BI/Lib/Fixpoint.lean

Lines changed: 135 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,25 @@ attribute [instance] mono_pred_ne
2222
abbrev bi_least_fixpoint [BI PROP] [OFE A] (F : (A → PROP) → (A → PROP)) (x : A) : PROP :=
2323
iprop(∀ (Φ : A -n> PROP), □ (∀ x, F Φ x -∗ Φ x) -∗ Φ x)
2424

25-
def bi_greatest_fixpoint [BI PROP] [OFE A] (F : (A → PROP) → (A → PROP)) (x : A) : PROP :=
25+
abbrev bi_greatest_fixpoint [BI PROP] [OFE A] (F : (A → PROP) → (A → PROP)) (x : A) : PROP :=
2626
iprop(∃ (Φ : A -n> PROP), □ (∀ x, Φ x -∗ F Φ x) ∗ Φ x)
2727

2828
/-- Porting note: The Rocq version of this theorem has an additional
2929
`∀ Φ, NonExpansive Φ → NonExpansive (F Φ)` hypothesis. Not sure why! -/
30-
instance [BI PROP] [OFE A] {F : (A → PROP) → (A → PROP)} : NonExpansive (bi_least_fixpoint F) where
30+
instance [BI PROP] [OFE A] {F : (A → PROP) → (A → PROP)} :
31+
NonExpansive (bi_least_fixpoint F) where
3132
ne {_ _ _} Hx := by
3233
refine forall_ne fun _ => ?_
3334
refine wand_ne.ne (.of_eq rfl) ?_
3435
exact NonExpansive.ne Hx
3536

37+
instance greatest_fixpoint_ne' [BI PROP] [OFE A] {F : (A → PROP) → (A → PROP)} :
38+
NonExpansive (bi_greatest_fixpoint F) where
39+
ne {_ _ _} Hx := by
40+
refine exists_ne fun _ => ?_
41+
refine sep_ne.ne (.of_eq rfl) ?_
42+
exact NonExpansive.ne Hx
43+
3644
section LeastFixpoint
3745

3846
variable [BI PROP] [OFE A] (F : (A → PROP) → (A → PROP))
@@ -194,3 +202,128 @@ theorem least_fixpoint_ind :
194202

195203
end Strong
196204
end LeastFixpoint
205+
206+
section GreatestFixpoint
207+
208+
variable [BI PROP] [OFE A] (F : (A → PROP) → (A → PROP))
209+
210+
theorem greatest_fixpoint_ne_outer {F1 F2 : (A → PROP) → (A → PROP)}
211+
(HF : ∀ Φ x n, F1 Φ x ≡{n}≡ F2 Φ x) (Hx : x1 ≡{n}≡ x2) :
212+
bi_greatest_fixpoint F1 x1 ≡{n}≡ bi_greatest_fixpoint F2 x2 := by
213+
refine exists_ne fun _ => ?_
214+
refine sep_ne.ne ?_ (NonExpansive.ne Hx)
215+
refine intuitionistically_ne.ne ?_
216+
refine forall_ne fun _ => ?_
217+
refine wand_ne.ne (.of_eq rfl) ?_
218+
exact (HF _ _ n)
219+
220+
theorem greatest_fixpoint_unfold_1 {x} [BIMonoPred F] :
221+
bi_greatest_fixpoint F x ⊢ F (bi_greatest_fixpoint F) x := by
222+
iintro ⟨%Φ, #Hincl, HΦ⟩
223+
iapply mono_pred (Φ := Φ) $$ [], [HΦ]
224+
· iintro !> %_ H
225+
iexists Φ
226+
isplitr
227+
· iassumption
228+
· iassumption
229+
· iapply Hincl $$ HΦ
230+
231+
theorem greatest_fixpoint_unfold_2 {x} [BIMonoPred F] :
232+
F (bi_greatest_fixpoint F) x ⊢ bi_greatest_fixpoint F x := by
233+
iintro Hf
234+
iexists (Hom.mk (F (bi_greatest_fixpoint F)) mono_pred_ne)
235+
isplitr
236+
· iintro !> %y Hy
237+
iapply mono_pred (Φ := (bi_greatest_fixpoint F)) $$ [], Hy
238+
iintro !> %z Hz
239+
iapply greatest_fixpoint_unfold_1 $$ Hz
240+
· iexact Hf
241+
242+
theorem greatest_fixpoint_unfold {x} [BIMonoPred F] :
243+
bi_greatest_fixpoint F x ≡ F (bi_greatest_fixpoint F) x :=
244+
equiv_iff.mpr ⟨greatest_fixpoint_unfold_1 _, greatest_fixpoint_unfold_2 _⟩
245+
246+
theorem greatest_fixpoint_coiter (Φ : A → PROP) [I : NonExpansive Φ] :
247+
⊢ □ (∀ y, Φ y -∗ F Φ y) -∗ ∀ x, Φ x -∗ bi_greatest_fixpoint F x := by
248+
iintro #HΦ %x Hx
249+
iexists ⟨Φ, I⟩
250+
isplitr [Hx]
251+
· iassumption
252+
· iassumption
253+
254+
instance greatest_fixpoint_absorbing [BIMonoPred F]
255+
[∀ Φ, [∀ x, Absorbing (Φ x)] → (∀ x, Absorbing (F Φ x))] {x : A} :
256+
Absorbing (bi_greatest_fixpoint F x) where
257+
absorbing := by
258+
revert x
259+
letI _ : NonExpansive fun x => iprop(<absorb> bi_greatest_fixpoint F x) :=
260+
fun _ _ _ H => absorbingly_ne.ne (NonExpansive.ne H)⟩
261+
iapply greatest_fixpoint_coiter
262+
iintro !> %y >HF
263+
ihave HF : F (bi_greatest_fixpoint F) y $$ [HF]
264+
· iapply greatest_fixpoint_unfold_1 $$ HF
265+
iapply mono_pred $$ [], HF
266+
iintro !> %_ HF !>
267+
iassumption
268+
269+
theorem greatest_fixpoint_strong_mono (G : (A → PROP) → (A → PROP)) [BIMonoPred F] :
270+
⊢ □ (∀ Φ x, F Φ x -∗ G Φ x) -∗ ∀ x, bi_greatest_fixpoint F x -∗ bi_greatest_fixpoint G x := by
271+
iintro #Hmon
272+
iapply greatest_fixpoint_coiter
273+
iintro !> %y IH
274+
iapply Hmon
275+
iapply greatest_fixpoint_unfold_1
276+
iexact IH
277+
278+
section Coind
279+
280+
variable [IF : BIMonoPred F] (Φ : A → PROP) [IN : NonExpansive Φ]
281+
282+
local instance paco_mono : BIMonoPred (fun (Ψ : A → PROP) (a : A) => iprop(Φ a ∨ F Ψ a)) where
283+
mono_pred {Ψ Ψ' HΨ HΨ'} := by
284+
iintro #Hmon %x ⟨H|H⟩
285+
· ileft
286+
iexact H
287+
· iright
288+
iapply mono_pred (Φ := Ψ) $$ Hmon, H
289+
mono_pred_ne.ne _ _ _ H := or_ne.ne (NonExpansive.ne H) (NonExpansive.ne H)
290+
291+
theorem greatest_fixpoint_paco :
292+
⊢ □ (∀ y, Φ y -∗ F (bi_greatest_fixpoint (fun Ψ a => iprop(Φ a ∨ F Ψ a))) y) -∗
293+
∀ x, Φ x -∗ bi_greatest_fixpoint F x := by
294+
iintro #Hmon %x HΦ
295+
iapply greatest_fixpoint_unfold_2
296+
iapply mono_pred (Φ := (bi_greatest_fixpoint fun Ψ a => iprop(Φ a ∨ F Ψ a))) $$ [], [HΦ]
297+
· iintro !> %y Hy
298+
iapply greatest_fixpoint_coiter $$ [], Hy
299+
iintro !> %z Hz
300+
ihave Hcase : Φ z ∨ F (bi_greatest_fixpoint (fun Ψ a => iprop(Φ a ∨ F Ψ a))) z $$ [Hz]
301+
· iapply greatest_fixpoint_unfold_1 $$ Hz
302+
icases Hcase with ⟨H|H⟩
303+
· iapply Hmon $$ H
304+
· iapply H
305+
· iapply Hmon $$ HΦ
306+
307+
theorem greatest_fixpoint_coind [_HF : NonExpansive F] :
308+
⊢ □ (∀ y, Φ y -∗ F (fun x => iprop(Φ x ∨ bi_greatest_fixpoint F x)) y) -∗
309+
∀ x, Φ x -∗ bi_greatest_fixpoint F x := by
310+
iintro #Ha
311+
iapply greatest_fixpoint_paco
312+
iintro !> %y Hy
313+
letI _ : NonExpansive fun Ψ a => iprop(Φ a ∨ F Ψ a) :=
314+
fun _ _ _ H x => or_ne.ne (.of_eq rfl) (_HF.ne H x)⟩
315+
letI _ : NonExpansive fun x => iprop(Φ x ∨ bi_greatest_fixpoint F x) :=
316+
fun _ _ _ H => or_ne.ne (NonExpansive.ne H) (NonExpansive.ne H)⟩
317+
iapply mono_pred (Φ := (fun x => iprop(Φ x ∨ bi_greatest_fixpoint F x))) $$ [], [Ha, Hy]
318+
· iintro !> %x ⟨HΦ|Hf⟩
319+
· iapply greatest_fixpoint_unfold_2
320+
ileft
321+
iexact HΦ
322+
· iapply greatest_fixpoint_strong_mono (F := F) $$ [], Hf
323+
iintro !> %_ %_ HF
324+
iright
325+
iexact HF
326+
· iapply Ha $$ Hy
327+
328+
end Coind
329+
end GreatestFixpoint

0 commit comments

Comments
 (0)