Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

Commit a30b7c7

Browse files
committed
feat(data/string): fix string_lt, add repr for multiset, pnat
1 parent fbe1047 commit a30b7c7

File tree

8 files changed

+242
-59
lines changed

8 files changed

+242
-59
lines changed

data/char.lean

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/-
2+
Copyright (c) 2018 Mario Carneiro. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Author: Mario Carneiro
5+
6+
Supplementary theorems about the `char` type.
7+
-/
8+
9+
instance : decidable_linear_order char :=
10+
{ le_refl := λ a, @le_refl ℕ _ _,
11+
le_trans := λ a b c, @le_trans ℕ _ _ _ _,
12+
le_antisymm := λ a b h₁ h₂,
13+
char.eq_of_veq $ le_antisymm h₁ h₂,
14+
le_total := λ a b, @le_total ℕ _ _ _,
15+
lt_iff_le_not_le := λ a b, @lt_iff_le_not_le ℕ _ _ _,
16+
decidable_le := char.decidable_le,
17+
decidable_eq := char.decidable_eq,
18+
decidable_lt := char.decidable_lt,
19+
..char.has_le, ..char.has_lt }

data/finset.lean

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1224,6 +1224,8 @@ theorem sort_sorted_lt [decidable_linear_order α] (s : finset α) :
12241224
list.sorted (<) (sort (≤) s) :=
12251225
(sort_sorted _ _).imp₂ (@lt_of_le_of_ne _ _) (sort_nodup _ _)
12261226

1227+
instance [has_repr α] : has_repr (finset α) := ⟨λ s, repr s.1
1228+
12271229
end finset
12281230

12291231
namespace list

data/list/basic.lean

Lines changed: 136 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ Basic properties of lists.
88
import
99
tactic.interactive tactic.mk_iff_of_inductive_prop tactic.split_ifs
1010
logic.basic logic.function logic.relation
11-
algebra.group
11+
algebra.group order.basic
1212
data.nat.basic data.option data.bool data.prod data.sigma data.fin
1313
open function nat
1414

@@ -352,12 +352,12 @@ by induction l₂ with b l₂ ih; simp
352352

353353
local attribute [simp] reverse_core
354354

355-
@[simp] theorem reverse_cons (a : α) (l : list α) : reverse (a::l) = concat (reverse l) a :=
356-
have aux : ∀ l₁ l₂, reverse_core l₁ (concat l₂ a) = concat (reverse_core l₁ l₂) a,
357-
by intros l₁; induction l₁; intros; rsimp,
358-
aux l nil
355+
@[simp] theorem reverse_cons (a : α) (l : list α) : reverse (a::l) = reverse l ++ [a] :=
356+
have aux : ∀ l₁ l₂, reverse_core l₁ l₂ ++ [a] = reverse_core l₁ (l₂ ++ [a]),
357+
by intro l₁; induction l₁; simp *,
358+
(aux l nil).symm
359359

360-
theorem reverse_cons' (a : α) (l : list α) : reverse (a::l) = reverse l ++ [a] :=
360+
theorem reverse_cons' (a : α) (l : list α) : reverse (a::l) = concat (reverse l) a :=
361361
by simp
362362

363363
@[simp] theorem reverse_singleton (a : α) : reverse [a] = [a] := rfl
@@ -1085,6 +1085,133 @@ by induction L; simp *
10851085
@[simp] theorem length_bind (l : list α) (f : α → list β) : length (list.bind l f) = sum (map (length ∘ f) l) :=
10861086
by rw [list.bind, length_join, map_map]
10871087

