Skip to content

Commit 463b024

Browse files
j-loreauxkim-em
andcommitted
feat(Data.Prod.Lex): port file (#783)
mathlib3 SHA: 1fc36cc9c8264e6e81253f88be7fb2cb6c92d76a porting notes: there are several issues here that should probably be fixed before this gets merged 1. `Prod.Lex` is not protect in core, so when you have this namespace open and try to refer to `Lex`, Lean finds `Prod.Lex` instead of `_root_.Lex`. This is not a huge deal since we have notation `α ×ₗ β`, but we should probably ask for it to be protected in core. See leanprover/lean4#1895 2. on the declarations `toLex_mono` and `toLex_strictMono`, Lean sees right through the type synonym `α ×ₗ β` to `α × β` and uses the wrong `Preorder` instance, which is why I had to provide them manually. I think this is a bug and should be fixed, otherwise it will cause loads of other issues down the road (for other type synonyms) and the errors will be hard to diagnose. EDIT: Hopefully leanprover/lean4#1891 will provide a fix. 3. I had to provide the definitions of `min` and `max` for the `LinearOrder` instance manually because in Lean 4 we have the classes `Min` and `Max` which have no counterpart in Lean 3. In this case it's a bit annoying because `ite` requires decidability, so I effectively had to provide that three times in this instance declaration. Surely there should be a better way? Co-authored-by: Scott Morrison <scott.morrison@gmail.com>
1 parent 68d5751 commit 463b024

File tree

8 files changed

+221
-14
lines changed

8 files changed

+221
-14
lines changed

.github/workflows/bors.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ jobs:
2121
steps:
2222
- name: cleanup
2323
run: |
24-
rm -rf *
24+
find . -name . -o -prune -exec rm -rf -- {} +
2525
2626
- uses: actions/checkout@v2
2727

@@ -42,7 +42,7 @@ jobs:
4242
steps:
4343
- name: cleanup
4444
run: |
45-
rm -rf *
45+
find . -name . -o -prune -exec rm -rf -- {} +
4646
4747
- uses: actions/checkout@v2
4848

@@ -60,7 +60,7 @@ jobs:
6060
steps:
6161
- name: cleanup
6262
run: |
63-
rm -rf *
63+
find . -name . -o -prune -exec rm -rf -- {} +
6464
6565
- name: install elan
6666
run: |

.github/workflows/build.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ jobs:
2727
steps:
2828
- name: cleanup
2929
run: |
30-
rm -rf *
30+
find . -name . -o -prune -exec rm -rf -- {} +
3131
3232
- uses: actions/checkout@v2
3333

@@ -48,7 +48,7 @@ jobs:
4848
steps:
4949
- name: cleanup
5050
run: |
51-
rm -rf *
51+
find . -name . -o -prune -exec rm -rf -- {} +
5252
5353
- uses: actions/checkout@v2
5454

@@ -66,7 +66,7 @@ jobs:
6666
steps:
6767
- name: cleanup
6868
run: |
69-
rm -rf *
69+
find . -name . -o -prune -exec rm -rf -- {} +
7070
7171
- name: install elan
7272
run: |

.github/workflows/build.yml.in

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ jobs:
77
steps:
88
- name: cleanup
99
run: |
10-
rm -rf *
10+
find . -name . -o -prune -exec rm -rf -- {} +
1111

1212
- uses: actions/checkout@v2
1313

@@ -28,7 +28,7 @@ jobs:
2828
steps:
2929
- name: cleanup
3030
run: |
31-
rm -rf *
31+
find . -name . -o -prune -exec rm -rf -- {} +
3232

3333
- uses: actions/checkout@v2
3434

@@ -46,7 +46,7 @@ jobs:
4646
steps:
4747
- name: cleanup
4848
run: |
49-
rm -rf *
49+
find . -name . -o -prune -exec rm -rf -- {} +
5050

5151
- name: install elan
5252
run: |

.github/workflows/build_fork.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ jobs:
2525
steps:
2626
- name: cleanup
2727
run: |
28-
rm -rf *
28+
find . -name . -o -prune -exec rm -rf -- {} +
2929
3030
- uses: actions/checkout@v2
3131

@@ -46,7 +46,7 @@ jobs:
4646
steps:
4747
- name: cleanup
4848
run: |
49-
rm -rf *
49+
find . -name . -o -prune -exec rm -rf -- {} +
5050
5151
- uses: actions/checkout@v2
5252

@@ -64,7 +64,7 @@ jobs:
6464
steps:
6565
- name: cleanup
6666
run: |
67-
rm -rf *
67+
find . -name . -o -prune -exec rm -rf -- {} +
6868
6969
- name: install elan
7070
run: |

Mathlib.lean

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,7 @@ import Mathlib.Data.Option.NAry
9696
import Mathlib.Data.PNat.Defs
9797
import Mathlib.Data.Pi.Algebra
9898
import Mathlib.Data.Prod.Basic
99+
import Mathlib.Data.Prod.Lex
99100
import Mathlib.Data.Prod.PProd
100101
import Mathlib.Data.Quot
101102
import Mathlib.Data.Rat.Defs

Mathlib/Data/Prod/Basic.lean

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ theorem fst_eq_iff : ∀ {p : α × β} {x : α}, p.1 = x ↔ p = (x, p.2)
175175
theorem snd_eq_iff : ∀ {p : α × β} {x : β}, p.2 = x ↔ p = (p.1, x)
176176
| ⟨a, b⟩, x => by simp
177177

178-
theorem Lex_def (r : α → α → Prop) (s : β → β → Prop) {p q : α × β} :
178+
theorem lex_def (r : α → α → Prop) (s : β → β → Prop) {p q : α × β} :
179179
Prod.Lex r s p q ↔ r p.1 q.1 ∨ p.1 = q.1 ∧ s p.2 q.2 :=
180180
fun h ↦ by cases h <;> simp [*], fun h ↦
181181
match p, q, h with
@@ -185,7 +185,7 @@ theorem Lex_def (r : α → α → Prop) (s : β → β → Prop) {p q : α ×
185185
instance Lex.decidable [DecidableEq α]
186186
(r : α → α → Prop) (s : β → β → Prop) [DecidableRel r] [DecidableRel s] :
187187
DecidableRel (Prod.Lex r s) :=
188-
fun _ _ ↦ decidable_of_decidable_of_iff (Lex_def r s).symm
188+
fun _ _ ↦ decidable_of_decidable_of_iff (lex_def r s).symm
189189

190190
@[refl]
191191
theorem Lex.refl_left (r : α → α → Prop) (s : β → β → Prop) [IsRefl α r] : ∀ x, Prod.Lex r s x x

Mathlib/Data/Prod/Lex.lean

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
/-
2+
Copyright (c) 2019 Scott Morrison. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Authors: Scott Morrison, Minchao Wu
5+
-/
6+
import Mathlib.Order.BoundedOrder
7+
8+
/-!
9+
# Lexicographic order
10+
11+
This file defines the lexicographic relation for pairs of orders, partial orders and linear orders.
12+
13+
## Main declarations
14+
15+
* `Prod.Lex.<pre/partial/linear>Order`: Instances lifting the orders on `α` and `β` to `α ×ₗ β`.
16+
17+
## Notation
18+
19+
* `α ×ₗ β`: `α × β` equipped with the lexicographic order
20+
21+
## See also
22+
23+
Related files are:
24+
* `Data.Finset.CoLex`: Colexicographic order on finite sets.
25+
* `Data.List.Lex`: Lexicographic order on lists.
26+
* `Data.Pi.Lex`: Lexicographic order on `Πₗ i, α i`.
27+
* `Data.PSigma.Order`: Lexicographic order on `Σ' i, α i`.
28+
* `Data.Sigma.Order`: Lexicographic order on `Σ i, α i`.
29+
-/
30+
31+
32+
variable {α β γ : Type _}
33+
34+
namespace Prod.Lex
35+
36+
-- porting note: `Prod.Lex` is not protected in core, hence the `_root_.` prefix
37+
-- This will be fixed in nightly-2022-11-30
38+
@[inherit_doc] notation:35 α " ×ₗ " β:34 => _root_.Lex (Prod α β)
39+
40+
instance decidableEq (α β : Type _) [DecidableEq α] [DecidableEq β] : DecidableEq (α ×ₗ β) :=
41+
instDecidableEqProd
42+
#align prod.lex.decidable_eq Prod.Lex.decidableEq
43+
44+
instance inhabited (α β : Type _) [Inhabited α] [Inhabited β] : Inhabited (α ×ₗ β) :=
45+
instInhabitedProd
46+
#align prod.lex.inhabited Prod.Lex.inhabited
47+
48+
/-- Dictionary / lexicographic ordering on pairs. -/
49+
instance instLE (α β : Type _) [LT α] [LE β] : LE (α ×ₗ β) where le := Prod.Lex (· < ·) (· ≤ ·)
50+
#align prod.lex.has_le Prod.Lex.instLE
51+
52+
instance instLT (α β : Type _) [LT α] [LT β] : LT (α ×ₗ β) where lt := Prod.Lex (· < ·) (· < ·)
53+
#align prod.lex.has_lt Prod.Lex.instLT
54+
55+
theorem le_iff [LT α] [LE β] (a b : α × β) :
56+
toLex a ≤ toLex b ↔ a.1 < b.1 ∨ a.1 = b.1 ∧ a.2 ≤ b.2 :=
57+
Prod.lex_def (· < ·) (· ≤ ·)
58+
#align prod.lex.le_iff Prod.Lex.le_iff
59+
60+
theorem lt_iff [LT α] [LT β] (a b : α × β) :
61+
toLex a < toLex b ↔ a.1 < b.1 ∨ a.1 = b.1 ∧ a.2 < b.2 :=
62+
Prod.lex_def (· < ·) (· < ·)
63+
#align prod.lex.lt_iff Prod.Lex.lt_iff
64+
65+
example (x : α) (y : β) : toLex (x, y) = toLex (x, y) := rfl
66+
67+
/-- Dictionary / lexicographic preorder for pairs. -/
68+
instance preorder (α β : Type _) [Preorder α] [Preorder β] : Preorder (α ×ₗ β) :=
69+
{ Prod.Lex.instLE α β, Prod.Lex.instLT α β with
70+
le_refl := refl_of <| Prod.Lex _ _,
71+
le_trans := fun _ _ _ => trans_of <| Prod.Lex _ _,
72+
lt_iff_le_not_le := fun x₁ x₂ =>
73+
match x₁, x₂ with
74+
| (a₁, b₁), (a₂, b₂) => by
75+
constructor
76+
· rintro (⟨_, _, hlt⟩ | ⟨_, hlt⟩)
77+
· constructor
78+
· exact left _ _ hlt
79+
· rintro ⟨⟩
80+
· apply lt_asymm hlt; assumption
81+
· exact lt_irrefl _ hlt
82+
· constructor
83+
· right
84+
rw [lt_iff_le_not_le] at hlt
85+
exact hlt.1
86+
· rintro ⟨⟩
87+
· apply lt_irrefl a₁
88+
assumption
89+
· rw [lt_iff_le_not_le] at hlt
90+
apply hlt.2
91+
assumption
92+
· rintro ⟨⟨⟩, h₂r⟩
93+
· left
94+
assumption
95+
· right
96+
rw [lt_iff_le_not_le]
97+
constructor
98+
· assumption
99+
· intro h
100+
apply h₂r
101+
right
102+
exact h }
103+
#align prod.lex.preorder Prod.Lex.preorder
104+
105+
section Preorder
106+
107+
variable [PartialOrder α] [Preorder β]
108+
109+
-- porting note: type class search sees right through the type synonrm for `α ×ₗ β` and uses the
110+
-- `Preorder` structure for `α × β` instead
111+
-- This is hopefully the same problems as in https://github.com/leanprover/lean4/issues/1891
112+
-- and will be fixed in nightly-2022-11-30
113+
theorem toLex_mono : @Monotone _ _ _ (Prod.Lex.preorder α β) (toLex : α × β → α ×ₗ β) := by
114+
rintro ⟨a₁, b₁⟩ ⟨a₂, b₂⟩ ⟨ha, hb⟩
115+
obtain rfl | ha : a₁ = a₂ ∨ _ := ha.eq_or_lt
116+
· exact right _ hb
117+
· exact left _ _ ha
118+
#align prod.lex.to_lex_mono Prod.Lex.toLex_mono
119+
120+
-- porting note: type class search sees right through the type synonrm for `α ×ₗ β` and uses the
121+
-- `Preorder` structure for `α × β` instead
122+
-- This is hopefully the same problems as in https://github.com/leanprover/lean4/issues/1891
123+
-- and will be fixed in nightly-2022-11-30
124+
theorem toLex_strictMono : @StrictMono _ _ _ (Prod.Lex.preorder α β) (toLex : α × β → α ×ₗ β) := by
125+
rintro ⟨a₁, b₁⟩ ⟨a₂, b₂⟩ h
126+
obtain rfl | ha : a₁ = a₂ ∨ _ := h.le.1.eq_or_lt
127+
· exact right _ (Prod.mk_lt_mk_iff_right.1 h)
128+
· exact left _ _ ha
129+
130+
#align prod.lex.to_lex_strict_mono Prod.Lex.toLex_strictMono
131+
132+
end Preorder
133+
134+
/-- Dictionary / lexicographic partial order for pairs. -/
135+
instance partialOrder (α β : Type _) [PartialOrder α] [PartialOrder β] : PartialOrder (α ×ₗ β) :=
136+
{ Prod.Lex.preorder α β with
137+
le_antisymm := by
138+
haveI : IsStrictOrder α (· < ·) := { irrefl := lt_irrefl, trans := fun _ _ _ => lt_trans }
139+
haveI : IsAntisymm β (· ≤ ·) := ⟨fun _ _ => le_antisymm⟩
140+
exact @antisymm _ (Prod.Lex _ _) _ }
141+
#align prod.lex.partial_order Prod.Lex.partialOrder
142+
143+
/-- Dictionary / lexicographic linear order for pairs. -/
144+
instance linearOrder (α β : Type _) [LinearOrder α] [LinearOrder β] : LinearOrder (α ×ₗ β) :=
145+
{ Prod.Lex.partialOrder α β with
146+
le_total := total_of (Prod.Lex _ _),
147+
decidable_le := Prod.Lex.decidable _ _,
148+
decidable_lt := Prod.Lex.decidable _ _,
149+
decidable_eq := Lex.decidableEq _ _, }
150+
#align prod.lex.linear_order Prod.Lex.linearOrder
151+
152+
instance orderBot [PartialOrder α] [Preorder β] [OrderBot α] [OrderBot β] : OrderBot (α ×ₗ β) where
153+
bot := toLex ⊥
154+
bot_le _ := toLex_mono bot_le
155+
#align prod.lex.order_bot Prod.Lex.orderBot
156+
157+
instance orderTop [PartialOrder α] [Preorder β] [OrderTop α] [OrderTop β] : OrderTop (α ×ₗ β) where
158+
top := toLex ⊤
159+
le_top _ := toLex_mono le_top
160+
#align prod.lex.order_top Prod.Lex.orderTop
161+
162+
instance boundedOrder [PartialOrder α] [Preorder β] [BoundedOrder α] [BoundedOrder β] :
163+
BoundedOrder (α ×ₗ β) :=
164+
{ Lex.orderBot, Lex.orderTop with }
165+
#align prod.lex.bounded_order Prod.Lex.boundedOrder
166+
167+
instance [Preorder α] [Preorder β] [DenselyOrdered α] [DenselyOrdered β] :
168+
DenselyOrdered (α ×ₗ β) where
169+
dense := by
170+
rintro _ _ (@⟨a₁, b₁, a₂, b₂, h⟩ | @⟨a, b₁, b₂, h⟩)
171+
· obtain ⟨c, h₁, h₂⟩ := exists_between h
172+
exact ⟨(c, b₁), left _ _ h₁, left _ _ h₂⟩
173+
· obtain ⟨c, h₁, h₂⟩ := exists_between h
174+
exact ⟨(a, c), right _ h₁, right _ h₂⟩
175+
176+
instance noMaxOrder_of_left [Preorder α] [Preorder β] [NoMaxOrder α] : NoMaxOrder (α ×ₗ β) where
177+
exists_gt := by
178+
rintro ⟨a, b⟩
179+
obtain ⟨c, h⟩ := exists_gt a
180+
exact ⟨⟨c, b⟩, left _ _ h⟩
181+
#align prod.lex.no_max_order_of_left Prod.Lex.noMaxOrder_of_left
182+
183+
instance noMinOrder_of_left [Preorder α] [Preorder β] [NoMinOrder α] : NoMinOrder (α ×ₗ β) where
184+
exists_lt := by
185+
rintro ⟨a, b⟩
186+
obtain ⟨c, h⟩ := exists_lt a
187+
exact ⟨⟨c, b⟩, left _ _ h⟩
188+
#align prod.lex.no_min_order_of_left Prod.Lex.noMinOrder_of_left
189+
190+
instance noMaxOrder_of_right [Preorder α] [Preorder β] [NoMaxOrder β] : NoMaxOrder (α ×ₗ β) where
191+
exists_gt := by
192+
rintro ⟨a, b⟩
193+
obtain ⟨c, h⟩ := exists_gt b
194+
exact ⟨⟨a, c⟩, right _ h⟩
195+
#align prod.lex.no_max_order_of_right Prod.Lex.noMaxOrder_of_right
196+
197+
instance noMinOrder_of_right [Preorder α] [Preorder β] [NoMinOrder β] : NoMinOrder (α ×ₗ β) where
198+
exists_lt := by
199+
rintro ⟨a, b⟩
200+
obtain ⟨c, h⟩ := exists_lt b
201+
exact ⟨⟨a, c⟩, right _ h⟩
202+
#align prod.lex.no_min_order_of_right Prod.Lex.noMinOrder_of_right
203+
204+
end Prod.Lex

Mathlib/Init/Algebra/Order.lean

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,8 @@ class LinearOrder (α : Type u) extends PartialOrder α, Min α, Max α :=
226226
/-- In a linearly ordered type, we assume the order relations are all decidable. -/
227227
decidable_lt : DecidableRel (. < . : α → α → Prop) :=
228228
@decidableLt_of_decidableLe _ _ decidable_le
229+
min := fun a b => if a ≤ b then a else b
230+
max := fun a b => if a ≤ b then b else a
229231
/-- The minimum function is equivalent to the one you get from `minOfLe`. -/
230232
min_def : ∀ a b, min a b = if a ≤ b then a else b := by intros; rfl
231233
/-- The minimum function is equivalent to the one you get from `maxOfLe`. -/

0 commit comments

Comments
 (0)