Skip to content
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
2db8ec2
Start porting step-indexing for Transfinite Iris
alvinylt Jul 14, 2026
059e3b7
Introduce the type class `SIdx`
alvinylt Jul 14, 2026
946c03e
First theorem for `SIdx`: `nlt_0_r`
alvinylt Jul 14, 2026
8debfd2
More `Std` classes and more `SIdx` theorems
alvinylt Jul 14, 2026
be0f833
More theorem definitions
alvinylt Jul 14, 2026
dabb7e7
Four more theorems defined
alvinylt Jul 14, 2026
60a74ba
Prove `lt_le_trans`
alvinylt Jul 14, 2026
2b569f8
Prove `le_lt_trans`
alvinylt Jul 14, 2026
5d88f41
Typo fix
alvinylt Jul 14, 2026
e02680f
Prove `succ_le_mono`, `succ_lt_mono`
alvinylt Jul 14, 2026
96c333c
Prove `le_0_l`, `le_0_r`
alvinylt Jul 14, 2026
f436057
Towards proving more theorems
alvinylt Jul 14, 2026
f5e0f5a
Prove properties about `le`
alvinylt Jul 14, 2026
30096c7
More proofs
alvinylt Jul 14, 2026
904795a
Even more proofs
alvinylt Jul 14, 2026
1aee575
Further proofs
alvinylt Jul 14, 2026
2ac43a8
Prove `succ_inj`
alvinylt Jul 14, 2026
b2c2db5
Code reorganisation
alvinylt Jul 14, 2026
60232a8
Remove `StepIndexFinite.lean`: to be ported later
alvinylt Jul 14, 2026
cba8474
Add `rocq_ignore` entries, add decidability instances
alvinylt Jul 14, 2026
b762bd1
Fix `rocq_ignore` entries, port `SIdx.limit`
alvinylt Jul 14, 2026
fc7a175
Port `limit_0`, `limit_lt_0`, `limit_S`, `limit_finite`
alvinylt Jul 14, 2026
829f437
Port the `rec` and the remaining theorems
alvinylt Jul 15, 2026
9f32bc7
Typo fix
alvinylt Jul 15, 2026
8766178
Merge remote-tracking branch 'upstream/master' into StepIndexing
alvinylt Jul 21, 2026
1635b73
Instance of `SIdx` for `Ordinal`
alvinylt Jul 21, 2026
01c6141
Another `SIdx` instance
alvinylt Jul 21, 2026
af91482
Prove equivalence of `SIdx.Limit` and `Order.IsSuccLimit`
alvinylt Jul 21, 2026
6aaa95f
Minor cleanup
alvinylt Jul 21, 2026
7a0fb5c
Introduce `ordinalToTypeSIdx`
alvinylt Jul 21, 2026
ae0df19
Revert changes to `Std/Classes.lean`, use `IsPartialOrder` instead
alvinylt Jul 22, 2026
8ba0dc0
Minor formatting
alvinylt Jul 22, 2026
beaed9e
Add instances
alvinylt Jul 23, 2026
a681ca1
Fix `rocq_alias` annotations
alvinylt Jul 24, 2026
9ce72d9
Restructure proofs for readability
alvinylt Jul 24, 2026
2500861
Merge remote-tracking branch 'upstream/master' into StepIndexing
alvinylt Jul 25, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Iris/Iris/Algebra.lean
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public import Iris.Algebra.LeibnizSet
public import Iris.Algebra.LocalUpdates
public import Iris.Algebra.IProp
public import Iris.Algebra.OFE
public import Iris.Algebra.StepIndex
public import Iris.Algebra.UFrac
public import Iris.Algebra.Updates
public import Iris.Algebra.UPred
Expand Down
371 changes: 371 additions & 0 deletions Iris/Iris/Algebra/StepIndex.lean
Original file line number Diff line number Diff line change
@@ -0,0 +1,371 @@
/-
Copyright (c) 2026 Alvin Tang. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Michael Sammler, Alvin Tang
-/
module

