@@ -556,6 +556,7 @@ theorem support_reverse {u v : V} (p : G.Walk u v) : p.reverse.support = p.suppo
556
556
induction p <;> simp [support_append, *]
557
557
#align simple_graph.walk.support_reverse SimpleGraph.Walk.support_reverse
558
558
559
+ @[simp]
559
560
theorem support_ne_nil {u v : V} (p : G.Walk u v) : p.support ≠ [] := by cases p <;> simp
560
561
#align simple_graph.walk.support_ne_nil SimpleGraph.Walk.support_ne_nil
561
562
@@ -825,6 +826,81 @@ theorem edges_nodup_of_support_nodup {u v : V} {p : G.Walk u v} (h : p.support.N
825
826
exact ⟨fun h' => h.1 (fst_mem_support_of_mem_edges p' h'), ih h.2 ⟩
826
827
#align simple_graph.walk.edges_nodup_of_support_nodup SimpleGraph.Walk.edges_nodup_of_support_nodup
827
828
829
+ /-- Predicate for the empty walk.
830
+
831
+ Solves the dependent type problem where `p = G.Walk.nil` typechecks
832
+ only if `p` has defeq endpoints. -/
833
+ inductive Nil : {v w : V} → G.Walk v w → Prop
834
+ | nil {u : V} : Nil (nil : G.Walk u u)
835
+
836
+ @[simp] lemma nil_nil : (nil : G.Walk u u).Nil := Nil.nil
837
+
838
+ @[simp] lemma not_nil_cons {h : G.Adj u v} {p : G.Walk v w} : ¬ (cons h p).Nil := fun.
839
+
840
+ instance (p : G.Walk v w) : Decidable p.Nil :=
841
+ match p with
842
+ | nil => isTrue .nil
843
+ | cons _ _ => isFalse fun.
844
+
845
+ protected lemma Nil.eq {p : G.Walk v w} : p.Nil → v = w | .nil => rfl
846
+
847
+ lemma not_nil_of_ne {p : G.Walk v w} : v ≠ w → ¬ p.Nil := mt Nil.eq
848
+
849
+ lemma nil_iff_support_eq {p : G.Walk v w} : p.Nil ↔ p.support = [v] := by
850
+ cases p <;> simp
851
+
852
+ lemma nil_iff_length_eq {p : G.Walk v w} : p.Nil ↔ p.length = 0 := by
853
+ cases p <;> simp
854
+
855
+ lemma not_nil_iff {p : G.Walk v w} :
856
+ ¬ p.Nil ↔ ∃ (u : V) (h : G.Adj v u) (q : G.Walk u w), p = cons h q := by
857
+ cases p <;> simp [*]
858
+
859
+ @[elab_as_elim]
860
+ def notNilRec {motive : {u w : V} → (p : G.Walk u w) → (h : ¬ p.Nil) → Sort _}
861
+ (cons : {u v w : V} → (h : G.Adj u v) → (q : G.Walk v w) → motive (cons h q) not_nil_cons)
862
+ (p : G.Walk u w) : (hp : ¬ p.Nil) → motive p hp :=
863
+ match p with
864
+ | nil => fun hp => absurd .nil hp
865
+ | .cons h q => fun _ => cons h q
866
+
867
+ /-- The second vertex along a non-nil walk. -/
868
+ def sndOfNotNil (p : G.Walk v w) (hp : ¬ p.Nil) : V :=
869
+ p.notNilRec (@fun _ u _ _ _ => u) hp
870
+
871
+ @[simp] lemma adj_sndOfNotNil {p : G.Walk v w} (hp : ¬ p.Nil) :
872
+ G.Adj v (p.sndOfNotNil hp) :=
873
+ p.notNilRec (fun h _ => h) hp
874
+
875
+ /-- The walk obtained by removing the first dart of a non-nil walk. -/
876
+ def tail (p : G.Walk x y) (hp : ¬ p.Nil) : G.Walk (p.sndOfNotNil hp) y :=
877
+ p.notNilRec (fun _ q => q) hp
878
+
879
+ /-- The first dart of a walk. -/
880
+ @[simps]
881
+ def firstDart (p : G.Walk v w) (hp : ¬ p.Nil) : G.Dart where
882
+ fst := v
883
+ snd := p.sndOfNotNil hp
884
+ is_adj := p.adj_sndOfNotNil hp
885
+
886
+ lemma edge_firstDart (p : G.Walk v w) (hp : ¬ p.Nil) :
887
+ (p.firstDart hp).edge = ⟦(v, p.sndOfNotNil hp)⟧ := rfl
888
+
889
+ @[simp] lemma cons_tail_eq (p : G.Walk x y) (hp : ¬ p.Nil) :
890
+ cons (p.adj_sndOfNotNil hp) (p.tail hp) = p :=
891
+ p.notNilRec (fun _ _ => rfl) hp
892
+
893
+ @[simp] lemma cons_support_tail (p : G.Walk x y) (hp : ¬ p.Nil) :
894
+ x :: (p.tail hp).support = p.support := by
895
+ rw [← support_cons, cons_tail_eq]
896
+
897
+ @[simp] lemma length_tail_add_one {p : G.Walk x y} (hp : ¬ p.Nil) :
898
+ (p.tail hp).length + 1 = p.length := by
899
+ rw [← length_cons, cons_tail_eq]
900
+
901
+ @[simp] lemma nil_copy {p : G.Walk x y} (hx : x = x') (hy : y = y') :
902
+ (p.copy hx hy).Nil = p.Nil := by
903
+ subst_vars; rfl
828
904
829
905
/-! ### Trails, paths, circuits, cycles -/
830
906
@@ -972,6 +1048,10 @@ theorem cons_isPath_iff {u v w : V} (h : G.Adj u v) (p : G.Walk v w) :
972
1048
constructor <;> simp (config := { contextual := true }) [isPath_def]
973
1049
#align simple_graph.walk.cons_is_path_iff SimpleGraph.Walk.cons_isPath_iff
974
1050
1051
+ protected lemma IsPath.cons (hp : p.IsPath) (hu : u ∉ p.support) {h : G.Adj u v} :
1052
+ (cons h p).IsPath :=
1053
+ (cons_isPath_iff _ _).2 ⟨hp, hu⟩
1054
+
975
1055
@[simp]
976
1056
theorem isPath_iff_eq_nil {u : V} (p : G.Walk u u) : p.IsPath ↔ p = nil := by
977
1057
cases p <;> simp [IsPath.nil]
@@ -1011,6 +1091,10 @@ theorem cons_isCycle_iff {u v : V} (p : G.Walk v u) (h : G.Adj u v) :
1011
1091
tauto
1012
1092
#align simple_graph.walk.cons_is_cycle_iff SimpleGraph.Walk.cons_isCycle_iff
1013
1093
1094
+ lemma IsPath.tail {p : G.Walk u v} (hp : p.IsPath) (hp' : ¬ p.Nil) : (p.tail hp').IsPath := by
1095
+ rw [Walk.isPath_def] at hp ⊢
1096
+ rw [← cons_support_tail _ hp', List.nodup_cons] at hp
1097
+ exact hp.2
1014
1098
1015
1099
/-! ### About paths -/
1016
1100
0 commit comments