|
| 1 | +/- |
| 2 | +Copyright (c) 2024 Pim Otte. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Pim Otte |
| 5 | +-/ |
| 6 | + |
| 7 | +import Mathlib.Combinatorics.SimpleGraph.Matching |
| 8 | +import Mathlib.Combinatorics.SimpleGraph.Operations |
| 9 | +import Mathlib.Combinatorics.SimpleGraph.UniversalVerts |
| 10 | +import Mathlib.Data.Fintype.Card |
| 11 | + |
| 12 | +/-! |
| 13 | +# Tutte's theorem (work in progress) |
| 14 | +
|
| 15 | +## Main definitions |
| 16 | +* `SimpleGraph.TutteViolator G u` is a set of vertices `u` which certifies non-existence of a |
| 17 | + perfect matching. |
| 18 | +-/ |
| 19 | + |
| 20 | +namespace SimpleGraph |
| 21 | + |
| 22 | +universe u |
| 23 | +variable {V : Type u} {G G' : SimpleGraph V} {u x v' w : V} [Fintype V] |
| 24 | + |
| 25 | +/-- A set certifying non-existence of a perfect matching. -/ |
| 26 | +def IsTutteViolator (G : SimpleGraph V) (u : Set V) : Prop := |
| 27 | + u.ncard < ((⊤ : G.Subgraph).deleteVerts u).coe.oddComponents.ncard |
| 28 | + |
| 29 | +/-- Given a graph in which the universal vertices do not violate Tutte's condition, |
| 30 | +if the graph decomposes into cliques, there exists a matching that covers |
| 31 | +everything except some universal vertices. |
| 32 | +
|
| 33 | +This lemma is marked private, because |
| 34 | +it is strictly weaker than `IsPerfectMatching.exists_of_isClique_supp`. -/ |
| 35 | +private lemma Subgraph.IsMatching.exists_verts_compl_subset_universalVerts |
| 36 | + (h : ¬IsTutteViolator G G.universalVerts) |
| 37 | + (h' : ∀ (K : G.deleteUniversalVerts.coe.ConnectedComponent), |
| 38 | + G.deleteUniversalVerts.coe.IsClique K.supp) : |
| 39 | + ∃ M : Subgraph G, M.IsMatching ∧ M.vertsᶜ ⊆ G.universalVerts := by |
| 40 | + classical |
| 41 | + have hrep := ConnectedComponent.Represents.image_out |
| 42 | + G.deleteUniversalVerts.coe.oddComponents |
| 43 | + -- First we match one node from each odd component to a universal vertex |
| 44 | + obtain ⟨t, ht, M1, hM1⟩ := Subgraph.IsMatching.exists_of_universalVerts |
| 45 | + (disjoint_image_val_universalVerts _).symm (by |
| 46 | + simp only [IsTutteViolator, not_lt] at h |
| 47 | + rwa [Set.ncard_image_of_injective _ Subtype.val_injective, hrep.ncard_eq]) |
| 48 | + -- Then we match all other nodes in components internally |
| 49 | + have exists_complMatch (K : G.deleteUniversalVerts.coe.ConnectedComponent) : |
| 50 | + ∃ M : Subgraph G, M.verts = Subtype.val '' K.supp \ M1.verts ∧ M.IsMatching := by |
| 51 | + have : G.IsClique (Subtype.val '' K.supp \ M1.verts) := |
| 52 | + ((h' K).of_induce).subset Set.diff_subset |
| 53 | + rw [← this.even_iff_exists_isMatching (Set.toFinite _), hM1.1] |
| 54 | + exact even_ncard_image_val_supp_sdiff_image_val_rep_union _ ht hrep |
| 55 | + choose complMatch hcomplMatch_compl hcomplMatch_match using exists_complMatch |
| 56 | + let M2 : Subgraph G := ⨆ K, complMatch K |
| 57 | + have hM2 : M2.IsMatching := by |
| 58 | + refine .iSup hcomplMatch_match fun i j hij ↦ (?_ : Disjoint _ _) |
| 59 | + rw [(hcomplMatch_match i).support_eq_verts, hcomplMatch_compl i, |
| 60 | + (hcomplMatch_match j).support_eq_verts, hcomplMatch_compl j] |
| 61 | + exact Set.disjoint_of_subset Set.diff_subset Set.diff_subset <| |
| 62 | + Set.disjoint_image_of_injective Subtype.val_injective <| |
| 63 | + SimpleGraph.pairwise_disjoint_supp_connectedComponent _ hij |
| 64 | + have disjointM12 : Disjoint M1.support M2.support := by |
| 65 | + rw [hM1.2.support_eq_verts, hM2.support_eq_verts, Subgraph.verts_iSup, |
| 66 | + Set.disjoint_iUnion_right] |
| 67 | + exact fun K ↦ hcomplMatch_compl K ▸ Set.disjoint_sdiff_right |
| 68 | + -- The only vertices left are indeed contained in universalVerts |
| 69 | + have : (M1.verts ∪ M2.verts)ᶜ ⊆ G.universalVerts := by |
| 70 | + rw [Set.compl_subset_comm, Set.compl_eq_univ_diff] |
| 71 | + intro v hv |
| 72 | + by_cases h : v ∈ M1.verts |
| 73 | + · exact M1.verts.mem_union_left _ h |
| 74 | + right |
| 75 | + simp only [deleteUniversalVerts_verts, Subgraph.verts_iSup, Set.mem_iUnion, M2, |
| 76 | + hcomplMatch_compl] |
| 77 | + use G.deleteUniversalVerts.coe.connectedComponentMk ⟨v, hv⟩ |
| 78 | + aesop |
| 79 | + exact ⟨M1 ⊔ M2, hM1.2.sup hM2 disjointM12, this⟩ |
| 80 | + |
| 81 | +/-- Given a graph in which the universal vertices do not violate Tutte's condition, |
| 82 | +if the graph decomposes into cliques, it has a perfect matching. -/ |
| 83 | +theorem Subgraph.IsPerfectMatching.exists_of_isClique_supp |
| 84 | + (hveven : Even (Nat.card V)) (h : ¬G.IsTutteViolator G.universalVerts) |
| 85 | + (h' : ∀ (K : G.deleteUniversalVerts.coe.ConnectedComponent), |
| 86 | + G.deleteUniversalVerts.coe.IsClique K.supp) : ∃ (M : Subgraph G), M.IsPerfectMatching := by |
| 87 | + classical |
| 88 | + obtain ⟨M, hM, hsub⟩ := IsMatching.exists_verts_compl_subset_universalVerts h h' |
| 89 | + obtain ⟨M', hM'⟩ := ((G.isClique_universalVerts.subset hsub).even_iff_exists_isMatching |
| 90 | + (Set.toFinite _)).mp (by simpa [Set.even_ncard_compl_iff hveven, -Set.toFinset_card, |
| 91 | + ← Set.ncard_eq_toFinset_card'] using hM.even_card) |
| 92 | + use M ⊔ M' |
| 93 | + have hspan : (M ⊔ M').IsSpanning := by |
| 94 | + rw [Subgraph.isSpanning_iff, Subgraph.verts_sup, hM'.1] |
| 95 | + exact M.verts.union_compl_self |
| 96 | + exact ⟨hM.sup hM'.2 (by |
| 97 | + simp only [hM.support_eq_verts, hM'.2.support_eq_verts, hM'.1, Subgraph.verts_sup] |
| 98 | + exact (Set.disjoint_compl_left_iff_subset.mpr fun ⦃a⦄ a ↦ a).symm), hspan⟩ |
| 99 | + |
| 100 | +theorem IsTutteViolator.empty (hodd : Odd (Fintype.card V)) : G.IsTutteViolator ∅ := by |
| 101 | + have c := |
| 102 | + Finite.card_pos_iff.mp |
| 103 | + ((odd_ncard_oddComponents ((⊤ : Subgraph G).deleteVerts ∅).coe).mpr (by |
| 104 | + simpa [Fintype.card_congr (Equiv.Set.univ V)] using hodd)).pos |
| 105 | + rw [IsTutteViolator, Set.ncard_empty, Set.ncard_pos] |
| 106 | + exact Set.Nonempty.of_subtype |
| 107 | + |
| 108 | +/-- Proves the necessity part of Tutte's theorem -/ |
| 109 | +lemma not_isTutteViolator_of_isPerfectMatching {M : Subgraph G} (hM : M.IsPerfectMatching) |
| 110 | + (u : Set V) : |
| 111 | + ¬G.IsTutteViolator u := by |
| 112 | + choose f hf g hgf hg using ConnectedComponent.odd_matches_node_outside hM (u := u) |
| 113 | + have hfinj : f.Injective := fun c d hcd ↦ by |
| 114 | + replace hcd : g c = g d := Subtype.val_injective <| hM.1.eq_of_adj_right (hgf c) (hcd ▸ hgf d) |
| 115 | + exact Subtype.val_injective <| ConnectedComponent.eq_of_common_vertex (hg c) (hcd ▸ hg d) |
| 116 | + simpa [IsTutteViolator] using |
| 117 | + Finite.card_le_of_injective (fun c ↦ ⟨f c, hf c⟩) (fun c d ↦ by simp [hfinj.eq_iff]) |
| 118 | + |
| 119 | +end SimpleGraph |
0 commit comments