1088+
/- lexicographic ordering -/
1089+
1090+
inductive lex (r : α → α → Prop) : list α → list α → Prop
1091+
| nil {} {a l} : lex [] (a :: l)
1092+
| cons {a l₁ l₂} (h : lex l₁ l₂) : lex (a :: l₁) (a :: l₂)
1093+
| rel {a₁ l₁ a₂ l₂} (h : r a₁ a₂) : lex (a₁ :: l₁) (a₂ :: l₂)
1094+
1095+
namespace lex
1096+
theorem cons_iff {r : α → α → Prop} [is_irrefl α r] {a l₁ l₂} :
1097+
lex r (a :: l₁) (a :: l₂) ↔ lex r l₁ l₂ :=
1098+
⟨λ h, by cases h with _ _ _ _ _ h _ _ _ _ h;
1099+
[exact h, exact (irrefl_of r a h).elim], lex.cons⟩
1100+
1101+
instance is_order_connected (r : α → α → Prop)
1102+
[is_order_connected α r] [is_trichotomous α r] :
1103+
is_order_connected (list α) (lex r) :=
1104+
⟨λ l₁, match l₁ with
1105+
| _, [], c::l₃, nil := or.inr nil
1106+
| _, [], c::l₃, rel _ := or.inr nil
1107+
| _, [], c::l₃, cons _ := or.inr nil
1108+
| _, b::l₂, c::l₃, nil := or.inl nil
1109+
| a::l₁, b::l₂, c::l₃, rel h :=
1110+
(is_order_connected.conn _ b _ h).imp rel rel
1111+
| a::l₁, b::l₂, _::l₃, cons h := begin
1112+
rcases trichotomous_of r a b with ab | rfl | ab,
1113+
{ exact or.inl (rel ab) },
1114+
{ exact (_match _ l₂ _ h).imp cons cons },
1115+
{ exact or.inr (rel ab) }
1116+
end
1117+
end
1118+
1119+
instance is_trichotomous (r : α → α → Prop) [is_trichotomous α r] :
1120+
is_trichotomous (list α) (lex r) :=
1121+
⟨λ l₁, match l₁ with
1122+
| [], [] := or.inr (or.inl rfl)
1123+
| [], b::l₂ := or.inl nil
1124+
| a::l₁, [] := or.inr (or.inr nil)
1125+
| a::l₁, b::l₂ := begin
1126+
rcases trichotomous_of r a b with ab | rfl | ab,
1127+
{ exact or.inl (rel ab) },
1128+
{ exact (_match l₁ l₂).imp cons
1129+
(or.imp (congr_arg _) cons) },
1130+
{ exact or.inr (or.inr (rel ab)) }
1131+
end
1132+
end
1133+
1134+
instance is_asymm (r : α → α → Prop)
1135+
[is_asymm α r] : is_asymm (list α) (lex r) :=
1136+
⟨λ l₁, match l₁ with
1137+
| a::l₁, b::l₂, lex.rel h₁, lex.rel h₂ := asymm h₁ h₂
1138+
| a::l₁, b::l₂, lex.rel h₁, lex.cons h₂ := asymm h₁ h₁
1139+
| a::l₁, b::l₂, lex.cons h₁, lex.rel h₂ := asymm h₂ h₂
1140+
| a::l₁, b::l₂, lex.cons h₁, lex.cons h₂ :=
1141+
by exact _match _ _ h₁ h₂
1142+
end
1143+
1144+
instance is_strict_total_order (r : α → α → Prop)
1145+
[is_strict_total_order' α r] : is_strict_total_order' (list α) (lex r) :=
1146+
{..is_strict_weak_order_of_is_order_connected}
1147+
1148+
instance decidable_rel [decidable_eq α] (r : α → α → Prop)
1149+
[decidable_rel r] : decidable_rel (lex r)
1150+
| l₁ [] := is_false $ λ h, by cases h
1151+
| [] (b::l₂) := is_true lex.nil
1152+
| (a::l₁) (b::l₂) := begin
1153+
haveI := decidable_rel l₁ l₂,
1154+
refine decidable_of_iff (r a b ∨ a = b ∧ lex r l₁ l₂) ⟨λ h, _, λ h, _⟩,
1155+
{ rcases h with h | ⟨rfl, h⟩,
1156+
{ exact lex.rel h },
1157+
{ exact lex.cons h } },
1158+
{ rcases h with _|⟨_,_,_,h⟩|⟨_,_,_,_,h⟩,
1159+
{ exact or.inr ⟨rfl, h⟩ },
1160+
{ exact or.inl h } }
1161+
end
1162+
1163+
theorem append_right (r : α → α → Prop) :
1164+
∀ {s₁ s₂} t, lex r s₁ s₂ → lex r s₁ (s₂ ++ t)
1165+
| _ _ t nil := nil
1166+
| _ _ t (cons h) := cons (append_right _ h)
1167+
| _ _ t (rel r) := rel r
1168+
1169+
theorem append_left (R : α → α → Prop) {t₁ t₂} (h : lex R t₁ t₂) :
1170+
∀ s, lex R (s ++ t₁) (s ++ t₂)
1171+
| [] := h
1172+
| (a::l) := cons (append_left l)
1173+
1174+
theorem imp {r s : α → α → Prop} (H : ∀ a b, r a b → s a b) :
1175+
∀ l₁ l₂, lex r l₁ l₂ → lex s l₁ l₂
1176+
| _ _ nil := nil
1177+
| _ _ (cons h) := cons (imp _ _ h)
1178+
| _ _ (rel r) := rel (H _ _ r)
1179+
1180+
theorem to_ne : ∀ {l₁ l₂ : list α}, lex (≠) l₁ l₂ → l₁ ≠ l₂
1181+
| _ _ (cons h) e := to_ne h (list.cons.inj e).2
1182+
| _ _ (rel r) e := r (list.cons.inj e).1
1183+
1184+
theorem ne_iff {l₁ l₂ : list α} (H : length l₁ ≤ length l₂) :
1185+
lex (≠) l₁ l₂ ↔ l₁ ≠ l₂ :=
1186+
⟨to_ne, λ h, begin
1187+
induction l₁ with a l₁ IH generalizing l₂; cases l₂ with b l₂,
1188+
{ contradiction },
1189+
{ apply nil },
1190+
{ exact (not_lt_of_ge H).elim (succ_pos _) },
1191+
{ cases classical.em (a = b) with ab ab,
1192+
{ subst b, apply cons,
1193+
exact IH (le_of_succ_le_succ H) (mt (congr_arg _) h) },
1194+
{ exact rel ab } }
1195+
end
1196+
1197+
end lex
1198+
1199+
--Note: this overrides an instance in core lean
1200+
instance has_lt' [has_lt α] : has_lt (list α) := ⟨lex (<)⟩
1201+
1202+
theorem nil_lt_cons [has_lt α] (a : α) (l : list α) : [] < a :: l :=
1203+
lex.nil
1204+
1205+
instance [linear_order α] : linear_order (list α) :=
1206+
linear_order_of_STO' (lex (<))
1207+
1208+
--Note: this overrides an instance in core lean
1209+
instance has_le' [linear_order α] : has_le (list α) :=
1210+
preorder.to_has_le _
1211+
1212+
instance [decidable_linear_order α] : decidable_linear_order (list α) :=
1213+
decidable_linear_order_of_STO' (lex (<))
1214+
10881215
/- all & any, bounded quantifiers over lists -/
10891216

10901217
theorem forall_mem_nil (p : α → Prop) : ∀ x ∈ @nil α, p x :=
@@ -2892,56 +3019,17 @@ theorem pairwise_iff_nth_le {R} : ∀ {l : list α},
28923019
exact H _ _ (succ_lt_succ h) (succ_pos _) }
28933020
end
28943021

