@@ -95,17 +95,44 @@ inductive path {V} (G : quiver.{v u} V) (a : V) : V → Sort (max (u+1) v)
95
95
| nil : path a
96
96
| cons : Π {b c : V}, path b → G.arrow b c → path c
97
97
98
+ /-- An arrow viewed as a path of length one. -/
99
+ def arrow.to_path {V} {G : quiver V} {a b} (e : G.arrow a b) : G.path a b :=
100
+ path.nil.cons e
101
+
102
+ namespace path
103
+
104
+ variables {V : Type *} {G : quiver V}
105
+
98
106
/-- The length of a path is the number of arrows it uses. -/
99
- def path. length {V} {G : quiver V} {a : V} : Π {b}, G.path a b → ℕ
107
+ def length {a : V} : Π {b}, G.path a b → ℕ
100
108
| _ path.nil := 0
101
109
| _ (path.cons p _) := p.length + 1
102
110
103
- @[simp] lemma path. length_nil {V} {G : quiver V} {a : V} :
111
+ @[simp] lemma length_nil {a : V} :
104
112
(path.nil : G.path a a).length = 0 := rfl
105
113
106
- @[simp] lemma path. length_cons {V} {G : quiver V} (a b c : V) (p : G.path a b)
114
+ @[simp] lemma length_cons (a b c : V) (p : G.path a b)
107
115
(e : G.arrow b c) : (p.cons e).length = p.length + 1 := rfl
108
116
117
+ /-- Composition of paths. -/
118
+ def comp {a b} : Π {c}, G.path a b → G.path b c → G.path a c
119
+ | _ p (path.nil) := p
120
+ | _ p (path.cons q e) := (p.comp q).cons e
121
+
122
+ @[simp] lemma comp_cons {a b c d} (p : G.path a b) (q : G.path b c) (e : G.arrow c d) :
123
+ p.comp (q.cons e) = (p.comp q).cons e := rfl
124
+ @[simp] lemma comp_nil {a b} (p : G.path a b) : p.comp path.nil = p := rfl
125
+ @[simp] lemma nil_comp {a} : ∀ {b} (p : G.path a b), path.nil.comp p = p
126
+ | a path.nil := rfl
127
+ | b (path.cons p e) := by rw [comp_cons, nil_comp]
128
+ @[simp] lemma comp_assoc {a b c} : ∀ {d}
129
+ (p : G.path a b) (q : G.path b c) (r : G.path c d),
130
+ (p.comp q).comp r = p.comp (q.comp r)
131
+ | c p q path.nil := rfl
132
+ | d p q (path.cons r e) := by rw [comp_cons, comp_cons, comp_cons, comp_assoc]
133
+
134
+ end path
135
+
109
136
/-- A quiver is an arborescence when there is a unique path from the default vertex
110
137
to every other vertex. -/
111
138
class arborescence {V} (T : quiver.{v u} V) : Sort (max (u+1 ) v) :=
@@ -165,6 +192,8 @@ class rooted_connected {V} (G : quiver V) (r : V) : Prop :=
165
192
166
193
attribute [instance] rooted_connected.nonempty_path
167
194
195
+ section geodesic_subtree
196
+
168
197
variables {V : Type *} (G : quiver.{v+1 } V) (r : V) [G.rooted_connected r]
169
198
170
199
/-- A path from `r` of minimal length. -/
@@ -189,4 +218,55 @@ arborescence_mk _ r (λ a, (G.shortest_path r a).length)
189
218
rcases this with ⟨p, hp⟩, cases p with a _ p e,
190
219
{ exact or.inl rfl }, { exact or.inr ⟨a, ⟨⟨e, p, hp⟩⟩⟩ } })
191
220
221
+ end geodesic_subtree
222
+
223
+ variables {V : Type *} (G : quiver V)
224
+
225
+ /-- A quiver `has_reverse` if we can reverse an arrow `p` from `a` to `b` to get an arrow
226
+ `p.reverse` from `b` to `a`.-/
227
+ class has_reverse :=
228
+ (reverse' : Π {a b}, G.arrow a b → G.arrow b a)
229
+
230
+ variables {G} [has_reverse G]
231
+
232
+ /-- Reverse the direction of an arrow. -/
233
+ def arrow.reverse {a b} : G.arrow a b → G.arrow b a := has_reverse.reverse'
234
+
235
+ /-- Reverse the direction of a path. -/
236
+ def path.reverse {a} : Π {b}, G.path a b → G.path b a
237
+ | a path.nil := path.nil
238
+ | b (path.cons p e) := e.reverse.to_path.comp p.reverse
239
+
240
+ variable (H : quiver.{v+1 } V)
241
+
242
+ instance : has_reverse H.symmetrify := ⟨λ a b e, e.swap⟩
243
+
244
+ /-- Two vertices are related in the zigzag setoid if there is a
245
+ zigzag of arrows from one to the other. -/
246
+ def zigzag_setoid : setoid V :=
247
+ ⟨λ a b, nonempty (H.symmetrify.path a b),
248
+ λ a, ⟨path.nil⟩,
249
+ λ a b ⟨p⟩, ⟨p.reverse⟩,
250
+ λ a b c ⟨p⟩ ⟨q⟩, ⟨p.comp q⟩⟩
251
+
252
+ /-- The type of weakly connected components of a directed graph. Two vertices are
253
+ in the same weakly connected component if there is a zigzag of arrows from one
254
+ to the other. -/
255
+ def weakly_connected_component : Type * := quotient H.zigzag_setoid
256
+
257
+ namespace weakly_connected_component
258
+ variable {H}
259
+
260
+ /-- The weakly connected component corresponding to a vertex. -/
261
+ protected def mk : V → H.weakly_connected_component := quotient.mk'
262
+
263
+ instance : has_coe_t V H.weakly_connected_component := ⟨weakly_connected_component.mk⟩
264
+ instance [inhabited V] : inhabited H.weakly_connected_component := ⟨↑(default V)⟩
265
+
266
+ protected lemma eq (a b : V) :
267
+ (a : H.weakly_connected_component) = b ↔ nonempty (H.symmetrify.path a b) :=
268
+ quotient.eq'
269
+
270
+ end weakly_connected_component
271
+
192
272
end quiver
0 commit comments