public meta import Iris.Std.RocqPorting
public import Iris.Std.Classes

@[expose] public section

namespace Iris

@[rocq_alias sidx, rocq_alias SIdxMixin]
class SIdx (I : Type u) extends LT I, LE I, Zero I where
succ : I → I
lt_trans : ∀ {n m p : I}, n < m → m < p → n < p
lt_wf : WellFounded ((· < ·) : I → I → Prop)
lt_trichotomyT : ∀ n m : I, n < m ⊕' n = m ⊕' m < n
le_lteq : ∀ {m n : I}, n ≤ m ↔ n < m ∨ n = m
not_lt_zero : ∀ n : I, ¬n < 0
lt_succ_self : ∀ n : I, n < succ n
succ_le_of_lt : ∀ {n m : I}, n < m → succ n ≤ m
weak_case : ∀ n : I, (Σ' m : I, n = succ m) ⊕' ∀ m : I, m < n → succ m < n

/-- The step-indexing successor operator. -/
scoped prefix:max "succᵢ" => SIdx.succ

class SIdxFinite (I : Type u) [SIdx I] where
finite_index : ∀ n : I, n = 0 ∨ ∃ m, n = succᵢ m

#rocq_ignore SIdx.lt_trans "Lifting of mixin properties not required as they are part of the type class SIdx"
#rocq_ignore SIdx.lt_wf "Lifting of mixin properties not required as they are part of the type class SIdx"
#rocq_ignore SIdx.lt_lteq "Lifting of mixin properties not required as they are part of the type class SIdx"
#rocq_ignore SIdx.lt_trichotomy "Lifting of mixin properties not required as they are part of the type class SIdx"
#rocq_ignore SIdx.le_lteq "Lifting of mixin properties not required as they are part of the type class SIdx"
#rocq_ignore SIdx.nlt_0_r "Lifting of mixin properties not required as they are part of the type class SIdx"
#rocq_ignore SIdx.lt_succ_diag_r "Lifting of mixin properties not required as they are part of the type class SIdx"
#rocq_ignore SIdx.le_succ_l_2 "Lifting of mixin properties not required as they are part of the type class SIdx"
#rocq_ignore SIdx.weak_case "Lifting of mixin properties not required as they are part of the type class SIdx"

namespace SIdx

open Iris Std

variable {I : Type u} [inst : SIdx I] {m n p : I}

@[rocq_alias SIdx.lt_succ_diag_r']
theorem lt_succ_diag_r' (h : n = succᵢ m) : m < n := by
subst h
exact inst.lt_succ_self m

@[rocq_alias SIdx.inhabited]
instance inhabited : Inhabited I where
default := 0

theorem lt_irrefl (n : I) : ¬n < n := by
intro h
induction n using inst.lt_wf.induction with
| h n ih => apply ih n <;> exact h

theorem lt_asymm (h : n < m) : ¬m < n := by
intro h1
apply lt_irrefl n
exact inst.lt_trans h h1

@[rocq_alias SIdx.lt_strict]
instance lt_strict : StrictOrder inst.lt where
irrefl := by intro n; exact lt_irrefl n
trans := inst.lt_trans

@[rocq_alias SIdx.lt_le_incl]
theorem lt_le_incl (h : n < m) : n ≤ m := by
apply le_lteq.mpr; left; assumption

/-- For the `rfl` tactic. -/
@[refl, simp]
theorem le_refl : n ≤ n := by apply inst.le_lteq.mpr; right; rfl

theorem le_trans (h1 : n ≤ m) (h2 : m ≤ p) : n ≤ p := by
rcases le_lteq.mp h1 with (h1 | rfl)
· rcases le_lteq.mp h2 with (h2 | rfl)
· exact lt_le_incl <| inst.lt_trans h1 h2
· exact lt_le_incl h1
· assumption

theorem le_antisymm (h1 : m ≤ n) (h2 : n ≤ m) : m = n := by
rcases le_lteq.mp h2 with (h2 | h2)
· rcases le_lteq.mp h1 with (h1 | h1)
· exact absurd (inst.lt_trans h2 h1) (lt_irrefl n)
· exact h1
· subst h2; rfl

@[rocq_alias SIdx.le_po]
instance le_po : PartialOrder inst.le where
refl := le_refl
trans := le_trans
antisymm := le_antisymm

@[rocq_alias SIdx.lt_ge_cases]
theorem lt_ge_cases (m n : I) : n < m ∨ m ≤ n := by
rcases inst.lt_trichotomyT n m with (h | h | h)
· left; exact h
· right; apply le_lteq.mpr; right; symm; assumption
· right; exact lt_le_incl h

@[rocq_alias SIdx.le_gt_cases]
theorem le_gt_cases (m n : I) : n ≤ m ∨ m < n := lt_ge_cases n m |>.symm

@[rocq_alias SIdx.le_total]
theorem le_total : n ≤ m ∨ m ≤ n := by
rcases lt_ge_cases m n with (h | h)
· left; exact lt_le_incl h
· right; assumption

@[rocq_alias SIdx.lt_le_trans]
theorem lt_le_trans (h1 : n < m) (h2 : m ≤ p) : n < p := by
rcases inst.le_lteq.mp h2 with (h2 | h2)
· exact inst.lt_trans h1 h2
· subst h2; assumption

@[rocq_alias SIdx.le_lt_trans]
theorem le_lt_trans (h1 : n ≤ m) (h2 : m < p) : n < p := by
rcases inst.le_lteq.mp h1 with (h1 | h1)
· exact inst.lt_trans h1 h2
· subst h1; assumption

@[rocq_alias SIdx.le_succ_diag_r]
theorem le_succ_diag_r : n ≤ succᵢ n := by
apply lt_le_incl
apply inst.lt_succ_self

@[rocq_alias SIdx.le_ngt]
theorem le_ngt : n ≤ m ↔ ¬ m < n := by
constructor <;> intro h0
· intro h1
exact lt_irrefl m (lt_le_trans h1 h0)
· rcases lt_ge_cases n m <;> trivial

@[rocq_alias SIdx.lt_nge]
theorem lt_nge : n < m ↔ ¬ m ≤ n := by
constructor <;> intro h0
· intro h1
exact lt_irrefl n <| lt_le_trans h0 h1
· rcases lt_ge_cases m n <;> trivial

@[rocq_alias SIdx.le_neq]
theorem le_neq : n < m ↔ n ≤ m ∧ n ≠ m := by
constructor <;> intro h
· refine ⟨lt_le_incl h, ?_⟩
rintro rfl
exact lt_irrefl n h
· rcases h with ⟨h1, h2⟩
apply lt_nge.mpr
intro h3
apply h2
exact le_antisymm h1 h3

@[rocq_alias SIdx.le_succ_l]
theorem le_succ_l : succᵢ n ≤ m ↔ n < m := by
constructor <;> intro h
· exact lt_le_trans (lt_succ_self n) h
· exact succ_le_of_lt h

@[rocq_alias SIdx.lt_succ_r]
theorem lt_succ_r : n < succᵢ m ↔ n ≤ m := by
constructor <;> intro h
· refine le_ngt.mpr ?_
intro h1
apply lt_irrefl n
apply lt_le_trans h
exact succ_le_of_lt h1
· exact le_lt_trans h <| inst.lt_succ_self m

@[rocq_alias SIdx.succ_le_mono]
theorem succ_le_mono : n ≤ m ↔ succᵢ n ≤ succᵢ m := by
rewrite [le_succ_l, lt_succ_r]; rfl

@[rocq_alias SIdx.succ_lt_mono]
theorem succ_lt_mono : n < m ↔ succᵢ n < succᵢ m := by
rewrite [lt_succ_r, le_succ_l]; rfl

@[rocq_alias SIdx.succ_inj]
theorem succ_inj (h : succᵢ n = succᵢ m) : n = m := by
apply le_antisymm <;> apply succ_le_mono.mpr <;> rw [h]

@[rocq_alias SIdx.nlt_succ_r]
theorem nlt_succ_r : ¬ m < succᵢ n ↔ n < m := by
rw [lt_succ_r, lt_nge]

@[rocq_alias SIdx.le_0_l]
theorem le_0_l : 0 ≤ n := le_ngt.mpr <| inst.not_lt_zero n

@[rocq_alias SIdx.le_0_r]
theorem le_0_r : n ≤ 0 ↔ n = 0 := by
constructor <;> intro h
· apply antisymm
· assumption
· exact le_0_l
· subst h; rfl

@[rocq_alias SIdx.neq_0_lt_0]
theorem neq_0_lt_0 : n ≠ 0 ↔ 0 < n := by
constructor
· intro h
rcases lt_ge_cases n 0 with (h1 | h1)
· assumption
· exact absurd (le_0_r.mp h1) h
· rintro h rfl
exact inst.not_lt_zero 0 h

@[rocq_alias neq_succ_0]
theorem neq_succ_0 : succᵢ n ≠ 0 := neq_0_lt_0.mpr <| lt_succ_r.mpr le_0_l

@[rocq_alias succ_neq]
theorem succ_neq : n ≠ succᵢ n := by
intro h
have hlt := inst.lt_succ_self n
rw [← h] at hlt
exact lt_irrefl n hlt

@[rocq_alias SIdx.eq_dec]
instance (priority := low) eqDec : DecidableEq I := fun n m =>
match inst.lt_trichotomyT n m with
| .inl h => by
apply isFalse
rintro rfl
exact lt_irrefl n h
| .inr (.inl h) => isTrue h
| .inr (.inr h) => by
apply isFalse
rintro rfl
exact lt_irrefl n h

@[rocq_alias SIdx.lt_dec]
instance (priority := low) (n m : I) : Decidable (n < m) :=
match inst.lt_trichotomyT n m with
| .inl h => isTrue h
| .inr (.inl h) => by
apply isFalse
rintro h'
subst h
exact lt_irrefl n h'
| .inr (.inr h) => by
apply isFalse
intro h'
exact lt_irrefl m <| inst.lt_trans h h'

@[rocq_alias SIdx.le_dec]
instance (priority := low) (n m : I) : Decidable (n ≤ m) :=
match inst.lt_trichotomyT n m with
| .inl h => by
apply isTrue
exact lt_le_incl h
| .inr (.inl h) => by
apply isTrue
exact le_lteq.mpr <| .inr h
| .inr (.inr h) => by
apply isFalse
intro h'
exact lt_irrefl m <| lt_le_trans h h'

@[rocq_alias SIdx.limit]
structure Limit (n : I) [SIdx I] where
succ_lt : ∀ m, m < n → succᵢ m < n
ne_zero : n ≠ 0

@[simp, rocq_alias SIdx.limit_0]
theorem limit_0 : ¬Limit (0 : I) := by
intro h
exact h.ne_zero rfl

@[rocq_alias SIdx.limit_lt_0]
theorem Limit.limit_lt_0 (h : Limit n) : 0 < n := neq_0_lt_0.mp h.ne_zero

@[simp, rocq_alias SIdx.limit_S]
theorem limit_S (n : I) : ¬Limit (succᵢ n) := by
intro h
apply lt_irrefl (succᵢ n)
apply h.succ_lt n
exact lt_succ_self n

@[rocq_alias SIdx.limit_finite]
theorem limit_finite [inst : SIdxFinite I] (n : I) : ¬Limit n := by
intro h
rcases SIdxFinite.finite_index n with (h0 | h0)
· exact h.ne_zero h0
· rcases h0 with ⟨m, hm⟩
apply limit_S m
subst hm
assumption

@[rocq_alias SIdx.case]
def case (n : I) : (n = 0) ⊕' (Σ' m, n = succᵢ m) ⊕' Limit n :=
if h : n = 0 then .inl h
else
match inst.weak_case n with
| .inl ⟨m, hm⟩ => .inr <| .inl ⟨m, hm⟩
| .inr hlim => .inr <| .inr ⟨hlim, h⟩

@[rocq_alias SIdx.rec]
def rec' {P : I → Sort v}
(s : P 0)
(f : ∀ n, P n → P (succᵢ n))
(lim : ∀ n, Limit n → (∀ m, m < n → P m) → P n) :
∀ n, P n :=
WellFounded.fix inst.lt_wf fun n IH =>
match SIdx.case n with
| .inl EQ => EQ ▸ s
| .inr <| .inl ⟨m, EQ⟩ => EQ ▸ f m (IH m (lt_succ_diag_r' EQ))
| .inr <| .inr Hlim => lim n Hlim IH

@[rocq_alias SIdx.rec_unfold]
theorem rec_unfold {P : I → Sort v} (s : P 0) (f : ∀ n, P n → P (succᵢ n))
(lim : ∀ n, Limit n → (∀ m, m < n → P m) → P n) (n : I) :
rec' s f lim n =
match SIdx.case n with
| .inl EQ => EQ ▸ s
| .inr (.inl ⟨m, EQ⟩) => EQ ▸ f m (rec' s f lim m)
| .inr (.inr Hlim) => lim n Hlim (fun m _ => rec' s f lim m) :=
inst.lt_wf.fix_eq _ n

@[rocq_alias SIdx.rec_zero]
theorem rec_zero {P : I → Sort v} (s : P 0) (f : ∀ n, P n → P (succᵢ n))
(lim : ∀ n, Limit n → (∀ m, m < n → P m) → P n) :
rec' s f lim 0 = s := by
rw [rec_unfold s f lim 0]
cases SIdx.case (0 : I) with
| inl EQ => rfl
| inr h =>
cases h with
| inl h =>
let ⟨m, EQ⟩ := h
exact absurd EQ.symm neq_succ_0
| inr Hlim => exact absurd Hlim limit_0

@[rocq_alias SIdx.rec_succ]
theorem rec_succ {P : I → Sort v} (s : P 0) (f : ∀ n, P n → P (succᵢ n))
(lim : ∀ n, Limit n → (∀ m, m < n → P m) → P n) (n : I) :
rec' s f lim (succᵢ n) = f n (rec' s f lim n) := by
rw [rec_unfold s f lim (succᵢ n)]
cases SIdx.case (succᵢ n) with
| inl EQ => exact absurd EQ neq_succ_0
| inr h =>
cases h with
| inl h =>
obtain ⟨m, EQ⟩ := h
obtain rfl := succ_inj EQ
rfl
| inr Hlim => exact absurd Hlim (limit_S n)

@[rocq_alias SIdx.rec_lim]
theorem rec_lim {P : I → Sort v} (s : P 0) (f : ∀ n, P n → P (succᵢ n))
(lim : ∀ n, Limit n → (∀ m, m < n → P m) → P n) (n : I) (Hn : Limit n) :
rec' s f lim n = lim n Hn (fun m _ => rec' s f lim m) := by
rw [rec_unfold s f lim n]
cases SIdx.case n with
| inl EQ => exact absurd EQ Hn.ne_zero
| inr h =>
cases h with
| inl h =>
obtain ⟨m, EQ⟩ := h
exact absurd (EQ ▸ Hn) (limit_S m)
| inr Hlim => rfl

#rocq_ignore rec_lim_ext
"Proof irrelevance already handled automatically by Lean for the theorems \
rec_zero, rec_succ and rec_elim"

end SIdx
Loading