Catalog/Sparsity/ShallowTopologicalMinor/Full.lean
| 1 | import Mathlib.Combinatorics.SimpleGraph.Walk.Basic |
| 2 | import Mathlib.Combinatorics.SimpleGraph.Paths |
| 3 | import Mathlib.Data.Sym.Sym2 |
| 4 | import Catalog.Sparsity.ShallowMinor.Full |
| 5 | |
| 6 | namespace Catalog.Sparsity.ShallowTopologicalMinor |
| 7 | |
| 8 | open Catalog.Sparsity.ShallowMinor |
| 9 | |
| 10 | /-- A depth-`d` topological minor model of `H` in `G`. |
| 11 | |
| 12 | Each vertex of `H` is mapped injectively to a branch vertex of `G`. Every edge |
| 13 | of `H` is routed by a path between the corresponding branch vertices, of length |
| 14 | at most `2d + 1`. Internal routed vertices avoid all branch vertices, and the |
| 15 | internal vertices of routed paths for distinct edges are disjoint. |
| 16 | (Defs 1.12, 2.15-2.16) -/ |
| 17 | structure ShallowTopologicalMinorModel {V W : Type} |
| 18 | (H : SimpleGraph W) (G : SimpleGraph V) (d : ℕ) where |
| 19 | branchVertex : W ↪ V |
| 20 | edgeTail : H.edgeSet → W |
| 21 | edgeTail_mem : ∀ e : H.edgeSet, edgeTail e ∈ (e : Sym2 W) |
| 22 | edgePath : ∀ e : H.edgeSet, |
| 23 | G.Walk (branchVertex (edgeTail e)) |
| 24 | (branchVertex (Sym2.Mem.other (edgeTail_mem e))) |
| 25 | edgePath_isPath : ∀ e, (edgePath e).IsPath |
| 26 | edgePath_length : ∀ e, (edgePath e).length ≤ 2 * d + 1 |
| 27 | edgePath_interior_avoids_branch : |
| 28 | ∀ e {x : V}, |
| 29 | x ∈ (edgePath e).support → |
| 30 | x ≠ branchVertex (edgeTail e) → |
| 31 | x ≠ branchVertex (Sym2.Mem.other (edgeTail_mem e)) → |
| 32 | ∀ w : W, x ≠ branchVertex w |
| 33 | edgePath_interior_disjoint : |
| 34 | ∀ e e' {x : V}, |
| 35 | e ≠ e' → |
| 36 | x ∈ (edgePath e).support → |
| 37 | x ∈ (edgePath e').support → |
| 38 | x ≠ branchVertex (edgeTail e) → |
| 39 | x ≠ branchVertex (Sym2.Mem.other (edgeTail_mem e)) → |
| 40 | x ≠ branchVertex (edgeTail e') → |
| 41 | x ≠ branchVertex (Sym2.Mem.other (edgeTail_mem e')) → |
| 42 | False |
| 43 | |
| 44 | /-- `H` is a depth-`d` topological minor of `G`. -/ |
| 45 | def IsShallowTopologicalMinor {V W : Type} |
| 46 | (H : SimpleGraph W) (G : SimpleGraph V) (d : ℕ) : Prop := |
| 47 | Nonempty (ShallowTopologicalMinorModel H G d) |
| 48 | |
| 49 | noncomputable def ShallowTopologicalMinorModel.ofSubgraph |
| 50 | {V W : Type} {H : SimpleGraph W} {G G' : SimpleGraph V} {d : ℕ} |
| 51 | (m : ShallowTopologicalMinorModel H G d) |
| 52 | (hsub : ∀ {u v}, G.Adj u v → G'.Adj u v) : |
| 53 | ShallowTopologicalMinorModel H G' d := |
| 54 | { branchVertex := m.branchVertex |
| 55 | edgeTail := m.edgeTail |
| 56 | edgeTail_mem := m.edgeTail_mem |
| 57 | edgePath := fun e => by |
| 58 | let p := m.edgePath e |
| 59 | have hedge : ∀ e' ∈ p.edges, e' ∈ G'.edgeSet := by |
| 60 | intro e' he' |
| 61 | have hmem := SimpleGraph.Walk.edges_subset_edgeSet p he' |
| 62 | revert hmem |
| 63 | refine e'.ind ?_ |
| 64 | intro a b hab |
| 65 | exact show G'.Adj a b by exact hsub hab |
| 66 | exact p.transfer G' hedge |
| 67 | edgePath_isPath := by |
| 68 | intro e |
| 69 | let p := m.edgePath e |
| 70 | have hedge : ∀ e' ∈ p.edges, e' ∈ G'.edgeSet := by |
| 71 | intro e' he' |
| 72 | have hmem := SimpleGraph.Walk.edges_subset_edgeSet p he' |
| 73 | revert hmem |
| 74 | refine e'.ind ?_ |
| 75 | intro a b hab |
| 76 | exact show G'.Adj a b by exact hsub hab |
| 77 | simpa [p] using (m.edgePath_isPath e).transfer hedge |
| 78 | edgePath_length := by |
| 79 | intro e |
| 80 | let p := m.edgePath e |
| 81 | have hedge : ∀ e' ∈ p.edges, e' ∈ G'.edgeSet := by |
| 82 | intro e' he' |
| 83 | have hmem := SimpleGraph.Walk.edges_subset_edgeSet p he' |
| 84 | revert hmem |
| 85 | refine e'.ind ?_ |
| 86 | intro a b hab |
| 87 | exact show G'.Adj a b by exact hsub hab |
| 88 | rw [show ((p.transfer G' hedge)).length = p.length by |
| 89 | rw [SimpleGraph.Walk.length_transfer]] |
| 90 | exact m.edgePath_length e |
| 91 | edgePath_interior_avoids_branch := by |
| 92 | intro e x hx htail hhead w |
| 93 | let p := m.edgePath e |
| 94 | have hedge : ∀ e' ∈ p.edges, e' ∈ G'.edgeSet := by |
| 95 | intro e' he' |
| 96 | have hmem := SimpleGraph.Walk.edges_subset_edgeSet p he' |
| 97 | revert hmem |
| 98 | refine e'.ind ?_ |
| 99 | intro a b hab |
| 100 | exact show G'.Adj a b by exact hsub hab |
| 101 | rw [show (p.transfer G' hedge).support = p.support by |
| 102 | rw [SimpleGraph.Walk.support_transfer]] at hx |
| 103 | exact m.edgePath_interior_avoids_branch e hx htail hhead w |
| 104 | edgePath_interior_disjoint := by |
| 105 | intro e e' x hne hx hx' htail hhead htail' hhead' |
| 106 | let p := m.edgePath e |
| 107 | let p' := m.edgePath e' |
| 108 | have hedge : ∀ e'' ∈ p.edges, e'' ∈ G'.edgeSet := by |
| 109 | intro e'' he'' |
| 110 | have hmem := SimpleGraph.Walk.edges_subset_edgeSet p he'' |
| 111 | revert hmem |
| 112 | refine e''.ind ?_ |
| 113 | intro a b hab |
| 114 | exact show G'.Adj a b by exact hsub hab |
| 115 | have hedge' : ∀ e'' ∈ p'.edges, e'' ∈ G'.edgeSet := by |
| 116 | intro e'' he'' |
| 117 | have hmem := SimpleGraph.Walk.edges_subset_edgeSet p' he'' |
| 118 | revert hmem |
| 119 | refine e''.ind ?_ |
| 120 | intro a b hab |
| 121 | exact show G'.Adj a b by exact hsub hab |
| 122 | rw [show (p.transfer G' hedge).support = p.support by |
| 123 | rw [SimpleGraph.Walk.support_transfer]] at hx |
| 124 | rw [show (p'.transfer G' hedge').support = p'.support by |
| 125 | rw [SimpleGraph.Walk.support_transfer]] at hx' |
| 126 | exact m.edgePath_interior_disjoint e e' hne hx hx' htail hhead htail' hhead' } |
| 127 | |
| 128 | theorem shallowTopologicalMinor_of_subgraph |
| 129 | {V W : Type} {H : SimpleGraph W} {G G' : SimpleGraph V} {d : ℕ} |
| 130 | (hsub : ∀ {u v}, G.Adj u v → G'.Adj u v) : |
| 131 | IsShallowTopologicalMinor H G d → IsShallowTopologicalMinor H G' d := by |
| 132 | rintro ⟨m⟩ |
| 133 | exact ⟨m.ofSubgraph hsub⟩ |
| 134 | |
| 135 | private def routedPathSplit {V : Type} {G : SimpleGraph V} {u v : V} |
| 136 | (p : G.Walk u v) (d : ℕ) : ℕ := |
| 137 | min d (p.length - 1) |
| 138 | |
| 139 | private def routedPrefixVertices {V : Type} {G : SimpleGraph V} {u v : V} |
| 140 | (p : G.Walk u v) (d : ℕ) : Set V := |
| 141 | {x | ∃ i ≤ routedPathSplit p d, x = p.getVert i} |
| 142 | |
| 143 | private def routedSuffixVertices {V : Type} {G : SimpleGraph V} {u v : V} |
| 144 | (p : G.Walk u v) (d : ℕ) : Set V := |
| 145 | {x | ∃ i, routedPathSplit p d + 1 ≤ i ∧ i ≤ p.length ∧ x = p.getVert i} |
| 146 | |
| 147 | private def topologicalBranchSet {V W : Type} |
| 148 | {H : SimpleGraph W} {G : SimpleGraph V} {d : ℕ} |
| 149 | (m : ShallowTopologicalMinorModel H G d) (w : W) : Set V := |
| 150 | {x | x = m.branchVertex w ∨ |
| 151 | ∃ e : H.edgeSet, |
| 152 | (m.edgeTail e = w ∧ x ∈ routedPrefixVertices (m.edgePath e) d) ∨ |
| 153 | (Sym2.Mem.other (m.edgeTail_mem e) = w ∧ x ∈ routedSuffixVertices (m.edgePath e) d)} |
| 154 | |
| 155 | private theorem mem_topologicalBranchSet_center |
| 156 | {V W : Type} {H : SimpleGraph W} {G : SimpleGraph V} {d : ℕ} |
| 157 | (m : ShallowTopologicalMinorModel H G d) (w : W) : |
| 158 | m.branchVertex w ∈ topologicalBranchSet m w := by |
| 159 | left |
| 160 | rfl |
| 161 | |
| 162 | private theorem edgePath_internal_not_branchVertex |
| 163 | {V W : Type} {H : SimpleGraph W} {G : SimpleGraph V} {d : ℕ} |
| 164 | (m : ShallowTopologicalMinorModel H G d) (e : H.edgeSet) {i : ℕ} |
| 165 | (hi0 : 0 < i) (hil : i < (m.edgePath e).length) : |
| 166 | ∀ w : W, (m.edgePath e).getVert i ≠ m.branchVertex w := by |
| 167 | intro w |
| 168 | have hp := m.edgePath_isPath e |
| 169 | have hne_tail : (m.edgePath e).getVert i ≠ m.branchVertex (m.edgeTail e) := by |
| 170 | intro hEq |
| 171 | have hi_eq : i = 0 := (hp.getVert_eq_start_iff hil.le).mp (by simpa using hEq) |
| 172 | omega |
| 173 | have hne_head : (m.edgePath e).getVert i ≠ |
| 174 | m.branchVertex (Sym2.Mem.other (m.edgeTail_mem e)) := by |
| 175 | intro hEq |
| 176 | have hi_eq : i = (m.edgePath e).length := |
| 177 | (hp.getVert_eq_end_iff hil.le).mp (by simpa using hEq) |
| 178 | omega |
| 179 | exact m.edgePath_interior_avoids_branch e ((m.edgePath e).getVert_mem_support i) |
| 180 | hne_tail hne_head w |
| 181 | |
| 182 | private theorem mem_topologicalBranchSet_noncenter |
| 183 | {V W : Type} {H : SimpleGraph W} {G : SimpleGraph V} {d : ℕ} |
| 184 | (m : ShallowTopologicalMinorModel H G d) {w : W} {x : V} |
| 185 | (hx : x ∈ topologicalBranchSet m w) (hxc : x ≠ m.branchVertex w) : |
| 186 | ∃ e : H.edgeSet, ∃ i : ℕ, |
| 187 | x = (m.edgePath e).getVert i ∧ |
| 188 | 0 < i ∧ i < (m.edgePath e).length ∧ |
| 189 | ((m.edgeTail e = w ∧ i ≤ routedPathSplit (m.edgePath e) d) ∨ |
| 190 | (Sym2.Mem.other (m.edgeTail_mem e) = w ∧ |
| 191 | routedPathSplit (m.edgePath e) d + 1 ≤ i)) := by |
| 192 | rcases hx with rfl | ⟨e, hx⟩ |
| 193 | · exact (hxc rfl).elim |
| 194 | · rcases hx with ⟨hw, hx⟩ | ⟨hw, hx⟩ |
| 195 | · rcases hx with ⟨i, hi, rfl⟩ |
| 196 | have hi_pos : 0 < i := by |
| 197 | by_contra hi0 |
| 198 | apply hxc |
| 199 | have : i = 0 := Nat.eq_zero_of_not_pos hi0 |
| 200 | simpa [hw, this] using (m.edgePath e).getVert_zero |
| 201 | refine ⟨e, i, rfl, hi_pos, ?_, Or.inl ⟨hw, hi⟩⟩ |
| 202 | · have hi' : i ≤ (m.edgePath e).length - 1 := le_trans hi (Nat.min_le_right _ _) |
| 203 | have hlen : 1 < (m.edgePath e).length := by |
| 204 | exact Nat.sub_pos_iff_lt.mp (lt_of_lt_of_le hi_pos hi') |
| 205 | have hsucc : i + 1 ≤ (m.edgePath e).length := |
| 206 | (Nat.le_sub_iff_add_le hlen.le).mp hi' |
| 207 | exact lt_of_lt_of_le (Nat.lt_succ_self i) hsucc |
| 208 | · rcases hx with ⟨i, hi, hilen, rfl⟩ |
| 209 | refine ⟨e, i, rfl, ?_, ?_, Or.inr ⟨hw, hi⟩⟩ |
| 210 | · omega |
| 211 | · by_contra hlt |
| 212 | have hi_eq : i = (m.edgePath e).length := |
| 213 | le_antisymm hilen (Nat.not_lt.mp hlt) |
| 214 | apply hxc |
| 215 | simpa [hw, hi_eq] using (m.edgePath e).getVert_length |
| 216 | |
| 217 | private theorem topologicalBranchSet_disjoint |
| 218 | {V W : Type} {H : SimpleGraph W} {G : SimpleGraph V} {d : ℕ} |
| 219 | (m : ShallowTopologicalMinorModel H G d) : |
| 220 | ∀ u v, u ≠ v → Disjoint (topologicalBranchSet m u) (topologicalBranchSet m v) := by |
| 221 | intro u v huv |
| 222 | refine Set.disjoint_left.mpr ?_ |
| 223 | intro x hxu hxv |
| 224 | by_cases hxu0 : x = m.branchVertex u |
| 225 | · by_cases hxv0 : x = m.branchVertex v |
| 226 | · exact huv (m.branchVertex.injective (hxu0.symm.trans hxv0)) |
| 227 | · obtain ⟨e, i, hxi, hi0, hil, _⟩ := mem_topologicalBranchSet_noncenter m hxv hxv0 |
| 228 | exact (edgePath_internal_not_branchVertex m e hi0 hil u) (hxi.symm.trans hxu0) |
| 229 | · by_cases hxv0 : x = m.branchVertex v |
| 230 | · obtain ⟨e, i, hxi, hi0, hil, _⟩ := mem_topologicalBranchSet_noncenter m hxu hxu0 |
| 231 | exact (edgePath_internal_not_branchVertex m e hi0 hil v) (hxi.symm.trans hxv0) |
| 232 | · obtain ⟨e, i, hxi, hi0, hil, hside_u⟩ := mem_topologicalBranchSet_noncenter m hxu hxu0 |
| 233 | obtain ⟨e', j, hxj, hj0, hjl, hside_v⟩ := mem_topologicalBranchSet_noncenter m hxv hxv0 |
| 234 | by_cases he : e = e' |
| 235 | · subst e' |
| 236 | have hp := m.edgePath_isPath e |
| 237 | have hij : i = j := hp.getVert_injOn (by simp [hil.le]) (by simp [hjl.le]) |
| 238 | (hxi.symm.trans hxj) |
| 239 | rcases hside_u with ⟨hu, hi_le⟩ | ⟨hu, hi_ge⟩ |
| 240 | · rcases hside_v with ⟨hv, hj_le⟩ | ⟨hv, hj_ge⟩ |
| 241 | · exact huv (hu.symm.trans hv) |
| 242 | · have : i < j := by omega |
| 243 | exact this.ne hij |
| 244 | · rcases hside_v with ⟨hv, hj_le⟩ | ⟨hv, hj_ge⟩ |
| 245 | · have : j < i := by omega |
| 246 | exact this.ne hij.symm |
| 247 | · exact huv (hu.symm.trans hv) |
| 248 | · have hx_support : x ∈ (m.edgePath e).support := by |
| 249 | rw [hxi] |
| 250 | exact (m.edgePath e).getVert_mem_support i |
| 251 | have hx_support' : x ∈ (m.edgePath e').support := by |
| 252 | rw [hxj] |
| 253 | exact (m.edgePath e').getVert_mem_support j |
| 254 | have hne_tail : x ≠ m.branchVertex (m.edgeTail e) := by |
| 255 | simpa [hxi] using (edgePath_internal_not_branchVertex m e hi0 hil (m.edgeTail e)) |
| 256 | have hne_head : x ≠ m.branchVertex (Sym2.Mem.other (m.edgeTail_mem e)) := by |
| 257 | simpa [hxi] using |
| 258 | (edgePath_internal_not_branchVertex m e hi0 hil |
| 259 | (Sym2.Mem.other (m.edgeTail_mem e))) |
| 260 | have hne_tail' : x ≠ m.branchVertex (m.edgeTail e') := by |
| 261 | simpa [hxj] using |
| 262 | (edgePath_internal_not_branchVertex m e' hj0 hjl (m.edgeTail e')) |
| 263 | have hne_head' : x ≠ m.branchVertex (Sym2.Mem.other (m.edgeTail_mem e')) := by |
| 264 | simpa [hxj] using |
| 265 | (edgePath_internal_not_branchVertex m e' hj0 hjl |
| 266 | (Sym2.Mem.other (m.edgeTail_mem e'))) |
| 267 | exact m.edgePath_interior_disjoint e e' he hx_support hx_support' |
| 268 | hne_tail hne_head hne_tail' hne_head' |
| 269 | |
| 270 | private theorem topologicalBranchSet_radius |
| 271 | {V W : Type} {H : SimpleGraph W} {G : SimpleGraph V} {d : ℕ} |
| 272 | (m : ShallowTopologicalMinorModel H G d) : |
| 273 | ∀ v x, x ∈ topologicalBranchSet m v → |
| 274 | ∃ p : G.Walk (m.branchVertex v) x, p.IsPath ∧ p.length ≤ d ∧ |
| 275 | ∀ w ∈ p.support, w ∈ topologicalBranchSet m v := by |
| 276 | intro v x hx |
| 277 | rcases hx with rfl | ⟨e, hx⟩ |
| 278 | · refine ⟨SimpleGraph.Walk.nil, by simp, by simp, ?_⟩ |
| 279 | intro w hw |
| 280 | simp at hw |
| 281 | simpa [hw] using mem_topologicalBranchSet_center m v |
| 282 | · rcases hx with ⟨hv, hx⟩ | ⟨hv, hx⟩ |
| 283 | · rcases hx with ⟨i, hi, rfl⟩ |
| 284 | let p := m.edgePath e |
| 285 | have hi_len : i ≤ p.length := by |
| 286 | exact le_trans hi (le_trans (Nat.min_le_right d (p.length - 1)) (Nat.sub_le _ _)) |
| 287 | refine ⟨(p.take i).copy (by simpa [hv]) rfl, ?_, ?_, ?_⟩ |
| 288 | · simpa [p] using (m.edgePath_isPath e).take i |
| 289 | · rw [SimpleGraph.Walk.length_copy, SimpleGraph.Walk.take_length, Nat.min_eq_left hi_len] |
| 290 | exact le_trans hi (Nat.min_le_left d (p.length - 1)) |
| 291 | · intro w hw |
| 292 | have hw' : w ∈ (p.take i).support := by simpa using hw |
| 293 | rcases SimpleGraph.Walk.mem_support_iff_exists_getVert.mp hw' with ⟨j, rfl, hj⟩ |
| 294 | have hj' : j ≤ i := by |
| 295 | rwa [SimpleGraph.Walk.take_length, Nat.min_eq_left hi_len] at hj |
| 296 | right |
| 297 | refine ⟨e, Or.inl ?_⟩ |
| 298 | refine ⟨hv, ⟨j, le_trans hj' hi, ?_⟩⟩ |
| 299 | rw [SimpleGraph.Walk.take_getVert] |
| 300 | simpa [p, Nat.min_eq_right hj'] |
| 301 | · rcases hx with ⟨i, hi_split, hi_len, rfl⟩ |
| 302 | let p := m.edgePath e |
| 303 | have hi_split' : routedPathSplit p d + 1 ≤ i := by simpa [p] using hi_split |
| 304 | have hi_len' : i ≤ p.length := by simpa [p] using hi_len |
| 305 | have hp_len : p.length ≤ 2 * d + 1 := by simpa [p] using m.edgePath_length e |
| 306 | have hdrop_len : p.length - i ≤ d := by |
| 307 | dsimp [routedPathSplit] at hi_split' |
| 308 | by_cases hmin : d ≤ p.length - 1 |
| 309 | · rw [Nat.min_eq_left hmin] at hi_split' |
| 310 | omega |
| 311 | · rw [Nat.min_eq_right (Nat.le_of_not_ge hmin)] at hi_split' |
| 312 | omega |
| 313 | refine ⟨((p.drop i).reverse).copy (by simpa [hv]) rfl, ?_, ?_, ?_⟩ |
| 314 | · simpa [p] using ((m.edgePath_isPath e).drop i).reverse |
| 315 | · rw [SimpleGraph.Walk.length_copy, SimpleGraph.Walk.length_reverse, SimpleGraph.Walk.drop_length] |
| 316 | exact hdrop_len |
| 317 | · intro w hw |
| 318 | have hw' : w ∈ ((p.drop i).reverse).support := by simpa using hw |
| 319 | rw [SimpleGraph.Walk.support_reverse] at hw' |
| 320 | have hw'' : w ∈ (p.drop i).support := List.mem_reverse.mp hw' |
| 321 | rcases SimpleGraph.Walk.mem_support_iff_exists_getVert.mp hw'' with ⟨j, rfl, hj⟩ |
| 322 | have hij : i + j ≤ p.length := by |
| 323 | rw [SimpleGraph.Walk.drop_length] at hj |
| 324 | simpa [Nat.add_comm] using Nat.add_le_of_le_sub hi_len' hj |
| 325 | right |
| 326 | refine ⟨e, Or.inr ?_⟩ |
| 327 | refine ⟨hv, ⟨i + j, le_trans hi_split' (Nat.le_add_right _ _), hij, ?_⟩⟩ |
| 328 | rw [SimpleGraph.Walk.drop_getVert] |
| 329 | |
| 330 | private theorem topologicalBranchSet_edge |
| 331 | {V W : Type} {H : SimpleGraph W} {G : SimpleGraph V} {d : ℕ} |
| 332 | (m : ShallowTopologicalMinorModel H G d) : |
| 333 | ∀ u v, H.Adj u v → |
| 334 | ∃ x ∈ topologicalBranchSet m u, ∃ y ∈ topologicalBranchSet m v, G.Adj x y := by |
| 335 | intro u v huv |
| 336 | let e : H.edgeSet := ⟨s(u, v), huv⟩ |
| 337 | let p := m.edgePath e |
| 338 | let s := routedPathSplit p d |
| 339 | have htail_mem : m.edgeTail e ∈ (e : Sym2 W) := m.edgeTail_mem e |
| 340 | have hother_ne : Sym2.Mem.other htail_mem ≠ m.edgeTail e := |
| 341 | H.edge_other_ne e.property htail_mem |
| 342 | have hp_not_nil : ¬ p.Nil := by |
| 343 | apply SimpleGraph.Walk.not_nil_of_ne |
| 344 | intro hEq |
| 345 | exact hother_ne (m.branchVertex.injective hEq.symm) |
| 346 | have hs_lt : s < p.length := by |
| 347 | have hp_pos : 0 < p.length := SimpleGraph.Walk.not_nil_iff_lt_length.mp hp_not_nil |
| 348 | dsimp [s, routedPathSplit] |
| 349 | exact lt_of_le_of_lt (Nat.min_le_right _ _) (Nat.sub_lt hp_pos (by decide)) |
| 350 | have htail_cases : m.edgeTail e = u ∨ m.edgeTail e = v := by |
| 351 | simpa [e] using htail_mem |
| 352 | rcases htail_cases with htail_u | htail_v |
| 353 | · have hother_v : Sym2.Mem.other htail_mem = v := by |
| 354 | have hmem : Sym2.Mem.other htail_mem ∈ (e : Sym2 W) := Sym2.other_mem htail_mem |
| 355 | have hne : Sym2.Mem.other htail_mem ≠ u := by simpa [htail_u] using hother_ne |
| 356 | have hmem' : Sym2.Mem.other htail_mem = u ∨ Sym2.Mem.other htail_mem = v := by |
| 357 | simpa [e] using hmem |
| 358 | exact hmem'.resolve_left hne |
| 359 | refine ⟨p.getVert s, ?_, p.getVert (s + 1), ?_, p.adj_getVert_succ hs_lt⟩ |
| 360 | · right |
| 361 | refine ⟨e, Or.inl ?_⟩ |
| 362 | refine ⟨htail_u, ?_⟩ |
| 363 | exact ⟨s, le_rfl, rfl⟩ |
| 364 | · right |
| 365 | refine ⟨e, Or.inr ?_⟩ |
| 366 | refine ⟨hother_v, ?_⟩ |
| 367 | exact ⟨s + 1, le_rfl, Nat.succ_le_of_lt hs_lt, rfl⟩ |
| 368 | · have hother_u : Sym2.Mem.other htail_mem = u := by |
| 369 | have hmem : Sym2.Mem.other htail_mem ∈ (e : Sym2 W) := Sym2.other_mem htail_mem |
| 370 | have hne : Sym2.Mem.other htail_mem ≠ v := by simpa [htail_v] using hother_ne |
| 371 | have hmem' : Sym2.Mem.other htail_mem = u ∨ Sym2.Mem.other htail_mem = v := by |
| 372 | simpa [e] using hmem |
| 373 | exact hmem'.resolve_right hne |
| 374 | refine ⟨p.getVert (s + 1), ?_, p.getVert s, ?_, (p.adj_getVert_succ hs_lt).symm⟩ |
| 375 | · right |
| 376 | refine ⟨e, Or.inr ?_⟩ |
| 377 | refine ⟨hother_u, ?_⟩ |
| 378 | exact ⟨s + 1, le_rfl, Nat.succ_le_of_lt hs_lt, rfl⟩ |
| 379 | · right |
| 380 | refine ⟨e, Or.inl ?_⟩ |
| 381 | refine ⟨htail_v, ?_⟩ |
| 382 | exact ⟨s, le_rfl, rfl⟩ |
| 383 | |
| 384 | private def ShallowTopologicalMinorModel.toShallowMinorModel |
| 385 | {V W : Type} {H : SimpleGraph W} {G : SimpleGraph V} {d : ℕ} |
| 386 | (m : ShallowTopologicalMinorModel H G d) : ShallowMinorModel H G d := |
| 387 | { branchSet := topologicalBranchSet m |
| 388 | center := m.branchVertex |
| 389 | center_mem := mem_topologicalBranchSet_center m |
| 390 | branchDisjoint := topologicalBranchSet_disjoint m |
| 391 | branchRadius := topologicalBranchSet_radius m |
| 392 | branchEdge := topologicalBranchSet_edge m } |
| 393 | |
| 394 | /-- Every depth-`d` shallow topological minor is a depth-`d` shallow minor. -/ |
| 395 | theorem shallowTopologicalMinor_toShallowMinor |
| 396 | {V W : Type} {H : SimpleGraph W} {G : SimpleGraph V} {d : ℕ} : |
| 397 | IsShallowTopologicalMinor H G d → IsShallowMinor H G d := by |
| 398 | rintro ⟨m⟩ |
| 399 | exact ⟨m.toShallowMinorModel⟩ |
| 400 | |
| 401 | end Catalog.Sparsity.ShallowTopologicalMinor |
| 402 |