Skip to content

Commit d202ded

Browse files
committed
feat(Combinatorics/SimpleGraph): Characterizing SimpleGraph.IsCycles (#20830)
Shows that IsCycles is appropriately named. The core result is `IsCycles.exists_cycle_toSubgraph_verts_eq_connectedComponent_supp`, which shows that for an edge in a nontrivial component a cycle can be constructed that has exactly the edges of the component. In order to get this some API is included: - Coercions of walks in graphs that are the result of coerced subgraphs - NeighborSets of `toSubgraph` for paths - Supporting results for `IsCycles` - Some miscellaneous supporting lemma's This is all in preparation for Tutte's theorem. Co-authored-by: Pim Otte <otte.pim@gmail.com>
1 parent c5d6ae9 commit d202ded

File tree

5 files changed

+253
-5
lines changed

5 files changed

+253
-5
lines changed

Mathlib/Combinatorics/SimpleGraph/Connectivity/Subgraph.lean

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,22 @@ protected lemma Connected.sup {H K : G.Subgraph}
103103
rintro ⟨v, (hv|hv)⟩
104104
· exact Reachable.map (Subgraph.inclusion (le_sup_left : H ≤ H ⊔ K)) (hH ⟨u, hu⟩ ⟨v, hv⟩)
105105
· exact Reachable.map (Subgraph.inclusion (le_sup_right : K ≤ H ⊔ K)) (hK ⟨u, hu'⟩ ⟨v, hv⟩)
106+
107+
/--
108+
This lemma establishes a condition under which a subgraph is the same as a connected component.
109+
Note the asymmetry in the hypothesis `h`: `v` is in `H.verts`, but `w` is not required to be.
110+
-/
111+
lemma Connected.exists_verts_eq_connectedComponentSupp {H : Subgraph G}
112+
(hc : H.Connected) (h : ∀ v ∈ H.verts, ∀ w, G.Adj v w → H.Adj v w) :
113+
∃ c : G.ConnectedComponent, H.verts = c.supp := by
114+
rw [SimpleGraph.ConnectedComponent.exists]
115+
obtain ⟨v, hv⟩ := hc.nonempty
116+
use v
117+
ext w
118+
simp only [ConnectedComponent.mem_supp_iff, ConnectedComponent.eq]
119+
exact ⟨fun hw ↦ by simpa using (hc ⟨w, hw⟩ ⟨v, hv⟩).map H.hom,
120+
fun a ↦ a.symm.mem_subgraphVerts h hv⟩
121+
106122
end Subgraph
107123

108124
/-! ### Walks as subgraphs -/
@@ -240,6 +256,71 @@ theorem toSubgraph_adj_iff {u v u' v'} (w : G.Walk u v) :
240256
rw [← Subgraph.mem_edgeSet, ← hi.1, Subgraph.mem_edgeSet]
241257
exact toSubgraph_adj_getVert _ hi.2
242258

259+
namespace IsPath
260+
261+
lemma neighborSet_toSubgraph_startpoint {u v} {p : G.Walk u v}
262+
(hp : p.IsPath) (hnp : ¬ p.Nil) : p.toSubgraph.neighborSet u = {p.snd} := by
263+
have hadj1 := p.toSubgraph_adj_snd hnp
264+
ext v
265+
simp_all only [Subgraph.mem_neighborSet, Set.mem_insert_iff, Set.mem_singleton_iff,
266+
SimpleGraph.Walk.toSubgraph_adj_iff, Sym2.eq, Sym2.rel_iff', Prod.mk.injEq, Prod.swap_prod_mk]
267+
refine ⟨?_, by aesop⟩
268+
rintro ⟨i, hl | hr⟩
269+
· have : i = 0 := by
270+
apply hp.getVert_injOn (by rw [Set.mem_setOf]; omega) (by rw [Set.mem_setOf]; omega)
271+
aesop
272+
aesop
273+
· have : i + 1 = 0 := by
274+
apply hp.getVert_injOn (by rw [Set.mem_setOf]; omega) (by rw [Set.mem_setOf]; omega)
275+
aesop
276+
contradiction
277+
278+
lemma neighborSet_toSubgraph_endpoint {u v} {p : G.Walk u v}
279+
(hp : p.IsPath) (hnp : ¬ p.Nil) : p.toSubgraph.neighborSet v = {p.penultimate} := by
280+
simpa using IsPath.neighborSet_toSubgraph_startpoint hp.reverse
281+
(by rw [Walk.not_nil_iff_lt_length, Walk.length_reverse]; exact
282+
Walk.not_nil_iff_lt_length.mp hnp)
283+
284+
lemma neighborSet_toSubgraph_internal {u} {i : ℕ} {p : G.Walk u v} (hp : p.IsPath)
285+
(h : i ≠ 0) (h' : i < p.length) :
286+
p.toSubgraph.neighborSet (p.getVert i) = {p.getVert (i - 1), p.getVert (i + 1)} := by
287+
have hadj1 := ((show i - 1 + 1 = i from by omega) ▸
288+
p.toSubgraph_adj_getVert (by omega : (i - 1) < p.length)).symm
289+
ext v
290+
simp_all only [ne_eq, Subgraph.mem_neighborSet, Set.mem_insert_iff, Set.mem_singleton_iff,
291+
SimpleGraph.Walk.toSubgraph_adj_iff, Sym2.eq, Sym2.rel_iff', Prod.mk.injEq,
292+
Prod.swap_prod_mk]
293+
refine ⟨?_, by aesop⟩
294+
rintro ⟨i', ⟨hl, _⟩ | ⟨_, hl⟩⟩ <;>
295+
apply hp.getVert_injOn (by rw [Set.mem_setOf_eq]; omega)
296+
(by rw [Set.mem_setOf_eq]; omega) at hl <;> aesop
297+
298+
lemma ncard_neighborSet_toSubgraph_internal_eq_two {u} {i : ℕ} {p : G.Walk u v} (hp : p.IsPath)
299+
(h : i ≠ 0) (h' : i < p.length) :
300+
(p.toSubgraph.neighborSet (p.getVert i)).ncard = 2 := by
301+
rw [hp.neighborSet_toSubgraph_internal h h']
302+
have : p.getVert (i - 1) ≠ p.getVert (i + 1) := by
303+
intro h
304+
have := hp.getVert_injOn (by rw [Set.mem_setOf_eq]; omega) (by rw [Set.mem_setOf_eq]; omega) h
305+
omega
306+
simp_all
307+
308+
lemma snd_of_toSubgraph_adj {u v v'} {p : G.Walk u v} (hp : p.IsPath)
309+
(hadj : p.toSubgraph.Adj u v') : p.snd = v' := by
310+
have ⟨i, hi⟩ := p.toSubgraph_adj_iff.mp hadj
311+
simp only [Sym2.eq, Sym2.rel_iff', Prod.mk.injEq, Prod.swap_prod_mk] at hi
312+
rcases hi.1 with ⟨hl1, rfl⟩|⟨hr1, hr2⟩
313+
· have : i = 0 := by
314+
apply hp.getVert_injOn (by rw [Set.mem_setOf]; omega) (by rw [Set.mem_setOf]; omega)
315+
rw [p.getVert_zero, hl1]
316+
simp [this]
317+
· have : i + 1 = 0 := by
318+
apply hp.getVert_injOn (by rw [Set.mem_setOf]; omega) (by rw [Set.mem_setOf]; omega)
319+
rw [p.getVert_zero, hr2]
320+
contradiction
321+
322+
end IsPath
323+
243324
namespace IsCycle
244325

245326
lemma neighborSet_toSubgraph_endpoint {u} {p : G.Walk u u} (hpc : p.IsCycle) :
@@ -250,7 +331,7 @@ lemma neighborSet_toSubgraph_endpoint {u} {p : G.Walk u u} (hpc : p.IsCycle) :
250331
simp_all only [Subgraph.mem_neighborSet, Set.mem_insert_iff, Set.mem_singleton_iff,
251332
SimpleGraph.Walk.toSubgraph_adj_iff, Sym2.eq, Sym2.rel_iff', Prod.mk.injEq, Prod.swap_prod_mk]
252333
refine ⟨?_, by aesop⟩
253-
rintro ⟨i, (hl | hr)
334+
rintro ⟨i, hl | hr⟩
254335
· rw [hpc.getVert_endpoint_iff (by omega)] at hl
255336
cases hl.1 <;> aesop
256337
· rcases (hpc.getVert_endpoint_iff (by omega)).mp hr.2 with h1 | h2
@@ -269,7 +350,7 @@ lemma neighborSet_toSubgraph_internal {u} {i : ℕ} {p : G.Walk u u} (hpc : p.Is
269350
SimpleGraph.Walk.toSubgraph_adj_iff, Sym2.eq, Sym2.rel_iff', Prod.mk.injEq,
270351
Prod.swap_prod_mk]
271352
refine ⟨?_, by aesop⟩
272-
rintro ⟨i', (⟨hl1, hl2⟩ | ⟨hr1, hr2⟩)
353+
rintro ⟨i', ⟨hl1, hl2⟩ | ⟨hr1, hr2⟩⟩
273354
· apply hpc.getVert_injOn' (by rw [Set.mem_setOf_eq]; omega)
274355
(by rw [Set.mem_setOf_eq]; omega) at hl1
275356
aesop

Mathlib/Combinatorics/SimpleGraph/Matching.lean

Lines changed: 116 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ Copyright (c) 2020 Alena Gusakov. All rights reserved.
33
Released under Apache 2.0 license as described in the file LICENSE.
44
Authors: Alena Gusakov, Arthur Paulino, Kyle Miller, Pim Otte
55
-/
6-
import Mathlib.Combinatorics.SimpleGraph.DegreeSum
6+
import Mathlib.Combinatorics.SimpleGraph.Connectivity.Subgraph
77
import Mathlib.Combinatorics.SimpleGraph.Connectivity.WalkCounting
8+
import Mathlib.Combinatorics.SimpleGraph.DegreeSum
89
import Mathlib.Data.Fintype.Order
910
import Mathlib.Data.Set.Functor
1011

@@ -334,6 +335,16 @@ lemma IsCycles.other_adj_of_adj (h : G.IsCycles) (hadj : G.Adj v w) :
334335
obtain ⟨w', hww'⟩ := (G.neighborSet v).exists_ne_of_one_lt_ncard (by omega) w
335336
exact ⟨w', ⟨hww'.2.symm, hww'.1⟩⟩
336337

338+
lemma IsCycles.existsUnique_ne_adj (h : G.IsCycles) (hadj : G.Adj v w) :
339+
∃! w', w ≠ w' ∧ G.Adj v w' := by
340+
obtain ⟨w', ⟨hww, hww'⟩⟩ := h.other_adj_of_adj hadj
341+
use w'
342+
refine ⟨⟨hww, hww'⟩, ?_⟩
343+
intro y ⟨hwy, hwy'⟩
344+
obtain ⟨x, y', hxy'⟩ := Set.ncard_eq_two.mp (h ⟨w, hadj⟩)
345+
simp_rw [← SimpleGraph.mem_neighborSet] at *
346+
aesop
347+
337348
lemma IsCycles.induce_supp (c : G.ConnectedComponent) (h : G.IsCycles) :
338349
(G.induce c.supp).spanningCoe.IsCycles := by
339350
intro v ⟨w, hw⟩
@@ -360,6 +371,110 @@ lemma Subgraph.IsPerfectMatching.symmDiff_isCycles
360371
use w, w'
361372
aesop
362373

374+
lemma IsCycles.snd_of_mem_support_of_isPath_of_adj [Finite V] {v w w' : V}
375+
(hcyc : G.IsCycles) (p : G.Walk v w) (hw : w ≠ w') (hw' : w' ∈ p.support) (hp : p.IsPath)
376+
(hadj : G.Adj v w') : p.snd = w' := by
377+
classical
378+
apply hp.snd_of_toSubgraph_adj
379+
rw [Walk.mem_support_iff_exists_getVert] at hw'
380+
obtain ⟨n, ⟨rfl, hnl⟩⟩ := hw'
381+
by_cases hn : n = 0 ∨ n = p.length
382+
· aesop
383+
have e : G.neighborSet (p.getVert n) ≃ p.toSubgraph.neighborSet (p.getVert n) := by
384+
refine @Classical.ofNonempty _ ?_
385+
rw [← Cardinal.eq, ← Set.cast_ncard (Set.toFinite _), ← Set.cast_ncard (Set.toFinite _),
386+
hp.ncard_neighborSet_toSubgraph_internal_eq_two (by omega) (by omega),
387+
hcyc (Set.nonempty_of_mem hadj.symm)]
388+
rw [Subgraph.adj_comm, Subgraph.adj_iff_of_neighborSet_equiv e (Set.toFinite _).fintype]
389+
exact hadj.symm
390+
391+
private lemma IsCycles.reachable_sdiff_toSubgraph_spanningCoe_aux [Fintype V] {v w : V}
392+
(hcyc : G.IsCycles) (p : G.Walk v w) (hp : p.IsPath) :
393+
(G \ p.toSubgraph.spanningCoe).Reachable w v := by
394+
classical
395+
-- Consider the case when p is nil
396+
by_cases hvw : v = w
397+
· subst hvw
398+
use .nil
399+
have hpn : ¬p.Nil := Walk.not_nil_of_ne hvw
400+
obtain ⟨w', ⟨hw'1, hw'2⟩, hwu⟩ := hcyc.existsUnique_ne_adj
401+
(p.toSubgraph_adj_snd hpn).adj_sub
402+
-- The edge (v, w) can't be in p, because then it would be the second node
403+
have hnpvw' : ¬ p.toSubgraph.Adj v w' := by
404+
intro h
405+
exact hw'1 (hp.snd_of_toSubgraph_adj h)
406+
-- If w = w', then then the reachability can be proved with just one edge
407+
by_cases hww' : w = w'
408+
· subst hww'
409+
have : (G \ p.toSubgraph.spanningCoe).Adj w v := by
410+
simp only [sdiff_adj, Subgraph.spanningCoe_adj]
411+
exact ⟨hw'2.symm, fun h ↦ hnpvw' h.symm⟩
412+
exact this.reachable
413+
-- Construct the walk needed recursively by extending p
414+
have hle : (G \ (p.cons hw'2.symm).toSubgraph.spanningCoe) ≤ (G \ p.toSubgraph.spanningCoe) := by
415+
apply sdiff_le_sdiff (by rfl) ?hcd
416+
aesop
417+
have hp'p : (p.cons hw'2.symm).IsPath := by
418+
rw [Walk.cons_isPath_iff]
419+
refine ⟨hp, fun hw' ↦ ?_⟩
420+
exact hw'1 (hcyc.snd_of_mem_support_of_isPath_of_adj _ hww' hw' hp hw'2)
421+
have : (G \ p.toSubgraph.spanningCoe).Adj w' v := by
422+
simp only [sdiff_adj, Subgraph.spanningCoe_adj]
423+
refine ⟨hw'2.symm, fun h ↦ ?_⟩
424+
exact hnpvw' h.symm
425+
use (((hcyc.reachable_sdiff_toSubgraph_spanningCoe_aux
426+
(p.cons hw'2.symm) hp'p).some).mapLe hle).append this.toWalk
427+
termination_by Fintype.card V + 1 - p.length
428+
decreasing_by
429+
simp_wf
430+
have := Walk.IsPath.length_lt hp
431+
omega
432+
433+
lemma IsCycles.reachable_sdiff_toSubgraph_spanningCoe [Finite V] {v w : V} (hcyc : G.IsCycles)
434+
(p : G.Walk v w) (hp : p.IsPath) : (G \ p.toSubgraph.spanningCoe).Reachable w v := by
435+
have : Fintype V := Fintype.ofFinite V
436+
exact reachable_sdiff_toSubgraph_spanningCoe_aux hcyc p hp
437+
438+
lemma IsCycles.reachable_deleteEdges [Finite V] (hadj : G.Adj v w)
439+
(hcyc : G.IsCycles) : (G.deleteEdges {s(v, w)}).Reachable v w := by
440+
have : fromEdgeSet {s(v, w)} = hadj.toWalk.toSubgraph.spanningCoe := by
441+
simp only [Walk.toSubgraph, singletonSubgraph_le_iff, subgraphOfAdj_verts, Set.mem_insert_iff,
442+
Set.mem_singleton_iff, or_true, sup_of_le_left]
443+
exact (Subgraph.spanningCoe_subgraphOfAdj hadj).symm
444+
rw [show G.deleteEdges {s(v, w)} = G \ fromEdgeSet {s(v, w)} from by rfl]
445+
exact this ▸ (hcyc.reachable_sdiff_toSubgraph_spanningCoe hadj.toWalk
446+
(Walk.IsPath.of_adj hadj)).symm
447+
448+
lemma IsCycles.exists_cycle_toSubgraph_verts_eq_connectedComponentSupp [Finite V]
449+
{c : G.ConnectedComponent} (h : G.IsCycles) (hv : v ∈ c.supp)
450+
(hn : (G.neighborSet v).Nonempty) :
451+
∃ (p : G.Walk v v), p.IsCycle ∧ p.toSubgraph.verts = c.supp := by
452+
classical
453+
obtain ⟨w, hw⟩ := hn
454+
obtain ⟨u, p, hp⟩ := SimpleGraph.adj_and_reachable_delete_edges_iff_exists_cycle.mp
455+
⟨hw, h.reachable_deleteEdges hw⟩
456+
have hvp : v ∈ p.support := SimpleGraph.Walk.fst_mem_support_of_mem_edges _ hp.2
457+
have : p.toSubgraph.verts = c.supp := by
458+
obtain ⟨c', hc'⟩ := p.toSubgraph_connected.exists_verts_eq_connectedComponentSupp (by
459+
intro v hv w hadj
460+
refine (Subgraph.adj_iff_of_neighborSet_equiv ?_ (Set.toFinite _).fintype).mpr hadj
461+
have : (G.neighborSet v).Nonempty := by
462+
rw [Walk.mem_verts_toSubgraph] at hv
463+
refine (Set.nonempty_of_ncard_ne_zero ?_).mono (p.toSubgraph.neighborSet_subset v)
464+
rw [hp.1.ncard_neighborSet_toSubgraph_eq_two hv]
465+
omega
466+
refine @Classical.ofNonempty _ ?_
467+
rw [← Cardinal.eq, ← Set.cast_ncard (Set.toFinite _), ← Set.cast_ncard (Set.toFinite _),
468+
h this, hp.1.ncard_neighborSet_toSubgraph_eq_two (p.mem_verts_toSubgraph.mp hv)])
469+
rw [hc']
470+
have : v ∈ c'.supp := by
471+
rw [← hc', Walk.mem_verts_toSubgraph]
472+
exact hvp
473+
simp_all
474+
use p.rotate hvp
475+
rw [← this]
476+
exact ⟨hp.1.rotate _, by simp_all⟩
477+
363478
/--
364479
A graph `G` is alternating with respect to some other graph `G'`, if exactly every other edge in
365480
`G` is in `G'`. Note that the degree of each vertex needs to be at most 2 for this to be

Mathlib/Combinatorics/SimpleGraph/Path.lean

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -227,6 +227,9 @@ theorem IsPath.of_append_right {u v w : V} {p : G.Walk u v} {q : G.Walk v w}
227227
rw [reverse_append] at h
228228
apply h.of_append_left
229229

230+
lemma IsPath.of_adj {G : SimpleGraph V} {u v : V} (h : G.Adj u v) : h.toWalk.IsPath := by
231+
aesop
232+
230233
@[simp]
231234
theorem IsCycle.not_of_nil {u : V} : ¬(nil : G.Walk u u).IsCycle := fun h => h.ne_nil rfl
232235

@@ -799,6 +802,21 @@ theorem Iso.symm_apply_reachable {G : SimpleGraph V} {G' : SimpleGraph V'} {φ :
799802
{v : V'} : G.Reachable (φ.symm v) u ↔ G'.Reachable v (φ u) := by
800803
rw [← Iso.reachable_iff, RelIso.apply_symm_apply]
801804

805+
lemma Reachable.mem_subgraphVerts {u v} {H : G.Subgraph} (hr : G.Reachable u v)
806+
(h : ∀ v ∈ H.verts, ∀ w, G.Adj v w → H.Adj v w)
807+
(hu : u ∈ H.verts) : v ∈ H.verts := by
808+
let rec aux {v' : V} (hv' : v' ∈ H.verts) (p : G.Walk v' v) : v ∈ H.verts := by
809+
by_cases hnp : p.Nil
810+
· exact hnp.eq ▸ hv'
811+
exact aux (H.edge_vert (h _ hv' _ (Walk.adj_snd hnp)).symm) p.tail
812+
termination_by p.length
813+
decreasing_by {
814+
simp_wf
815+
rw [← Walk.length_tail_add_one hnp]
816+
omega
817+
}
818+
exact aux hu hr.some
819+
802820
variable (G)
803821

804822
theorem reachable_is_equivalence : Equivalence G.Reachable :=
@@ -1179,8 +1197,8 @@ def IsBridge (G : SimpleGraph V) (e : Sym2 V) : Prop :=
11791197
theorem isBridge_iff {u v : V} :
11801198
G.IsBridge s(u, v) ↔ G.Adj u v ∧ ¬(G \ fromEdgeSet {s(u, v)}).Reachable u v := Iff.rfl
11811199

1182-
theorem reachable_delete_edges_iff_exists_walk {v w : V} :
1183-
(G \ fromEdgeSet {s(v, w)}).Reachable v w ↔ ∃ p : G.Walk v w, ¬s(v, w) ∈ p.edges := by
1200+
theorem reachable_delete_edges_iff_exists_walk {v w v' w': V} :
1201+
(G \ fromEdgeSet {s(v, w)}).Reachable v' w' ↔ ∃ p : G.Walk v' w', ¬s(v, w) ∈ p.edges := by
11841202
constructor
11851203
· rintro ⟨p⟩
11861204
use p.map (Hom.mapSpanningSubgraphs (by simp))

Mathlib/Combinatorics/SimpleGraph/Subgraph.lean

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,12 @@ theorem spanningCoe_inj : G₁.spanningCoe = G₂.spanningCoe ↔ G₁.Adj = G
174174
lemma mem_of_adj_spanningCoe {v w : V} {s : Set V} (G : SimpleGraph s)
175175
(hadj : G.spanningCoe.Adj v w) : v ∈ s := by aesop
176176

177+
@[simp]
178+
lemma spanningCoe_subgraphOfAdj {v w : V} (hadj : G.Adj v w) :
179+
(G.subgraphOfAdj hadj).spanningCoe = fromEdgeSet {s(v, w)} := by
180+
ext v w
181+
aesop
182+
177183
/-- `spanningCoe` is equivalent to `coe` for a subgraph that `IsSpanning`. -/
178184
@[simps]
179185
def spanningCoeEquivCoeOfSpanning (G' : Subgraph G) (h : G'.IsSpanning) :
@@ -566,6 +572,10 @@ theorem _root_.SimpleGraph.toSubgraph.isSpanning (H : SimpleGraph V) (h : H ≤
566572
theorem spanningCoe_le_of_le {H H' : Subgraph G} (h : H ≤ H') : H.spanningCoe ≤ H'.spanningCoe :=
567573
h.2
568574

575+
@[simp]
576+
lemma sup_spanningCoe (H H' : Subgraph G) :
577+
(H ⊔ H').spanningCoe = H.spanningCoe ⊔ H'.spanningCoe := rfl
578+
569579
/-- The top of the `Subgraph G` lattice is equivalent to the graph itself. -/
570580
def topEquiv : (⊤ : Subgraph G).coe ≃g G where
571581
toFun v := ↑v
@@ -764,6 +774,22 @@ theorem degree_eq_one_iff_unique_adj {G' : Subgraph G} {v : V} [Fintype (G'.neig
764774
rw [← finset_card_neighborSet_eq_degree, Finset.card_eq_one, Finset.singleton_iff_unique_mem]
765775
simp only [Set.mem_toFinset, mem_neighborSet]
766776

777+
lemma adj_iff_of_neighborSet_equiv {v : V} {H : Subgraph G}
778+
(h : G.neighborSet v ≃ H.neighborSet v) (hfin : Fintype (G.neighborSet v)) :
779+
∀ {w}, H.Adj v w ↔ G.Adj v w := by
780+
classical
781+
intro w
782+
refine ⟨fun a => a.adj_sub, ?_⟩
783+
have : Fintype (H.neighborSet v) := (h.set_finite_iff.mp hfin.finite).fintype
784+
let f : H.neighborSet v → G.neighborSet v := fun a => ⟨a, a.coe_prop.adj_sub⟩
785+
have hfinj : f.Injective := fun w w' hww' ↦ by aesop
786+
have hfbij : f.Bijective := ⟨hfinj, hfinj.surjective_of_fintype h.symm⟩
787+
intro h
788+
have hv := (Fintype.bijInv hfbij ⟨w, h⟩).coe_prop
789+
obtain ⟨v', hv'⟩ : ∃ v', f v' = ⟨w, h⟩ := hfbij.surjective ⟨w, h⟩
790+
have : (f v') = w := by simpa using congrArg Subtype.val hv'
791+
aesop
792+
767793
end Subgraph
768794

769795
section MkProperties

Mathlib/Combinatorics/SimpleGraph/Walk.lean

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -890,6 +890,14 @@ lemma adj_penultimate {p : G.Walk v w} (hp : ¬ p.Nil) :
890890
rw [nil_iff_length_eq] at hp
891891
convert adj_getVert_succ _ _ <;> omega
892892

893+
@[simp]
894+
lemma snd_reverse (p : G.Walk u v) : p.reverse.snd = p.penultimate := by
895+
simpa using getVert_reverse p 1
896+
897+
@[simp]
898+
lemma penultimate_reverse (p : G.Walk u v) : p.reverse.penultimate = p.snd := by
899+
cases p <;> simp [snd, penultimate, getVert_append]
900+
893901
/-- The walk obtained by removing the first dart of a walk. A nil walk stays nil. -/
894902
def tail (p : G.Walk u v) : G.Walk (p.snd) v := p.drop 1
895903

0 commit comments

Comments
 (0)