@@ -151,6 +151,13 @@ def append : Π {u v w : V}, G.walk u v → G.walk v w → G.walk u w
151
151
| _ _ _ nil q := q
152
152
| _ _ _ (cons h p) q := cons h (p.append q)
153
153
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
+
154
161
/-- The concatenation of the reverse of the first walk with the second walk. -/
155
162
protected def reverse_aux : Π {u v w : V}, G.walk u v → G.walk u w → G.walk v w
156
163
| _ _ _ 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
215
222
(hu : u = u') (hv : v = v') (hw : w = w') :
216
223
(p.copy hu hv).append (q.copy hv hw) = (p.append q).copy hu hw := by { subst_vars, refl }
217
224
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
+
218
254
@[simp] lemma reverse_nil {u : V} : (nil : G.walk u u).reverse = nil := rfl
219
255
220
256
lemma reverse_singleton {u v : V} (h : G.adj u v) :
@@ -250,6 +286,10 @@ by simp [reverse]
250
286
(p.append q).reverse = q.reverse.append p.reverse :=
251
287
by simp [reverse]
252
288
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
+
253
293
@[simp] lemma reverse_reverse : Π {u v : V} (p : G.walk u v), p.reverse.reverse = p
254
294
| _ _ nil := rfl
255
295
| _ _ (cons h p) := by simp [reverse_reverse]
@@ -268,6 +308,9 @@ by { subst_vars, refl }
268
308
| _ _ _ nil _ := by simp
269
309
| _ _ _ (cons _ _) _ := by simp [length_append, add_left_comm, add_comm]
270
310
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
+
271
314
@[simp] protected lemma length_reverse_aux : Π {u v w : V} (p : G.walk u v) (q : G.walk u w),
272
315
(p.reverse_aux q).length = p.length + q.length
273
316
| _ _ _ nil _ := by simp!
291
334
@[simp] lemma length_eq_zero_iff {u : V} {p : G.walk u u} : p.length = 0 ↔ p = nil :=
292
335
by cases p; simp
293
336
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
+
294
407
/-- The `support` of a walk is the list of vertices it visits in order. -/
295
408
def support : Π {u v : V}, G.walk u v → list V
296
409
| 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
310
423
@[simp] lemma support_cons {u v w : V} (h : G.adj u v) (p : G.walk v w) :
311
424
(cons h p).support = u :: p.support := rfl
312
425
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
+
313
429
@[simp] lemma support_copy {u v u' v'} (p : G.walk u v) (hu : u = u') (hv : v = v') :
314
430
(p.copy hu hv).support = p.support := by { subst_vars, refl }
315
431
@@ -427,6 +543,9 @@ edges_subset_edge_set p h
427
543
@[simp] lemma darts_cons {u v w : V} (h : G.adj u v) (p : G.walk v w) :
428
544
(cons h p).darts = ⟨(u, v), h⟩ :: p.darts := rfl
429
545
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
+
430
549
@[simp] lemma darts_copy {u v u' v'} (p : G.walk u v) (hu : u = u') (hv : v = v') :
431
550
(p.copy hu hv).darts = p.darts := by { subst_vars, refl }
432
551
@@ -463,6 +582,9 @@ by simpa! using congr_arg list.init (map_fst_darts_append p)
463
582
@[simp] lemma edges_cons {u v w : V} (h : G.adj u v) (p : G.walk v w) :
464
583
(cons h p).edges = ⟦(u, v)⟧ :: p.edges := rfl
465
584
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
+
466
588
@[simp] lemma edges_copy {u v u' v'} (p : G.walk u v) (hu : u = u') (hv : v = v') :
467
589
(p.copy hu hv).edges = p.edges := by { subst_vars, refl }
468
590
0 commit comments