Skip to content

Commit 896a59b

Browse files
committed
feat(Combinatorics/SimpleGraph): the reverse of a cycle is a cycle (#19611)
Added the result that a reverse cycle is a cycle. Includes supporting lemmas concerning lists. In preparation for Tutte's theorem. Co-authored-by: Pim Otte <otte.pim@gmail.com>
1 parent afdc9d9 commit 896a59b

File tree

4 files changed

+55
-0
lines changed

4 files changed

+55
-0
lines changed

Mathlib/Combinatorics/SimpleGraph/Path.lean

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,15 @@ theorem cons_isCycle_iff {u v : V} (p : G.Walk v u) (h : G.Adj u v) :
249249
have : p.support.Nodup → p.edges.Nodup := edges_nodup_of_support_nodup
250250
tauto
251251

252+
protected lemma IsCycle.reverse {p : G.Walk u u} (h : p.IsCycle) : p.reverse.IsCycle := by
253+
simp only [Walk.isCycle_def, nodup_tail_support_reverse] at h ⊢
254+
exact ⟨h.1.reverse, fun h' ↦ h.2.1 (by simp_all [← Walk.length_eq_zero_iff]), h.2.2
255+
256+
@[simp]
257+
lemma isCycle_reverse {p : G.Walk u u} : p.reverse.IsCycle ↔ p.IsCycle where
258+
mp h := by simpa using h.reverse
259+
mpr := .reverse
260+
252261
lemma IsPath.tail {p : G.Walk u v} (hp : p.IsPath) (hp' : ¬ p.Nil) : p.tail.IsPath := by
253262
rw [Walk.isPath_def] at hp ⊢
254263
rw [← cons_support_tail _ hp', List.nodup_cons] at hp

Mathlib/Combinatorics/SimpleGraph/Walk.lean

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -557,6 +557,20 @@ theorem subset_support_append_right {V : Type u} {G : SimpleGraph V} {u v w : V}
557557
intro h
558558
simp +contextual only [mem_support_append_iff, or_true, imp_true_iff]
559559

560+
lemma getVert_eq_support_get? {u v n} (p : G.Walk u v) (h2 : n ≤ p.length) :
561+
p.getVert n = p.support[n]? := by
562+
match p with
563+
| .nil => simp_all
564+
| .cons h q =>
565+
simp only [Walk.support_cons]
566+
by_cases hn : n = 0
567+
· simp only [hn, getVert_zero, List.length_cons, Nat.zero_lt_succ, List.getElem?_eq_getElem,
568+
List.getElem_cons_zero]
569+
· push_neg at hn
570+
nth_rewrite 2 [show n = (n - 1) + 1 from by omega]
571+
rw [Walk.getVert_cons q h hn, List.getElem?_cons_succ]
572+
exact getVert_eq_support_get? q (Nat.sub_le_of_le_add (Walk.length_cons _ _ ▸ h2))
573+
560574
theorem coe_support {u v : V} (p : G.Walk u v) :
561575
(p.support : Multiset V) = {u} + p.support.tail := by cases p <;> rfl
562576

@@ -739,6 +753,14 @@ theorem edges_nodup_of_support_nodup {u v : V} {p : G.Walk u v} (h : p.support.N
739753
simp only [edges_cons, support_cons, List.nodup_cons] at h ⊢
740754
exact ⟨fun h' => h.1 (fst_mem_support_of_mem_edges p' h'), ih h.2
741755

756+
theorem nodup_tail_support_reverse {u : V} {p : G.Walk u u} :
757+
p.reverse.support.tail.Nodup ↔ p.support.tail.Nodup := by
758+
rw [Walk.support_reverse]
759+
refine List.nodup_tail_reverse p.support ?h
760+
rw [← getVert_eq_support_get? _ (by omega), List.getLast?_eq_getElem?,
761+
← getVert_eq_support_get? _ (by rw [Walk.length_support]; omega)]
762+
aesop
763+
742764
theorem edges_injective {u v : V} : Function.Injective (Walk.edges : G.Walk u v → List (Sym2 V))
743765
| .nil, .nil, _ => rfl
744766
| .nil, .cons _ _, h => by simp at h

Mathlib/Data/List/Basic.lean

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,15 @@ theorem cons_get_drop_succ {l : List α} {n} :
10321032
l.get n :: l.drop (n.1 + 1) = l.drop n.1 :=
10331033
(drop_eq_getElem_cons n.2).symm
10341034

1035+
lemma drop_length_sub_one {l : List α} (h : l ≠ []) : l.drop (l.length - 1) = [l.getLast h] := by
1036+
induction l with
1037+
| nil => aesop
1038+
| cons a l ih =>
1039+
by_cases hl : l = []
1040+
· aesop
1041+
rw [length_cons, Nat.add_one_sub_one, List.drop_length_cons hl a]
1042+
aesop
1043+
10351044
section TakeI
10361045

10371046
variable [Inhabited α]

Mathlib/Data/List/Nodup.lean

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,21 @@ theorem Nodup.filter (p : α → Bool) {l} : Nodup l → Nodup (filter p l) := b
227227
theorem nodup_reverse {l : List α} : Nodup (reverse l) ↔ Nodup l :=
228228
pairwise_reverse.trans <| by simp only [Nodup, Ne, eq_comm]
229229

230+
lemma nodup_tail_reverse (l : List α) (h : l[0]? = l.getLast?) :
231+
Nodup l.reverse.tail ↔ Nodup l.tail := by
232+
induction l with
233+
| nil => simp
234+
| cons a l ih =>
235+
by_cases hl : l = []
236+
· aesop
237+
· simp_all only [List.get?_eq_getElem?, List.tail_reverse, List.nodup_reverse,
238+
List.dropLast_cons_of_ne_nil hl, List.tail_cons]
239+
simp only [length_cons, Nat.zero_lt_succ, getElem?_eq_getElem, getElem_cons_zero,
240+
Nat.add_one_sub_one, Nat.lt_add_one, Option.some.injEq, List.getElem_cons,
241+
show l.length ≠ 0 from by aesop, ↓reduceDIte, getLast?_eq_getElem?] at h
242+
rw [h, show l.Nodup = (l.dropLast ++ [l.getLast hl]).Nodup from by
243+
simp [List.dropLast_eq_take, ← List.drop_length_sub_one], List.nodup_append_comm]
244+
simp [List.getLast_eq_getElem]
230245

231246
theorem Nodup.erase_getElem [DecidableEq α] {l : List α} (hl : l.Nodup)
232247
(i : Nat) (h : i < l.length) : l.erase l[i] = l.eraseIdx ↑i := by

0 commit comments

Comments
 (0)