@@ -58,7 +58,7 @@ variable (G : SimpleGraph V) (G' : SimpleGraph V')
5858
5959namespace Walk
6060
61- variable {G} {u v w : V}
61+ variable {G} {u u' v w : V}
6262
6363/-! ### Trails, paths, circuits, cycles -/
6464
@@ -136,9 +136,14 @@ theorem IsTrail.of_cons {u v w : V} {h : G.Adj u v} {p : G.Walk v w} :
136136 (cons h p).IsTrail → p.IsTrail := by simp [isTrail_def]
137137
138138@[simp]
139- theorem cons_isTrail_iff {u v w : V} (h : G.Adj u v) (p : G.Walk v w) :
139+ theorem isTrail_cons {u v w : V} (h : G.Adj u v) (p : G.Walk v w) :
140140 (cons h p).IsTrail ↔ p.IsTrail ∧ s(u, v) ∉ p.edges := by simp [isTrail_def, and_comm]
141141
142+ @[deprecated (since := "2025-11-03")] alias cons_isTrail_iff := isTrail_cons
143+
144+ protected lemma IsTrail.cons {w : G.Walk u' v} (hw : w.IsTrail) (hu : G.Adj u u')
145+ (hu' : s(u, u') ∉ w.edges) : (w.cons hu).IsTrail := by simp [*]
146+
142147theorem IsTrail.reverse {u v : V} (p : G.Walk u v) (h : p.IsTrail) : p.reverse.IsTrail := by
143148 simpa [isTrail_def] using h
144149
@@ -581,7 +586,7 @@ theorem notMem_edges_of_loop {v : V} {e : Sym2 V} {p : G.Path v v} :
581586
582587theorem cons_isCycle {u v : V} (p : G.Path v u) (h : G.Adj u v)
583588 (he : s(u, v) ∉ (p : G.Walk v u).edges) : (Walk.cons h ↑p).IsCycle := by
584- simp [Walk.isCycle_def, Walk.cons_isTrail_iff , he]
589+ simp [Walk.isCycle_def, Walk.isTrail_cons , he]
585590
586591end Path
587592
@@ -590,7 +595,7 @@ end Path
590595
591596namespace Walk
592597
593- variable {G} [DecidableEq V]
598+ variable {G} [DecidableEq V] {u u' v v' : V}
594599
595600/-- Given a walk, produces a walk from it by bypassing subwalks between repeated vertices.
596601The result is a path, as shown in `SimpleGraph.Walk.bypass_isPath`.
@@ -605,12 +610,12 @@ def bypass {u v : V} : G.Walk u v → G.Walk u v
605610 cons ha p'
606611
607612@[simp]
608- theorem bypass_copy {u v u' v'} (p : G.Walk u v) (hu : u = u') (hv : v = v') :
613+ theorem bypass_copy (p : G.Walk u v) (hu : u = u') (hv : v = v') :
609614 (p.copy hu hv).bypass = p.bypass.copy hu hv := by
610615 subst_vars
611616 rfl
612617
613- theorem bypass_isPath {u v : V} (p : G.Walk u v) : p.bypass.IsPath := by
618+ theorem bypass_isPath (p : G.Walk u v) : p.bypass.IsPath := by
614619 induction p with
615620 | nil => simp!
616621 | cons _ p' ih =>
@@ -619,7 +624,7 @@ theorem bypass_isPath {u v : V} (p : G.Walk u v) : p.bypass.IsPath := by
619624 · exact ih.dropUntil hs
620625 · simp [*, cons_isPath_iff]
621626
622- theorem length_bypass_le {u v : V} (p : G.Walk u v) : p.bypass.length ≤ p.length := by
627+ theorem length_bypass_le (p : G.Walk u v) : p.bypass.length ≤ p.length := by
623628 induction p with
624629 | nil => rfl
625630 | cons _ _ ih =>
@@ -632,7 +637,7 @@ theorem length_bypass_le {u v : V} (p : G.Walk u v) : p.bypass.length ≤ p.leng
632637 · rw [length_cons, length_cons]
633638 exact Nat.add_le_add_right ih 1
634639
635- lemma bypass_eq_self_of_length_le {u v : V} (p : G.Walk u v) (h : p.length ≤ p.bypass.length) :
640+ lemma bypass_eq_self_of_length_le (p : G.Walk u v) (h : p.length ≤ p.bypass.length) :
636641 p.bypass = p := by
637642 induction p with
638643 | nil => rfl
@@ -651,10 +656,10 @@ lemma bypass_eq_self_of_length_le {u v : V} (p : G.Walk u v) (h : p.length ≤ p
651656 rw [ih h]
652657
653658/-- Given a walk, produces a path with the same endpoints using `SimpleGraph.Walk.bypass`. -/
654- def toPath {u v : V} (p : G.Walk u v) : G.Path u v :=
659+ def toPath (p : G.Walk u v) : G.Path u v :=
655660 ⟨p.bypass, p.bypass_isPath⟩
656661
657- theorem support_bypass_subset {u v : V} (p : G.Walk u v) : p.bypass.support ⊆ p.support := by
662+ theorem support_bypass_subset (p : G.Walk u v) : p.bypass.support ⊆ p.support := by
658663 induction p with
659664 | nil => simp!
660665 | cons _ _ ih =>
@@ -667,11 +672,11 @@ theorem support_bypass_subset {u v : V} (p : G.Walk u v) : p.bypass.support ⊆
667672 apply List.cons_subset_cons
668673 assumption
669674
670- theorem support_toPath_subset {u v : V} (p : G.Walk u v) :
675+ theorem support_toPath_subset (p : G.Walk u v) :
671676 (p.toPath : G.Walk u v).support ⊆ p.support :=
672677 support_bypass_subset _
673678
674- theorem darts_bypass_subset {u v : V} (p : G.Walk u v) : p.bypass.darts ⊆ p.darts := by
679+ theorem darts_bypass_subset (p : G.Walk u v) : p.bypass.darts ⊆ p.darts := by
675680 induction p with
676681 | nil => simp!
677682 | cons _ _ ih =>
@@ -682,15 +687,41 @@ theorem darts_bypass_subset {u v : V} (p : G.Walk u v) : p.bypass.darts ⊆ p.da
682687 · rw [darts_cons]
683688 exact List.cons_subset_cons _ ih
684689
685- theorem edges_bypass_subset {u v : V} (p : G.Walk u v) : p.bypass.edges ⊆ p.edges :=
690+ theorem edges_bypass_subset (p : G.Walk u v) : p.bypass.edges ⊆ p.edges :=
686691 List.map_subset _ p.darts_bypass_subset
687692
688- theorem darts_toPath_subset {u v : V} (p : G.Walk u v) : (p.toPath : G.Walk u v).darts ⊆ p.darts :=
693+ theorem darts_toPath_subset (p : G.Walk u v) : (p.toPath : G.Walk u v).darts ⊆ p.darts :=
689694 darts_bypass_subset _
690695
691- theorem edges_toPath_subset {u v : V} (p : G.Walk u v) : (p.toPath : G.Walk u v).edges ⊆ p.edges :=
696+ theorem edges_toPath_subset (p : G.Walk u v) : (p.toPath : G.Walk u v).edges ⊆ p.edges :=
692697 edges_bypass_subset _
693698
699+ /-- Bypass repeated vertices like `Walk.bypass`, except the starting vertex.
700+
701+ This is intended to be used for closed walks, for which `Walk.bypass` unhelpfully returns the empty
702+ walk. -/
703+ def cycleBypass : G.Walk v v → G.Walk v v
704+ | .nil => .nil
705+ | .cons hvv' w => .cons hvv' w.bypass
706+
707+ @[simp] lemma cycleBypass_nil : (.nil : G.Walk v v).cycleBypass = .nil := rfl
708+
709+ lemma edges_cycleBypass_subset : ∀ {w : G.Walk v v}, w.cycleBypass.edges ⊆ w.edges
710+ | .nil => by simp
711+ | .cons (v := v') hvv' w => by
712+ classical
713+ dsimp only [cycleBypass, edges_cons]
714+ gcongr
715+ exact edges_bypass_subset _
716+
717+ lemma IsTrail.isCycle_cycleBypass : ∀ {w : G.Walk v v}, w ≠ .nil → w.IsTrail → w.cycleBypass.IsCycle
718+ | .cons (v := v') hvv' w, _, hw => by
719+ dsimp [cycleBypass]
720+ refine ⟨⟨(bypass_isPath _).isTrail.cons _ fun hvv' ↦ ?_, by simp⟩, ?_⟩
721+ · simp only [isTrail_cons] at hw
722+ exact hw.2 <| edges_bypass_subset _ hvv'
723+ · simpa using (bypass_isPath _).support_nodup
724+
694725end Walk
695726
696727/-! ### Mapping paths -/
@@ -726,7 +757,7 @@ theorem map_isTrail_iff_of_injective (hinj : Function.Injective f) :
726757 induction p with
727758 | nil => simp
728759 | cons _ _ ih =>
729- rw [map_cons, cons_isTrail_iff , ih, cons_isTrail_iff ]
760+ rw [map_cons, isTrail_cons , ih, isTrail_cons ]
730761 apply and_congr_right'
731762 rw [← Sym2.map_pair_eq, edges_map, ← List.mem_map_of_injective (Sym2.map.injective hinj)]
732763
0 commit comments