Skip to content

Commit 8f06fca

Browse files
committed
feat(Combinatorics/SimpleGraph/Matching): add IsCycles and IsAlternating with basic results (#19250)
add `SimpleGraph.IsCycles` and `SimpleGraph.IsAlternating` with some basic results involving matchings. These are defined on `SimpleGraph`, because we want to use the `symmDiff` defined on there. This is in preparation for Tutte's theorem. Co-authored-by: Pim Otte <otte.pim@gmail.com>
1 parent 1426b9e commit 8f06fca

File tree

1 file changed

+87
-0
lines changed

1 file changed

+87
-0
lines changed

Mathlib/Combinatorics/SimpleGraph/Matching.lean

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ one edge, and the edges of the subgraph represent the paired vertices.
2727
* `SimpleGraph.Subgraph.IsPerfectMatching` defines when a subgraph `M` of a simple graph is a
2828
perfect matching, denoted `M.IsPerfectMatching`.
2929
30+
* `SimpleGraph.IsMatchingFree` means that a graph `G` has no perfect matchings.
31+
32+
* `SimpleGraph.IsCycles` means that a graph consists of cycles (including cycles of length 0,
33+
also known as isolated vertices)
34+
35+
* `SimpleGraph.IsAlternating` means that edges in a graph `G` are alternatingly
36+
included and not included in some other graph `G'`
37+
3038
## TODO
3139
3240
* Define an `other` function and prove useful results about it (https://leanprover.zulipchat.com/#narrow/stream/252551-graph-theory/topic/matchings/near/266205863)
@@ -309,4 +317,83 @@ lemma exists_maximal_isMatchingFree [Finite V] (h : G.IsMatchingFree) :
309317
obtain ⟨Gmax, hGmax⟩ := Finite.exists_le_maximal h
310318
exact ⟨Gmax, ⟨hGmax.1, ⟨hGmax.2.prop, fun _ h' ↦ hGmax.2.not_prop_of_gt h'⟩⟩⟩
311319

320+
/-- A graph `G` consists of a set of cycles, if each vertex is either isolated or connected to
321+
exactly two vertices. This is used to create new matchings by taking the `symmDiff` with cycles.
322+
The definition of `symmDiff` that makes sense is the one for `SimpleGraph`. The `symmDiff`
323+
for `SimpleGraph.Subgraph` deriving from the lattice structure also affects the vertices included,
324+
which we do not want in this case. This is why this property is defined for `SimpleGraph`, rather
325+
than `SimpleGraph.Subgraph`.
326+
-/
327+
def IsCycles (G : SimpleGraph V) := ∀ ⦃v⦄, (G.neighborSet v).Nonempty → (G.neighborSet v).ncard = 2
328+
329+
/--
330+
Given a vertex with one edge in a graph of cycles this gives the other edge incident
331+
to the same vertex.
332+
-/
333+
lemma IsCycles.other_adj_of_adj (h : G.IsCycles) (hadj : G.Adj v w) :
334+
∃ w', w ≠ w' ∧ G.Adj v w' := by
335+
simp_rw [← SimpleGraph.mem_neighborSet] at hadj ⊢
336+
cases' (G.neighborSet v).eq_empty_or_nonempty with hl hr
337+
· exact ((Set.eq_empty_iff_forall_not_mem.mp hl) _ hadj).elim
338+
· have := h hr
339+
obtain ⟨w', hww'⟩ := (G.neighborSet v).exists_ne_of_one_lt_ncard (by omega) w
340+
exact ⟨w', ⟨hww'.2.symm, hww'.1⟩⟩
341+
342+
open scoped symmDiff
343+
344+
lemma Subgraph.IsPerfectMatching.symmDiff_spanningCoe_IsCycles
345+
{M : Subgraph G} {M' : Subgraph G'} (hM : M.IsPerfectMatching)
346+
(hM' : M'.IsPerfectMatching) : (M.spanningCoe ∆ M'.spanningCoe).IsCycles := by
347+
intro v
348+
obtain ⟨w, hw⟩ := hM.1 (hM.2 v)
349+
obtain ⟨w', hw'⟩ := hM'.1 (hM'.2 v)
350+
simp only [symmDiff_def, Set.ncard_eq_two, ne_eq, imp_iff_not_or, Set.not_nonempty_iff_eq_empty,
351+
Set.eq_empty_iff_forall_not_mem, SimpleGraph.mem_neighborSet, SimpleGraph.sup_adj, sdiff_adj,
352+
spanningCoe_adj, not_or, not_and, not_not]
353+
by_cases hww' : w = w'
354+
· simp_all [← imp_iff_not_or, hww']
355+
· right
356+
use w, w'
357+
aesop
358+
359+
/--
360+
A graph `G` is alternating with respect to some other graph `G'`, if exactly every other edge in
361+
`G` is in `G'`. Note that the degree of each vertex needs to be at most 2 for this to be
362+
possible. This property is used to create new matchings using `symmDiff`.
363+
The definition of `symmDiff` that makes sense is the one for `SimpleGraph`. The `symmDiff`
364+
for `SimpleGraph.Subgraph` deriving from the lattice structure also affects the vertices included,
365+
which we do not want in this case. This is why this property, just like `IsCycles`, is defined
366+
for `SimpleGraph` rather than `SimpleGraph.Subgraph`.
367+
-/
368+
def IsAlternating (G G' : SimpleGraph V) :=
369+
∀ ⦃v w w': V⦄, w ≠ w' → G.Adj v w → G.Adj v w' → (G'.Adj v w ↔ ¬ G'.Adj v w')
370+
371+
lemma IsPerfectMatching.symmDiff_spanningCoe_of_isAlternating {M : Subgraph G}
372+
(hM : M.IsPerfectMatching) (hG' : G'.IsAlternating M.spanningCoe) (hG'cyc : G'.IsCycles) :
373+
(SimpleGraph.toSubgraph (M.spanningCoe ∆ G')
374+
(by rfl)).IsPerfectMatching := by
375+
rw [Subgraph.isPerfectMatching_iff]
376+
intro v
377+
simp only [toSubgraph_adj, symmDiff_def, sup_adj, sdiff_adj, Subgraph.spanningCoe_adj]
378+
obtain ⟨w, hw⟩ := hM.1 (hM.2 v)
379+
by_cases h : G'.Adj v w
380+
· obtain ⟨w', hw'⟩ := hG'cyc.other_adj_of_adj h
381+
have hmadj : M.Adj v w ↔ ¬M.Adj v w' := by simpa using hG' hw'.1 h hw'.2
382+
use w'
383+
simp only [hmadj.mp hw.1, hw'.2, not_true_eq_false, and_self, not_false_eq_true, or_true,
384+
true_and]
385+
rintro y (hl | hr)
386+
· aesop
387+
· obtain ⟨w'', hw''⟩ := hG'cyc.other_adj_of_adj hr.1
388+
by_contra! hc
389+
simp_all only [show M.Adj v y ↔ ¬M.Adj v w' from by simpa using hG' hc hr.1 hw'.2,
390+
not_false_eq_true, ne_eq, iff_true, not_true_eq_false, and_false]
391+
· use w
392+
simp only [hw.1, h, not_false_eq_true, and_self, not_true_eq_false, or_false, true_and]
393+
rintro y (hl | hr)
394+
· exact hw.2 _ hl.1
395+
· have ⟨w', hw'⟩ := hG'cyc.other_adj_of_adj hr.1
396+
simp_all only [show M.Adj v y ↔ ¬M.Adj v w' from by simpa using hG' hw'.1 hr.1 hw'.2, not_not,
397+
ne_eq, and_false]
398+
312399
end SimpleGraph

0 commit comments

Comments
 (0)