@@ -25,8 +25,11 @@ Note that we make no guarantees of being the longest sublist with this property;
25
25
adjacent, chain, duplicates, remove, list, stutter, destutter
26
26
-/
27
27
28
+ open Function
28
29
29
- variable {α : Type *} (l : List α) (R : α → α → Prop ) [DecidableRel R] {a b : α}
30
+ variable {α β : Type *} (l l₁ l₂ : List α) (R : α → α → Prop ) [DecidableRel R] {a b : α}
31
+
32
+ variable {R₂ : β → β → Prop } [DecidableRel R₂]
30
33
31
34
namespace List
32
35
@@ -148,4 +151,116 @@ theorem destutter_eq_nil : ∀ {l : List α}, destutter R l = [] ↔ l = []
148
151
| [] => Iff.rfl
149
152
| _ :: l => ⟨fun h => absurd h <| l.destutter'_ne_nil R, fun h => nomatch h⟩
150
153
154
+ variable {R}
155
+
156
+ /-- For a relation-preserving map, `destutter` commutes with `map`. -/
157
+ theorem map_destutter {f : α → β} : ∀ {l : List α}, (∀ a ∈ l, ∀ b ∈ l, R a b ↔ R₂ (f a) (f b)) →
158
+ (l.destutter R).map f = (l.map f).destutter R₂
159
+ | [], hl => by simp
160
+ | [a], hl => by simp
161
+ | a :: b :: l, hl => by
162
+ have := hl a (by simp) b (by simp)
163
+ simp_rw [map_cons, destutter_cons_cons, ← this]
164
+ by_cases hr : R a b <;>
165
+ simp [hr, ← destutter_cons', map_destutter fun c hc d hd ↦ hl _ (cons_subset_cons _
166
+ (subset_cons_self _ _) hc) _ (cons_subset_cons _ (subset_cons_self _ _) hd),
167
+ map_destutter fun c hc d hd ↦ hl _ (subset_cons_self _ _ hc) _ (subset_cons_self _ _ hd)]
168
+
169
+ /-- For a injective function `f`, `destutter' (·≠·)` commutes with `map f`. -/
170
+ theorem map_destutter_ne {f : α → β} (h : Injective f) [DecidableEq α] [DecidableEq β] :
171
+ (l.destutter (·≠·)).map f = (l.map f).destutter (·≠·) :=
172
+ map_destutter fun _ _ _ _ ↦ h.ne_iff.symm
173
+
174
+ /-- `destutter'` on a relation like ≠ or <, whose negation is transitive, has length monotone
175
+ under a `¬R` changing of the first element. -/
176
+ theorem length_destutter'_cotrans_ge [i : IsTrans α Rᶜ] :
177
+ ∀ {a} {l : List α}, ¬R b a → (l.destutter' R b).length ≤ (l.destutter' R a).length
178
+ | a, [], hba => by simp
179
+ | a, c :: l, hba => by
180
+ by_cases hbc : R b c
181
+ case pos =>
182
+ have hac : ¬Rᶜ a c := (mt (_root_.trans hba)) (not_not.2 hbc)
183
+ simp_rw [destutter', if_pos (not_not.1 hac), if_pos hbc, length_cons, le_refl]
184
+ case neg =>
185
+ simp only [destutter', if_neg hbc]
186
+ by_cases hac : R a c
187
+ case pos =>
188
+ simp only [if_pos hac, length_cons]
189
+ exact Nat.le_succ_of_le (length_destutter'_cotrans_ge hbc)
190
+ case neg =>
191
+ simp only [if_neg hac]
192
+ exact length_destutter'_cotrans_ge hba
193
+
194
+ /-- `List.destutter'` on a relation like `≠`, whose negation is an equivalence, gives the same
195
+ length if the first elements are not related. -/
196
+ theorem length_destutter'_congr [IsEquiv α Rᶜ] (hab : ¬R a b) :
197
+ (l.destutter' R a).length = (l.destutter' R b).length :=
198
+ (length_destutter'_cotrans_ge hab).antisymm <| length_destutter'_cotrans_ge (symm hab : Rᶜ b a)
199
+
200
+ /-- `List.destutter'` on a relation like ≠, whose negation is an equivalence, has length
201
+ monotonic under List.cons -/
202
+ /-
203
+ TODO: Replace this lemma by the more general version:
204
+ theorem Sublist.length_destutter'_mono [IsEquiv α Rᶜ] (h : a :: l₁ <+ b :: l₂) :
205
+ (List.destutter' R a l₁).length ≤ (List.destutter' R b l₂).length
206
+ -/
207
+ theorem le_length_destutter'_cons [IsEquiv α Rᶜ] :
208
+ ∀ {l : List α}, (l.destutter' R b).length ≤ ((b :: l).destutter' R a).length
209
+ | [] => by by_cases hab : (R a b) <;> simp_all [Nat.le_succ]
210
+ | c :: cs => by
211
+ by_cases hab : R a b
212
+ case pos => simp [destutter', if_pos hab, Nat.le_succ]
213
+ obtain hac | hac : R a c ∨ Rᶜ a c := em _
214
+ · have hbc : ¬Rᶜ b c := mt (_root_.trans hab) (not_not.2 hac)
215
+ simp [destutter', if_pos hac, if_pos (not_not.1 hbc), if_neg hab]
216
+ · have hbc : ¬R b c := trans (symm hab) hac
217
+ simp only [destutter', if_neg hbc, if_neg hac, if_neg hab]
218
+ exact (length_destutter'_congr cs hab).ge
219
+
220
+ /-- `List.destutter` on a relation like ≠, whose negation is an equivalence, has length
221
+ monotone under List.cons -/
222
+ theorem length_destutter_le_length_destutter_cons [IsEquiv α Rᶜ] :
223
+ ∀ {l : List α}, (l.destutter R).length ≤ ((a :: l).destutter R).length
224
+ | [] => by simp [destutter]
225
+ | b :: l => le_length_destutter'_cons
226
+
227
+ variable {l l₁ l₂}
228
+
229
+ /-- `destutter ≠` has length monotone under `List.cons`. -/
230
+ theorem length_destutter_ne_le_length_destutter_cons [DecidableEq α] :
231
+ (l.destutter (· ≠ ·)).length ≤ ((a :: l).destutter (· ≠ ·)).length :=
232
+ length_destutter_le_length_destutter_cons
233
+
234
+ /-- `destutter` of relations like `≠`, whose negation is an equivalence relation,
235
+ gives a list of maximal length over any chain.
236
+
237
+ In other words, `l.destutter R` is an `R`-chain sublist of `l`, and is at least as long as any other
238
+ `R`-chain sublist. -/
239
+ lemma Chain'.length_le_length_destutter [IsEquiv α Rᶜ] :
240
+ ∀ {l₁ l₂ : List α}, l₁ <+ l₂ → l₁.Chain' R → l₁.length ≤ (l₂.destutter R).length
241
+ -- `l₁ := []`, `l₂ := []`
242
+ | [], [], _, _ => by simp
243
+ -- `l₁ := l₁`, `l₂ := a :: l₂`
244
+ | l₁, _, .cons (l₂ := l₂) a hl, hl₁ =>
245
+ (hl₁.length_le_length_destutter hl).trans length_destutter_le_length_destutter_cons
246
+ -- `l₁ := [a]`, `l₂ := a :: l₂`
247
+ | _, _, .cons₂ (l₁ := []) (l₂ := l₁) a hl, hl₁ => by simp [Nat.one_le_iff_ne_zero]
248
+ -- `l₁ := a :: l₁`, `l₂ := a :: b :: l₂`
249
+ | _, _, .cons₂ a <| .cons (l₁ := l₁) (l₂ := l₂) b hl, hl₁ => by
250
+ by_cases hab : R a b
251
+ · simpa [destutter_cons_cons, hab] using hl₁.tail.length_le_length_destutter (hl.cons _)
252
+ · simpa [destutter_cons_cons, hab] using hl₁.length_le_length_destutter (hl.cons₂ _)
253
+ -- `l₁ := a :: b :: l₁`, `l₂ := a :: b :: l₂`
254
+ | _, _, .cons₂ a <| .cons₂ (l₁ := l₁) (l₂ := l₂) b hl, hl₁ => by
255
+ simpa [destutter_cons_cons, rel_of_chain_cons hl₁]
256
+ using hl₁.tail.length_le_length_destutter (hl.cons₂ _)
257
+
258
+ /-- `destutter` of `≠` gives a list of maximal length over any chain.
259
+
260
+ In other words, `l.destutter (· ≠ ·)` is a `≠`-chain sublist of `l`, and is at least as long as any
261
+ other `≠`-chain sublist. -/
262
+ lemma Chain'.length_le_length_destutter_ne [DecidableEq α] (hl : l₁ <+ l₂)
263
+ (hl₁ : l₁.Chain' (· ≠ ·)) : l₁.length ≤ (l₂.destutter (· ≠ ·)).length :=
264
+ hl₁.length_le_length_destutter hl
265
+
151
266
end List
0 commit comments