Skip to content

Commit ea49cde

Browse files
committed
feat(SimpleGraph/Walk): add missing results involving getVert / takeUntil (#29601)
Add some missing lemmas involving `getVert` / `takeUntil`. In particular `getVert_le_length_takeUntil_eq_iff` which says that if `p` is a walk containing the vertex `u` then `n = (p.takeUntil u h).length` is the smallest `n` such that `p.getVert n = u`. Co-authored-by: jt496 <john.talbot@gmail.com>
1 parent 1e81efc commit ea49cde

File tree

2 files changed

+47
-61
lines changed

2 files changed

+47
-61
lines changed

Mathlib/Combinatorics/SimpleGraph/Connectivity/WalkDecomp.lean

Lines changed: 40 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -187,21 +187,23 @@ theorem length_dropUntil_le {u v w : V} (p : G.Walk v w) (h : u ∈ p.support) :
187187
rw [length_append, add_comm] at this
188188
exact Nat.le.intro this
189189

190+
lemma takeUntil_append_of_mem_left {x : V} (p : G.Walk u v) (q : G.Walk v w) (hx : x ∈ p.support) :
191+
(p.append q).takeUntil x (subset_support_append_left _ _ hx) = p.takeUntil _ hx := by
192+
induction p with
193+
| nil => rw [mem_support_nil_iff] at hx; subst_vars; simp
194+
| @cons u _ _ _ _ ih =>
195+
rw [support_cons] at hx
196+
by_cases hxu : u = x
197+
· subst_vars; simp
198+
· have := List.mem_of_ne_of_mem (fun hf ↦ hxu hf.symm) hx
199+
simp_rw [takeUntil_cons this hxu, cons_append,
200+
takeUntil_cons (subset_support_append_left _ _ this) hxu]
201+
simpa using ih _ this
202+
190203
lemma getVert_takeUntil {u v : V} {n : ℕ} {p : G.Walk u v} (hw : w ∈ p.support)
191204
(hn : n ≤ (p.takeUntil w hw).length) : (p.takeUntil w hw).getVert n = p.getVert n := by
192-
cases p with
193-
| nil => simp only [support_nil, List.mem_singleton] at hw; aesop
194-
| cons h q =>
195-
by_cases huw : w = u
196-
· subst huw
197-
simp_all
198-
simp only [support_cons, List.mem_cons, huw, false_or] at hw
199-
by_cases hn0 : n = 0
200-
· simp_all
201-
simp only [takeUntil_cons hw ((Ne.eq_def _ _).mpr huw).symm, length_cons,
202-
getVert_cons _ _ hn0] at hn ⊢
203-
apply q.getVert_takeUntil hw
204-
omega
205+
conv_rhs => rw [← take_spec p hw, getVert_append]
206+
cases hn.lt_or_eq <;> simp_all
205207

206208
lemma snd_takeUntil (hsu : w ≠ u) (p : G.Walk u v) (h : w ∈ p.support) :
207209
(p.takeUntil w h).snd = p.snd := by
@@ -210,6 +212,25 @@ lemma snd_takeUntil (hsu : w ≠ u) (p : G.Walk u v) (h : w ∈ p.support) :
210212
simp only [Nat.lt_one_iff, ← nil_iff_length_eq, nil_takeUntil] at hc
211213
exact hsu hc.symm
212214

215+
lemma getVert_length_takeUntil {p : G.Walk v w} (h : u ∈ p.support) :
216+
p.getVert (p.takeUntil _ h).length = u := by
217+
have := congr_arg₂ (y := (p.takeUntil _ h).length) getVert (p.take_spec h) rfl
218+
grind [getVert_append, getVert_zero]
219+
220+
lemma getVert_lt_length_takeUntil_ne {n : ℕ} {p : G.Walk v w} (h : u ∈ p.support)
221+
(hn : n < (p.takeUntil _ h).length) : p.getVert n ≠ u := by
222+
rintro rfl
223+
have h₁ : n < (p.takeUntil _ h).support.dropLast.length := by simpa
224+
have : p.getVert n ∈ (p.takeUntil _ h).support.dropLast := by
225+
simp_rw [p.getVert_takeUntil h hn.le ▸ getVert_eq_support_getElem _ hn.le,
226+
← List.getElem_dropLast h₁, List.getElem_mem h₁]
227+
have := support_eq_concat _ ▸ p.count_support_takeUntil_eq_one h
228+
grind [List.not_mem_of_count_eq_zero]
229+
230+
theorem getVert_le_length_takeUntil_eq_iff {n : ℕ} {p : G.Walk v w} (h : u ∈ p.support)
231+
(hn : n ≤ (p.takeUntil _ h).length) : p.getVert n = u ↔ n = (p.takeUntil _ h).length := by
232+
grind [getVert_length_takeUntil, getVert_lt_length_takeUntil_ne]
233+
213234
lemma length_takeUntil_lt {u v w : V} {p : G.Walk v w} (h : u ∈ p.support) (huw : u ≠ w) :
214235
(p.takeUntil u h).length < p.length := by
215236
rw [(p.length_takeUntil_le h).lt_iff_ne]
@@ -219,29 +240,7 @@ lemma length_takeUntil_lt {u v w : V} {p : G.Walk v w} (h : u ∈ p.support) (hu
219240
lemma takeUntil_takeUntil {w x : V} (p : G.Walk u v) (hw : w ∈ p.support)
220241
(hx : x ∈ (p.takeUntil w hw).support) :
221242
(p.takeUntil w hw).takeUntil x hx = p.takeUntil x (p.support_takeUntil_subset hw hx) := by
222-
induction p, w, hw using takeUntil.induct with
223-
| case1 u v h =>
224-
#adaptation_note
225-
/-- Prior to `nightly-2025-02-24` this was just `aesop`. -/
226-
simp at h
227-
subst h
228-
simp
229-
| case2 _ _ q _ hadj hu' =>
230-
simp only [takeUntil_first, support_nil, List.mem_singleton] at hx
231-
subst hx
232-
simp
233-
| case3 a w' v' hadj q u' hu' hau' ih =>
234-
rw [← Ne.eq_def] at hau'
235-
simp only [support_cons, List.mem_cons, hau'.symm, false_or] at hu'
236-
simp only [takeUntil_cons hu' hau' hadj, support_cons, List.mem_cons] at hx
237-
by_cases hx' : x = a
238-
· aesop
239-
· replace hx : x ∈ (q.takeUntil u' hu').support := by simpa [hx'] using hx
240-
push_neg at hx'
241-
conv_lhs =>
242-
enter [1]
243-
rw [takeUntil_cons hu' hau' hadj]
244-
rw [takeUntil_cons hx hx'.symm hadj, ih _, takeUntil_cons _ hx'.symm]
243+
simp_rw [← takeUntil_append_of_mem_left _ (p.dropUntil w hw) hx, take_spec]
245244

246245
lemma notMem_support_takeUntil_support_takeUntil_subset {p : G.Walk u v} {w x : V} (h : x ≠ w)
247246
(hw : w ∈ p.support) (hx : x ∈ (p.takeUntil w hw).support) :
@@ -283,35 +282,15 @@ theorem rotate_edges {u v : V} (c : G.Walk v v) (h : u ∈ c.support) :
283282

284283
end WalkDecomp
285284

286-
/-- Given a walk `w` and a node in the support, there exists a natural `n`, such that given node
287-
is the `n`-th node (zero-indexed) in the walk. In addition, `n` is at most the length of the path.
285+
/-- Given a walk `p` and a node in the support, there exists a natural `n`, such that given node
286+
is the `n`-th node (zero-indexed) in the walk. In addition, `n` is at most the length of the walk.
288287
Due to the definition of `getVert` it would otherwise be legal to return a larger `n` for the last
289288
node. -/
290289
theorem mem_support_iff_exists_getVert {u v w : V} {p : G.Walk v w} :
291290
u ∈ p.support ↔ ∃ n, p.getVert n = u ∧ n ≤ p.length := by
292291
classical
293-
constructor
294-
· intro h
295-
obtain ⟨q, r, hqr⟩ := SimpleGraph.Walk.mem_support_iff_exists_append.mp h
296-
use q.length
297-
rw [hqr, Walk.getVert_append]
298-
simp only [lt_self_iff_false, ↓reduceIte, Nat.sub_self, getVert_zero, length_append,
299-
Nat.le_add_right, and_self]
300-
· rintro ⟨n, hn⟩
301-
rw [mem_support_iff]
302-
cases n with
303-
| zero => aesop
304-
| succ n =>
305-
right
306-
have hnp : ¬ p.Nil := by
307-
rw [nil_iff_length_eq]
308-
omega
309-
rw [← support_tail_of_not_nil _ hnp, mem_support_iff_exists_getVert]
310-
use n
311-
rwa [getVert_tail, ← Nat.add_one_le_add_one_iff, length_tail_add_one hnp]
312-
termination_by p.length
313-
decreasing_by
314-
· simp_wf
315-
rw [Nat.lt_iff_add_one_le, length_tail_add_one hnp]
292+
exact Iff.intro
293+
(fun h ↦ ⟨_, p.getVert_length_takeUntil h, p.length_takeUntil_le h⟩)
294+
(fun ⟨_, h, _⟩ ↦ h ▸ getVert_mem_support _ _)
316295

317296
end SimpleGraph.Walk

Mathlib/Combinatorics/SimpleGraph/Walk.lean

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,13 @@ theorem tail_support_append {u v w : V} (p : G.Walk u v) (p' : G.Walk v w) :
525525
theorem support_eq_cons {u v : V} (p : G.Walk u v) : p.support = u :: p.support.tail := by
526526
cases p <;> simp
527527

528+
theorem support_eq_concat {u v : V} (p : G.Walk u v) : p.support = p.support.dropLast.concat v := by
529+
cases p with
530+
| nil => rfl
531+
| cons h p =>
532+
obtain ⟨_, _, _, hq⟩ := exists_cons_eq_concat h p
533+
simp [hq]
534+
528535
@[simp]
529536
theorem start_mem_support {u v : V} (p : G.Walk u v) : u ∈ p.support := by cases p <;> simp
530537

0 commit comments

Comments
 (0)