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

Commit 13cd3e8

Browse files
committed
feat(combinatorics/simple_graph/connectivity): concat and concat_rec (#17209)
Adds the alternative constructor for walks along with its recursion principle. (Borrowed from lean2/hott.) Co-authored-by: Floris van Doorn <fpvdoorn@gmail.com>
1 parent 5a82b06 commit 13cd3e8

File tree

2 files changed

+133
-3
lines changed

2 files changed

+133
-3
lines changed

src/combinatorics/simple_graph/connectivity.lean

Lines changed: 122 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ def append : Π {u v w : V}, G.walk u v → G.walk v w → G.walk u w
151151
| _ _ _ nil q := q
152152
| _ _ _ (cons h p) q := cons h (p.append q)
153153

154+
/-- The reversed version of `simple_graph.walk.cons`, concatenating an edge to
155+
the end of a walk. -/
156+
def concat {u v w : V} (p : G.walk u v) (h : G.adj v w) : G.walk u w := p.append (cons h nil)
157+
158+
lemma concat_eq_append {u v w : V} (p : G.walk u v) (h : G.adj v w) :
159+
p.concat h = p.append (cons h nil) := rfl
160+
154161
/-- The concatenation of the reverse of the first walk with the second walk. -/
155162
protected def reverse_aux : Π {u v w : V}, G.walk u v → G.walk u w → G.walk v w
156163
| _ _ _ nil q := q
@@ -215,6 +222,35 @@ lemma append_assoc : Π {u v w x : V} (p : G.walk u v) (q : G.walk v w) (r : G.w
215222
(hu : u = u') (hv : v = v') (hw : w = w') :
216223
(p.copy hu hv).append (q.copy hv hw) = (p.append q).copy hu hw := by { subst_vars, refl }
217224

225+
lemma concat_nil {u v : V} (h : G.adj u v) : nil.concat h = cons h nil := rfl
226+
227+
@[simp] lemma concat_cons {u v w x : V} (h : G.adj u v) (p : G.walk v w) (h' : G.adj w x) :
228+
(cons h p).concat h' = cons h (p.concat h') := rfl
229+
230+
lemma append_concat {u v w x : V} (p : G.walk u v) (q : G.walk v w) (h : G.adj w x) :
231+
p.append (q.concat h) = (p.append q).concat h := append_assoc _ _ _
232+
233+
lemma concat_append {u v w x : V} (p : G.walk u v) (h : G.adj v w) (q : G.walk w x) :
234+
(p.concat h).append q = p.append (cons h q) :=
235+
by rw [concat_eq_append, ← append_assoc, cons_nil_append]
236+
237+
/-- A non-trivial `cons` walk is representable as a `concat` walk. -/
238+
lemma exists_cons_eq_concat : Π {u v w : V} (h : G.adj u v) (p : G.walk v w),
239+
∃ (x : V) (q : G.walk u x) (h' : G.adj x w), cons h p = q.concat h'
240+
| _ _ _ h nil := ⟨_, nil, h, rfl⟩
241+
| _ _ _ h (cons h' p) :=
242+
begin
243+
obtain ⟨y, q, h'', hc⟩ := exists_cons_eq_concat h' p,
244+
refine ⟨y, cons h q, h'', _⟩,
245+
rw [concat_cons, hc],
246+
end
247+
248+
/-- A non-trivial `concat` walk is representable as a `cons` walk. -/
249+
lemma exists_concat_eq_cons : Π {u v w : V} (p : G.walk u v) (h : G.adj v w),
250+
∃ (x : V) (h' : G.adj u x) (q : G.walk x w), p.concat h = cons h' q
251+
| _ _ _ nil h := ⟨_, h, nil, rfl⟩
252+
| _ _ _ (cons h' p) h := ⟨_, h', walk.concat p h, concat_cons _ _ _⟩
253+
218254
@[simp] lemma reverse_nil {u : V} : (nil : G.walk u u).reverse = nil := rfl
219255

220256
lemma reverse_singleton {u v : V} (h : G.adj u v) :
@@ -250,6 +286,10 @@ by simp [reverse]
250286
(p.append q).reverse = q.reverse.append p.reverse :=
251287
by simp [reverse]
252288

289+
@[simp] lemma reverse_concat {u v w : V} (p : G.walk u v) (h : G.adj v w) :
290+
(p.concat h).reverse = cons (G.symm h) p.reverse :=
291+
by simp [concat_eq_append]
292+
253293
@[simp] lemma reverse_reverse : Π {u v : V} (p : G.walk u v), p.reverse.reverse = p
254294
| _ _ nil := rfl
255295
| _ _ (cons h p) := by simp [reverse_reverse]
@@ -268,6 +308,9 @@ by { subst_vars, refl }
268308
| _ _ _ nil _ := by simp
269309
| _ _ _ (cons _ _) _ := by simp [length_append, add_left_comm, add_comm]
270310

311+
@[simp] lemma length_concat {u v w : V} (p : G.walk u v) (h : G.adj v w) :
312+
(p.concat h).length = p.length + 1 := length_append _ _
313+
271314
@[simp] protected lemma length_reverse_aux : Π {u v w : V} (p : G.walk u v) (q : G.walk u w),
272315
(p.reverse_aux q).length = p.length + q.length
273316
| _ _ _ nil _ := by simp!
@@ -291,6 +334,76 @@ end
291334
@[simp] lemma length_eq_zero_iff {u : V} {p : G.walk u u} : p.length = 0 ↔ p = nil :=
292335
by cases p; simp
293336

337+
section concat_rec
338+
339+
variables
340+
{motive : Π (u v : V), G.walk u v → Sort*}
341+
(Hnil : Π {u : V}, motive u u nil)
342+
(Hconcat : Π {u v w : V} (p : G.walk u v) (h : G.adj v w), motive u v p → motive u w (p.concat h))
343+
344+
/-- Auxiliary definition for `simple_graph.walk.concat_rec` -/
345+
def concat_rec_aux : Π {u v : V} (p : G.walk u v), motive v u p.reverse
346+
| _ _ nil := Hnil
347+
| _ _ (cons h p) := eq.rec (Hconcat p.reverse (G.symm h) (concat_rec_aux p)) (reverse_cons h p).symm
348+
349+
/-- Recursor on walks by inducting on `simple_graph.walk.concat`.
350+
351+
This is inducting from the opposite end of the walk compared
352+
to `simple_graph.walk.rec`, which inducts on `simple_graph.walk.cons`. -/
353+
@[elab_as_eliminator]
354+
def concat_rec {u v : V} (p : G.walk u v) : motive u v p :=
355+
eq.rec (concat_rec_aux @Hnil @Hconcat p.reverse) (reverse_reverse p)
356+
357+
@[simp] lemma concat_rec_nil (u : V) :
358+
@concat_rec _ _ motive @Hnil @Hconcat _ _ (nil : G.walk u u) = Hnil := rfl
359+
360+
@[simp] lemma concat_rec_concat {u v w : V} (p : G.walk u v) (h : G.adj v w) :
361+
@concat_rec _ _ motive @Hnil @Hconcat _ _ (p.concat h)
362+
= Hconcat p h (concat_rec @Hnil @Hconcat p) :=
363+
begin
364+
simp only [concat_rec],
365+
apply eq_of_heq,
366+
apply rec_heq_of_heq,
367+
transitivity concat_rec_aux @Hnil @Hconcat (cons h.symm p.reverse),
368+
{ congr, simp },
369+
{ rw [concat_rec_aux, rec_heq_iff_heq],
370+
congr; simp [heq_rec_iff_heq], }
371+
end
372+
373+
end concat_rec
374+
375+
lemma concat_ne_nil {u v : V} (p : G.walk u v) (h : G.adj v u) :
376+
p.concat h ≠ nil :=
377+
by cases p; simp [concat]
378+
379+
lemma concat_inj {u v v' w : V}
380+
{p : G.walk u v} {h : G.adj v w} {p' : G.walk u v'} {h' : G.adj v' w}
381+
(he : p.concat h = p'.concat h') :
382+
∃ (hv : v = v'), p.copy rfl hv = p' :=
383+
begin
384+
induction p,
385+
{ cases p',
386+
{ exact ⟨rfl, rfl⟩ },
387+
{ exfalso,
388+
simp only [concat_nil, concat_cons] at he,
389+
obtain ⟨rfl, he⟩ := he,
390+
simp only [heq_iff_eq] at he,
391+
exact concat_ne_nil _ _ he.symm, } },
392+
{ rw concat_cons at he,
393+
cases p',
394+
{ exfalso,
395+
simp only [concat_nil] at he,
396+
obtain ⟨rfl, he⟩ := he,
397+
rw [heq_iff_eq] at he,
398+
exact concat_ne_nil _ _ he, },
399+
{ rw concat_cons at he,
400+
simp only at he,
401+
obtain ⟨rfl, he⟩ := he,
402+
rw [heq_iff_eq] at he,
403+
obtain ⟨rfl, rfl⟩ := p_ih he,
404+
exact ⟨rfl, rfl⟩, } }
405+
end
406+
294407
/-- The `support` of a walk is the list of vertices it visits in order. -/
295408
def support : Π {u v : V}, G.walk u v → list V
296409
| u v nil := [u]
@@ -310,6 +423,9 @@ def edges {u v : V} (p : G.walk u v) : list (sym2 V) := p.darts.map dart.edge
310423
@[simp] lemma support_cons {u v w : V} (h : G.adj u v) (p : G.walk v w) :
311424
(cons h p).support = u :: p.support := rfl
312425

426+
@[simp] lemma support_concat {u v w : V} (p : G.walk u v) (h : G.adj v w) :
427+
(p.concat h).support = p.support.concat w := by induction p; simp [*, concat_nil]
428+
313429
@[simp] lemma support_copy {u v u' v'} (p : G.walk u v) (hu : u = u') (hv : v = v') :
314430
(p.copy hu hv).support = p.support := by { subst_vars, refl }
315431

@@ -427,6 +543,9 @@ edges_subset_edge_set p h
427543
@[simp] lemma darts_cons {u v w : V} (h : G.adj u v) (p : G.walk v w) :
428544
(cons h p).darts = ⟨(u, v), h⟩ :: p.darts := rfl
429545

546+
@[simp] lemma darts_concat {u v w : V} (p : G.walk u v) (h : G.adj v w) :
547+
(p.concat h).darts = p.darts.concat ⟨(v, w), h⟩ := by induction p; simp [*, concat_nil]
548+
430549
@[simp] lemma darts_copy {u v u' v'} (p : G.walk u v) (hu : u = u') (hv : v = v') :
431550
(p.copy hu hv).darts = p.darts := by { subst_vars, refl }
432551

@@ -463,6 +582,9 @@ by simpa! using congr_arg list.init (map_fst_darts_append p)
463582
@[simp] lemma edges_cons {u v w : V} (h : G.adj u v) (p : G.walk v w) :
464583
(cons h p).edges = ⟦(u, v)⟧ :: p.edges := rfl
465584

585+
@[simp] lemma edges_concat {u v w : V} (p : G.walk u v) (h : G.adj v w) :
586+
(p.concat h).edges = p.edges.concat ⟦(v, w)⟧ := by simp [edges]
587+
466588
@[simp] lemma edges_copy {u v u' v'} (p : G.walk u v) (hu : u = u') (hv : v = v') :
467589
(p.copy hu hv).edges = p.edges := by { subst_vars, refl }
468590

src/logic/basic.lean

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -908,9 +908,17 @@ lemma heq_of_cast_eq :
908908
lemma cast_eq_iff_heq {α β : Sort*} {a : α} {a' : β} {e : α = β} : cast e a = a' ↔ a == a' :=
909909
⟨heq_of_cast_eq _, λ h, by cases h; refl⟩
910910

911-
lemma rec_heq_of_heq {β} {C : α → Sort*} {x : C a} {y : β} (eq : a = b) (h : x == y) :
912-
@eq.rec α a C x b eq == y :=
913-
by subst eq; exact h
911+
lemma rec_heq_of_heq {β} {C : α → Sort*} {x : C a} {y : β} (e : a = b) (h : x == y) :
912+
@eq.rec α a C x b e == y :=
913+
by subst e; exact h
914+
915+
lemma rec_heq_iff_heq {β} {C : α → Sort*} {x : C a} {y : β} {e : a = b} :
916+
@eq.rec α a C x b e == y ↔ x == y :=
917+
by subst e
918+
919+
lemma heq_rec_iff_heq {β} {C : α → Sort*} {x : β} {y : C a} {e : a = b} :
920+
x == @eq.rec α a C y b e ↔ x == y :=
921+
by subst e
914922

915923
protected lemma eq.congr {x₁ x₂ y₁ y₂ : α} (h₁ : x₁ = y₁) (h₂ : x₂ = y₂) :
916924
(x₁ = x₂) ↔ (y₁ = y₂) :=

0 commit comments

Comments
 (0)