Skip to content

Commit 3800f1e

Browse files
datokratluisacicolini
authored andcommitted
feat: add simple Ordering lemmas (leanprover#6821)
This PR adds basic lemmas about `Ordering`, describing the interaction of `isLT`/`isLE`/`isGE`/`isGT`, `swap` and the constructors. Additionally, it refactors the instance derivation code such that a `LawfulBEq Ordering` instance is also derived automatically. Some of these lemmas are helpful for the `TreeMap` verification. --------- Co-authored-by: Paul Reichert <[email protected]>
1 parent 90c695c commit 3800f1e

File tree

2 files changed

+176
-12
lines changed

2 files changed

+176
-12
lines changed

src/Init/Data/Ord.lean

+176-3
Original file line numberDiff line numberDiff line change
@@ -10,12 +10,10 @@ import Init.Data.Array.Basic
1010

1111
inductive Ordering where
1212
| lt | eq | gt
13-
deriving Inhabited, BEq
13+
deriving Inhabited, DecidableEq
1414

1515
namespace Ordering
1616

17-
deriving instance DecidableEq for Ordering
18-
1917
/-- Swaps less and greater ordering results -/
2018
def swap : Ordering → Ordering
2119
| .lt => .gt
@@ -86,6 +84,181 @@ def isGE : Ordering → Bool
8684
| lt => false
8785
| _ => true
8886

87+
section Lemmas
88+
89+
@[simp]
90+
theorem isLT_lt : lt.isLT := rfl
91+
92+
@[simp]
93+
theorem isLE_lt : lt.isLE := rfl
94+
95+
@[simp]
96+
theorem isEq_lt : lt.isEq = false := rfl
97+
98+
@[simp]
99+
theorem isNe_lt : lt.isNe = true := rfl
100+
101+
@[simp]
102+
theorem isGE_lt : lt.isGE = false := rfl
103+
104+
@[simp]
105+
theorem isGT_lt : lt.isGT = false := rfl
106+
107+
@[simp]
108+
theorem isLT_eq : eq.isLT = false := rfl
109+
110+
@[simp]
111+
theorem isLE_eq : eq.isLE := rfl
112+
113+
@[simp]
114+
theorem isEq_eq : eq.isEq := rfl
115+
116+
@[simp]
117+
theorem isNe_eq : eq.isNe = false := rfl
118+
119+
@[simp]
120+
theorem isGE_eq : eq.isGE := rfl
121+
122+
@[simp]
123+
theorem isGT_eq : eq.isGT = false := rfl
124+
125+
@[simp]
126+
theorem isLT_gt : gt.isLT = false := rfl
127+
128+
@[simp]
129+
theorem isLE_gt : gt.isLE = false := rfl
130+
131+
@[simp]
132+
theorem isEq_gt : gt.isEq = false := rfl
133+
134+
@[simp]
135+
theorem isNe_gt : gt.isNe = true := rfl
136+
137+
@[simp]
138+
theorem isGE_gt : gt.isGE := rfl
139+
140+
@[simp]
141+
theorem isGT_gt : gt.isGT := rfl
142+
143+
@[simp]
144+
theorem swap_lt : lt.swap = .gt := rfl
145+
146+
@[simp]
147+
theorem swap_eq : eq.swap = .eq := rfl
148+
149+
@[simp]
150+
theorem swap_gt : gt.swap = .lt := rfl
151+
152+
theorem eq_eq_of_isLE_of_isLE_swap {o : Ordering} : o.isLE → o.swap.isLE → o = .eq := by
153+
cases o <;> simp
154+
155+
theorem eq_eq_of_isGE_of_isGE_swap {o : Ordering} : o.isGE → o.swap.isGE → o = .eq := by
156+
cases o <;> simp
157+
158+
theorem eq_eq_of_isLE_of_isGE {o : Ordering} : o.isLE → o.isGE → o = .eq := by
159+
cases o <;> simp
160+
161+
theorem eq_swap_iff_eq_eq {o : Ordering} : o = o.swap ↔ o = .eq := by
162+
cases o <;> simp
163+
164+
theorem eq_eq_of_eq_swap {o : Ordering} : o = o.swap → o = .eq :=
165+
eq_swap_iff_eq_eq.mp
166+
167+
@[simp]
168+
theorem isLE_eq_false {o : Ordering} : o.isLE = false ↔ o = .gt := by
169+
cases o <;> simp
170+
171+
@[simp]
172+
theorem isGE_eq_false {o : Ordering} : o.isGE = false ↔ o = .lt := by
173+
cases o <;> simp
174+
175+
@[simp]
176+
theorem swap_eq_gt {o : Ordering} : o.swap = .gt ↔ o = .lt := by
177+
cases o <;> simp
178+
179+
@[simp]
180+
theorem swap_eq_lt {o : Ordering} : o.swap = .lt ↔ o = .gt := by
181+
cases o <;> simp
182+
183+
@[simp]
184+
theorem swap_eq_eq {o : Ordering} : o.swap = .eq ↔ o = .eq := by
185+
cases o <;> simp
186+
187+
@[simp]
188+
theorem isLT_swap {o : Ordering} : o.swap.isLT = o.isGT := by
189+
cases o <;> simp
190+
191+
@[simp]
192+
theorem isLE_swap {o : Ordering} : o.swap.isLE = o.isGE := by
193+
cases o <;> simp
194+
195+
@[simp]
196+
theorem isEq_swap {o : Ordering} : o.swap.isEq = o.isEq := by
197+
cases o <;> simp
198+
199+
@[simp]
200+
theorem isNe_swap {o : Ordering} : o.swap.isNe = o.isNe := by
201+
cases o <;> simp
202+
203+
@[simp]
204+
theorem isGE_swap {o : Ordering} : o.swap.isGE = o.isLE := by
205+
cases o <;> simp
206+
207+
@[simp]
208+
theorem isGT_swap {o : Ordering} : o.swap.isGT = o.isLT := by
209+
cases o <;> simp
210+
211+
theorem isLT_iff_eq_lt {o : Ordering} : o.isLT ↔ o = .lt := by
212+
cases o <;> simp
213+
214+
theorem isLE_iff_eq_lt_or_eq_eq {o : Ordering} : o.isLE ↔ o = .lt ∨ o = .eq := by
215+
cases o <;> simp
216+
217+
theorem isLE_of_eq_lt {o : Ordering} : o = .lt → o.isLE := by
218+
rintro rfl; rfl
219+
220+
theorem isLE_of_eq_eq {o : Ordering} : o = .eq → o.isLE := by
221+
rintro rfl; rfl
222+
223+
theorem isEq_iff_eq_eq {o : Ordering} : o.isEq ↔ o = .eq := by
224+
cases o <;> simp
225+
226+
theorem isNe_iff_ne_eq {o : Ordering} : o.isNe ↔ o ≠ .eq := by
227+
cases o <;> simp
228+
229+
theorem isGE_iff_eq_gt_or_eq_eq {o : Ordering} : o.isGE ↔ o = .gt ∨ o = .eq := by
230+
cases o <;> simp
231+
232+
theorem isGE_of_eq_gt {o : Ordering} : o = .gt → o.isGE := by
233+
rintro rfl; rfl
234+
235+
theorem isGE_of_eq_eq {o : Ordering} : o = .eq → o.isGE := by
236+
rintro rfl; rfl
237+
238+
theorem isGT_iff_eq_gt {o : Ordering} : o.isGT ↔ o = .gt := by
239+
cases o <;> simp
240+
241+
@[simp]
242+
theorem swap_swap {o : Ordering} : o.swap.swap = o := by
243+
cases o <;> simp
244+
245+
@[simp] theorem swap_inj {o₁ o₂ : Ordering} : o₁.swap = o₂.swap ↔ o₁ = o₂ :=
246+
fun h => by simpa using congrArg swap h, congrArg _⟩
247+
248+
theorem swap_then (o₁ o₂ : Ordering) : (o₁.then o₂).swap = o₁.swap.then o₂.swap := by
249+
cases o₁ <;> rfl
250+
251+
theorem then_eq_lt {o₁ o₂ : Ordering} : o₁.then o₂ = lt ↔ o₁ = lt ∨ o₁ = eq ∧ o₂ = lt := by
252+
cases o₁ <;> cases o₂ <;> decide
253+
254+
theorem then_eq_eq {o₁ o₂ : Ordering} : o₁.then o₂ = eq ↔ o₁ = eq ∧ o₂ = eq := by
255+
cases o₁ <;> simp [«then»]
256+
257+
theorem then_eq_gt {o₁ o₂ : Ordering} : o₁.then o₂ = gt ↔ o₁ = gt ∨ o₁ = eq ∧ o₂ = gt := by
258+
cases o₁ <;> cases o₂ <;> decide
259+
260+
end Lemmas
261+
89262
end Ordering
90263

91264
/--

tests/lean/run/simpConfigPropagationIssue3.lean

-9
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,3 @@
1-
namespace Ordering
2-
3-
@[simp] theorem swap_swap {o : Ordering} : o.swap.swap = o := by cases o <;> rfl
4-
5-
@[simp] theorem swap_inj {o₁ o₂ : Ordering} : o₁.swap = o₂.swap ↔ o₁ = o₂ :=
6-
fun h => by simpa using congrArg swap h, congrArg _⟩
7-
8-
end Ordering
9-
101
/-- `OrientedCmp cmp` asserts that `cmp` is determined by the relation `cmp x y = .lt`. -/
112
class OrientedCmp (cmp : α → α → Ordering) : Prop where
123
/-- The comparator operation is symmetric, in the sense that if `cmp x y` equals `.lt` then

0 commit comments

Comments
 (0)