2895-
inductive lex (R : α → α → Prop) : list α → list α → Prop
2896-
| nil {} (a l) : lex [] (a::l)
2897-
| cons {} (a) {l l'} : lex l l' → lex (a::l) (a::l')
2898-
| rel {a a'} (l l') : R a a' → lex (a::l) (a'::l')
2899-
2900-
theorem lex_append_right (R : α → α → Prop) :
2901-
∀ {s₁ s₂} t, lex R s₁ s₂ → lex R s₁ (s₂ ++ t)
2902-
| _ _ t (lex.nil a l) := lex.nil _ _
2903-
| _ _ t (lex.cons a h) := lex.cons _ (lex_append_right _ h)
2904-
| _ _ t (lex.rel _ _ r) := lex.rel _ _ r
2905-
2906-
theorem lex_append_left (R : α → α → Prop) {t₁ t₂} (h : lex R t₁ t₂) :
2907-
∀ s, lex R (s ++ t₁) (s ++ t₂)
2908-
| [] := h
2909-
| (a::l) := lex.cons _ (lex_append_left l)
2910-
2911-
theorem lex.imp {R S : α → α → Prop} (H : ∀ a b, R a b → S a b) :
2912-
∀ l₁ l₂, lex R l₁ l₂ → lex S l₁ l₂
2913-
| _ _ (lex.nil a l) := lex.nil _ _
2914-
| _ _ (lex.cons a h) := lex.cons _ (lex.imp _ _ h)
2915-
| _ _ (lex.rel _ _ r) := lex.rel _ _ (H _ _ r)
2916-
2917-
theorem ne_of_lex_ne : ∀ {l₁ l₂ : list α}, lex (≠) l₁ l₂ → l₁ ≠ l₂
2918-
| _ _ (lex.cons a h) e := ne_of_lex_ne h (list.cons.inj e).2
2919-
| _ _ (lex.rel _ _ r) e := r (list.cons.inj e).1
2920-
2921-
theorem lex_ne_iff {l₁ l₂ : list α} (H : length l₁ ≤ length l₂) :
2922-
lex (≠) l₁ l₂ ↔ l₁ ≠ l₂ :=
2923-
⟨ne_of_lex_ne, λ h, begin
2924-
induction l₁ with a l₁ IH generalizing l₂; cases l₂ with b l₂,
2925-
{ contradiction },
2926-
{ apply lex.nil },
2927-
{ exact (not_lt_of_ge H).elim (succ_pos _) },
2928-
{ cases classical.em (a = b) with ab ab,
2929-
{ subst b, apply lex.cons,
2930-
exact IH (le_of_succ_le_succ H) (mt (congr_arg _) h) },
2931-
{ exact lex.rel _ _ ab } }
2932-
end
2933-
29343022
theorem pairwise_sublists' {R} : ∀ {l : list α}, pairwise R l →
29353023
pairwise (lex (swap R)) (sublists' l)
29363024
| _ (pairwise.nil _) := pairwise_singleton _ _
29373025
| _ (@pairwise.cons _ _ a l H₁ H₂) :=
29383026
begin
29393027
simp [pairwise_append, pairwise_map],
29403028
have IH := pairwise_sublists' H₂,
2941-
refine ⟨IH, IH.imp (λ l₁ l₂, lex.cons _), _⟩,
3029+
refine ⟨IH, IH.imp (λ l₁ l₂, lex.cons), _⟩,
29423030
intros l₁ sl₁ x l₂ sl₂ e, subst e,
29433031
cases l₁ with b l₁, {constructor},
2944-
exact lex.rel _ _ (H₁ _ $ subset_of_sublist sl₁ $ mem_cons_self _ _)
3032+
exact lex.rel (H₁ _ $ subset_of_sublist sl₁ $ mem_cons_self _ _)
29453033
end
29463034

29473035
theorem pairwise_sublists {R} {l : list α} (H : pairwise R l) :
@@ -3305,7 +3393,7 @@ nodup_filter _
33053393

33063394
@[simp] theorem nodup_sublists {l : list α} : nodup (sublists l) ↔ nodup l :=
33073395
⟨λ h, nodup_of_nodup_map _ (nodup_of_sublist (map_ret_sublist_sublists _) h),
3308-
λ h, (pairwise_sublists h).imp (λ _ _ h, mt reverse_inj.2 (ne_of_lex_ne h))⟩
3396+
λ h, (pairwise_sublists h).imp (λ _ _ h, mt reverse_inj.2 h.to_ne)⟩
33093397

33103398
@[simp] theorem nodup_sublists' {l : list α} : nodup (sublists' l) ↔ nodup l :=
33113399
by rw [sublists'_eq_sublists, nodup_map_iff reverse_injective,

data/list/perm.lean

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ end
115115

116116
@[simp] theorem reverse_perm : ∀ (l : list α), reverse l ~ l
117117
| [] := perm.nil
118-
| (a::l) := by rw reverse_cons'; exact
118+
| (a::l) := by rw reverse_cons; exact
119119
(perm_cons_app _ _).trans (skip a $ reverse_perm l)
120120

121121
theorem perm_cons_app_cons {l l₁ l₂ : list α} (a : α) (p : l ~ l₁++l₂) : a::l ~ l₁++(a::l₂) :=

data/multiset.lean

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@ Author: Mario Carneiro
55
66
Multisets.
77
-/
8-
import logic.function data.list.basic data.list.perm data.list.sort order.boolean_algebra
9-
algebra.order_functions data.quot algebra.group_power algebra.ordered_group
8+
import logic.function order.boolean_algebra
9+
data.list.basic data.list.perm data.list.sort data.quot data.string
10+
algebra.order_functions algebra.group_power algebra.ordered_group
11+
1012
open list subtype nat lattice
1113

1214
variables {α : Type*} {β : Type*} {γ : Type*}
@@ -2333,6 +2335,9 @@ quot.induction_on s $ λ l, quot.sound $ perm_merge_sort _ _
23332335

23342336
end sort
23352337

2338+
instance [has_repr α] : has_repr (multiset α) :=
2339+
⟨λ s, "{" ++ string.intercalate ", " ((s.map repr).sort (≤)) ++ "}"
2340+
23362341
section sections
23372342

23382343
def sections (s : multiset (multiset α)) : multiset (multiset α) :=

data/pnat.lean

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,6 @@ instance : has_pow ℕ+ ℕ := ⟨pow⟩
6969

7070
@[simp] theorem pow_coe (m : ℕ+) (n : ℕ) : (↑(m ^ n) : ℕ) = m ^ n := rfl
7171

72+
instance : has_repr ℕ+ := ⟨λ n, repr n.1
73+
7274
end pnat

data/string.lean

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
/-
2+
Copyright (c) 2018 Mario Carneiro. All rights reserved.
3+
Released under Apache 2.0 license as described in the file LICENSE.
4+
Author: Mario Carneiro
5+
6+
Supplementary theorems about the `string` type.
7+
-/
8+
import data.list.basic data.char
9+
10+
namespace string
11+
12+
def ltb : iterator → iterator → bool
13+
| s₁ s₂ := begin
14+
cases s₂.has_next, {exact ff},
15+
cases h₁ : s₁.has_next, {exact tt},
16+
exact if s₁.curr = s₂.curr then
17+
have s₁.next.2.length < s₁.2.length, from
18+
match s₁, h₁ with ⟨_, a::l⟩, h := nat.lt_succ_self _ end,
19+
ltb s₁.next s₂.next
20+
else s₁.curr < s₂.curr,
21+
end
22+
using_well_founded {rel_tac :=
23+
λ _ _, `[exact ⟨_, measure_wf (λ s, s.1.2.length)⟩]}
24+
25+
instance has_lt' : has_lt string :=
26+
⟨λ s₁ s₂, ltb s₁.mk_iterator s₂.mk_iterator⟩
27+
28+
instance decidable_lt : @decidable_rel string (<) := by apply_instance
29+
30+
@[simp] theorem lt_iff_to_list_lt :
31+
∀ {s₁ s₂ : string}, s₁ < s₂ ↔ s₁.to_list < s₂.to_list
32+
| ⟨i₁⟩ ⟨i₂⟩ :=
33+
suffices ∀ {p₁ p₂ s₁ s₂}, ltb ⟨p₁, s₁⟩ ⟨p₂, s₂⟩ ↔ s₁ < s₂, from this,
34+
begin
35+
intros,
36+
induction s₁ with a s₁ IH generalizing p₁ p₂ s₂;
37+
cases s₂ with b s₂; rw ltb; simp [iterator.has_next],
38+
{ exact iff_of_false bool.ff_ne_tt (lt_irrefl _) },
39+
{ exact iff_of_true rfl list.lex.nil },
40+
{ exact iff_of_false bool.ff_ne_tt (not_lt_of_lt list.lex.nil) },
41+
{ dsimp [iterator.has_next,
42+
iterator.curr, iterator.next],
43+
split_ifs,
44+
{ subst b, exact IH.trans list.lex.cons_iff.symm },
45+
{ simp, refine ⟨list.lex.rel, λ e, _⟩,
46+
cases e, {cases h rfl}, assumption } }
47+
end
48+
49+
instance has_le : has_le string := ⟨λ s₁ s₂, ¬ s₂ < s₁⟩
50+
51+
instance decidable_le : @decidable_rel string (≤) := by apply_instance
52+
53+
@[simp] theorem le_iff_to_list_le
54+
{s₁ s₂ : string} : s₁ ≤ s₂ ↔ s₁.to_list ≤ s₂.to_list :=
55+
(not_congr lt_iff_to_list_lt).trans not_lt
56+
57+
theorem to_list_inj : ∀ {s₁ s₂}, to_list s₁ = to_list s₂ ↔ s₁ = s₂
58+
| ⟨s₁⟩ ⟨s₂⟩ := ⟨congr_arg _, congr_arg _⟩
59+
60+
instance : decidable_linear_order string :=
61+
by refine_struct {
62+
lt := (<), le := (≤),
63+
le_antisymm := by simp; exact
64+
λ a b h₁ h₂, to_list_inj.1 (le_antisymm h₁ h₂),
65+
decidable_lt := by apply_instance,
66+
decidable_le := string.decidable_le,
67+
decidable_eq := by apply_instance, .. };
68+
{ simp [-not_le], introv, apply_field }
69+
70+
end string

order/basic.lean

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -206,18 +206,15 @@ instance [linear_order α] : is_strict_total_order' α (<) := {}
206206
@[algebra] class is_order_connected (α : Type u) (lt : α → α → Prop) : Prop :=
207207
(conn : ∀ a b c, lt a c → lt a b ∨ lt b c)
208208

209-
theorem is_order_connected.neg_trans (r : α → α → Prop) [is_order_connected α r]
209+
theorem is_order_connected.neg_trans {r : α → α → Prop} [is_order_connected α r]
210210
{a b c} (h₁ : ¬ r a b) (h₂ : ¬ r b c) : ¬ r a c :=
211211
mt (is_order_connected.conn a b c) $ by simp [h₁, h₂]
212212

213-
theorem is_strict_weak_order_of_is_order_connected [is_asymm α r] :
214-
∀ [is_order_connected α r], is_strict_weak_order α r
215-
| ⟨H⟩ := {
216-
trans := λ a b c h₁ h₂, (H _ c _ h₁).resolve_right (asymm h₂),
213+
theorem is_strict_weak_order_of_is_order_connected [is_asymm α r]
214+
[is_order_connected α r] : is_strict_weak_order α r :=
215+
{ trans := λ a b c h₁ h₂, (is_order_connected.conn _ c _ h₁).resolve_right (asymm h₂),
217216
incomp_trans := λ a b c ⟨h₁, h₂⟩ ⟨h₃, h₄⟩,
218-
have H' : ∀ {a b c}, ¬ r a b → ¬ r b c → ¬ r a c,
219-
from λ a b c, by simpa [not_or_distrib] using mt (H a b c),
220-
⟨H' h₁ h₃, H' h₄ h₂⟩,
217+
⟨is_order_connected.neg_trans h₁ h₃, is_order_connected.neg_trans h₄ h₂⟩,
221218
..@is_irrefl_of_is_asymm α r _ }
222219

223220
instance is_order_connected_of_is_strict_total_order'

0 commit comments

Comments
 (0)