CubicPathwidth.T2.Reduction
Source file CubicPathwidth/T2/Reduction.lean of the Lean project (how it is built).
import CubicPathwidth.T2.DefsB
import CubicPathwidth.T2.ReductionPieces
/-!
# Reductions: vertices of degree at most two cost `o(n)` in pathwidth
Plan (written before the proof; route actually used).
The reductions (R1)–(R4) are not simulated step by step. A reduced graph is
encoded by its vertex set `B ⊆ V(G)` and the existing torso `coreTorso G univ B`
(from `CoreTorso.lean`): `G`-edges inside `B`, plus an edge between the two
attachments of each component of `V \ B`. A set `B` is a `GoodCore` when every
component `T` of `V \ B` has at most two attachment vertices and carries a
`Piece` structure (`ReductionPieces.lean`): a rooted tree decomposition with
bags of at most three vertices recording how `T` was removed.
1. `goodCore_univ`: `B = V` is good (no components).
2. `goodCore_erase`: if `B` is good and a torso vertex `v` has torso degree at
most two, then `B.erase v` is good. The new component through `v` is `v`
plus the old components attached to `v`; its attachment is contained in the
torso neighbourhood of `v`. This is one reduction (R1)–(R4).
3. `exists_minimal_core`: a good `B` of minimum size has a torso of minimum
degree at least three.
4. `torso_degree_le` (as in `coreTorso_subcubic`): torso degrees are at most
the `G`-degrees. Hence maximum degree at most four, and
`degreeCount_transfer`: `a₃ n₃(R) + a₄ n₄(R) ≤ a₃ n₃(G) + a₄ n₄(G)` when
`0 ≤ a₃ ≤ a₄`.
5. `Piece.section_decomposition`: every piece has a section decomposition of
width at most `12 √|T|` (balanced separators of size three, recursively).
6. Lifting: `liftTorso`, `torso_attachment_bag` and `insert_components`
(`CoreLifting.lean`, "every old bag survives unchanged") give
`pw(G) ≤ pw(R) + 12 √n + 1`.
7. Assembly: if `|B| ≥ N₁` use `MinDegThreeBound` at `ε/2`; otherwise use the
trivial bound `|B| - 1 < N₁`. The overhead `N₁ + 12 √n + 1` is at most
`(ε/2) n` for large `n` (`coreOverhead_sublinear`).
-/
noncomputable section
namespace CubicPathwidth
namespace T2
open SectionDecomposition
variable {n : ℕ} (G : SimpleGraph (Fin n))
/-- A reduced vertex set: the removed components have at most two attachments
and were removed by reductions. -/
def GoodCore (B : Finset (Fin n)) : Prop :=
∀ T ∈ components G (Finset.univ \ B),
(attachment G B T).card ≤ 2 ∧ Piece G T (attachment G B T)
theorem mem_components_of_mem {U : Finset (Fin n)} {u : Fin n} (hu : u ∈ U) :
component G U u ∈ components G U := by
classical
unfold components
exact Finset.mem_image.mpr ⟨u, hu, rfl⟩
theorem goodCore_univ : GoodCore G Finset.univ := by
classical
intro T hT
have hT' := (mem_components G hT).2.2.1
obtain ⟨u, hu⟩ := hT'
have := (mem_components G hT).1 hu
simp at this
open Classical in
/-- Torso degrees are bounded by the original degrees. -/
theorem torso_degree_le (F B : Finset (Fin n))
(hattach : ∀ T ∈ components G (F \ B), (attachment G B T).card ≤ 2)
(i : Fin B.card) : (coreTorso G F B).degree i ≤ G.degree (enumerate B i) := by
let K := coreTorso G F B
have hw : ∀ j : K.neighborFinset i, ∃ w : G.neighborFinset (enumerate B i),
((w : Fin n) = enumerate B j ∨ ∃ T ∈ components G (F \ B),
(w : Fin n) ∈ T ∧ enumerate B i ∈ attachment G B T ∧
enumerate B j ∈ attachment G B T) := by
intro j
obtain ⟨w, hadj, hr⟩ := torso_edge_witness G ((K.mem_neighborFinset _ _).mp j.property)
exact ⟨⟨w, (G.mem_neighborFinset _ _).mpr hadj⟩, hr⟩
choose f hf using hw
have hinj : Function.Injective f := by
intro j k he
have hwval := congrArg Subtype.val he
have hij : enumerate B i ≠ enumerate B j :=
fun h => ((K.mem_neighborFinset _ _).mp j.property).1 ((enumerate B).injective h)
have hik : enumerate B i ≠ enumerate B k :=
fun h => ((K.mem_neighborFinset _ _).mp k.property).1 ((enumerate B).injective h)
apply Subtype.ext
apply (enumerate B).injective
rcases hf j with hj | ⟨S, hS, hwS, hiS, hjS⟩ <;>
rcases hf k with hk | ⟨T, hT, hwT, hiT, hkT⟩
· exact hj.symm.trans (hwval.trans hk)
· have hwB : (f k : Fin n) ∈ B := by
rw [← hwval, hj]
exact (mem_iff_enumerate B _).mpr ⟨j, rfl⟩
exact False.elim ((Finset.mem_sdiff.mp ((mem_components G hT).1 hwT)).2 hwB)
· have hwB : (f j : Fin n) ∈ B := by
rw [hwval, hk]
exact (mem_iff_enumerate B _).mpr ⟨k, rfl⟩
exact False.elim ((Finset.mem_sdiff.mp ((mem_components G hS).1 hwS)).2 hwB)
· have hST : S = T := by
by_contra hne
exact Finset.disjoint_left.mp (components_disjoint G hS hT hne) hwS (hwval.symm ▸ hwT)
subst T
exact two_attachment_unique (hattach S hS) hiS hjS hkT hij hik
have hc := Fintype.card_le_of_injective f hinj
have hc' : (K.neighborFinset i).card ≤ (G.neighborFinset (enumerate B i)).card := by
simpa only [Fintype.card_coe] using hc
exact hc'
open Classical in
/-- One reduction step: a torso vertex of degree at most two can be removed. -/
theorem goodCore_erase {B : Finset (Fin n)} (hB : GoodCore G B) {i : Fin B.card}
(hdeg : (coreTorso G Finset.univ B).degree i ≤ 2) :
GoodCore G (B.erase (enumerate B i)) := by
obtain ⟨v, hv⟩ : ∃ v, enumerate B i = v := ⟨_, rfl⟩
rw [hv]
have hvB : v ∈ B := (mem_iff_enumerate B v).mpr ⟨i, hv⟩
have hmemU : ∀ u, u ∈ Finset.univ \ B ↔ u ∉ B := by simp
have hmemU' : ∀ u, u ∈ Finset.univ \ B.erase v ↔ u = v ∨ u ∉ B := by
intro u
simp only [Finset.mem_sdiff, Finset.mem_univ, true_and, Finset.mem_erase, not_and_or,
not_not, ne_eq]
have hUU' : Finset.univ \ B ⊆ Finset.univ \ B.erase v := by
intro u hu
exact (hmemU' u).mpr (Or.inr ((hmemU u).mp hu))
intro T' hT'
obtain ⟨hT'U', hT'cl, hT'conn⟩ := mem_components G hT'
have hcomp : ∀ u ∈ T', u ∈ Finset.univ \ B → component G (Finset.univ \ B) u ⊆ T' := by
intro u huT hu
rcases connected_subset_or_disjoint G ((component_subset G _ u).trans hUU')
(component_connected G hu) hT'cl with h | h
· exact h
· exact False.elim (Finset.disjoint_left.mp h (mem_component_self G hu) huT)
by_cases hvT : v ∈ T'
· have hvA : v ∉ attachment G (B.erase v) T' := by
intro h
have := attachment_subset G _ _ h
simp at this
have hattv : ∀ T ∈ components G (Finset.univ \ B), T ⊆ T' → v ∈ attachment G B T := by
intro T hT hTT'
obtain ⟨hTU, hTcl, hTconn⟩ := mem_components G hT
have hne : T ≠ T' := by
intro h
rw [← h] at hvT
exact (hmemU v).mp (hTU hvT) hvB
obtain ⟨x, hx, y, hy, hxy⟩ := connected_cross_edge G hT'conn hTT' hTconn.1 hne
obtain ⟨hyT', hyT⟩ := Finset.mem_sdiff.mp hy
have hyv : y = v := by
by_contra hyv
have hyU : y ∈ Finset.univ \ B :=
(hmemU y).mpr (((hmemU' y).mp (hT'U' hyT')).resolve_left hyv)
exact hyT (hTcl x hx y hyU hxy)
rw [hyv] at hxy
exact (mem_attachment G).mpr ⟨hvB, x, hx, hxy.symm⟩
have hA'card : (attachment G (B.erase v) T').card ≤ 2 := by
have hsub : attachment G (B.erase v) T' ⊆
((coreTorso G Finset.univ B).neighborFinset i).image (enumerate B) := by
intro a ha
obtain ⟨haB', u, huT', hau⟩ := (mem_attachment G).mp ha
obtain ⟨hav, haB⟩ := Finset.mem_erase.mp haB'
obtain ⟨j, hj⟩ := (mem_iff_enumerate B a).mp haB
refine Finset.mem_image.mpr ⟨j, ?_, hj⟩
rw [SimpleGraph.mem_neighborFinset]
refine ⟨fun hij => hav (by rw [← hj, ← hij, hv]), ?_⟩
by_cases huv : u = v
· left
rw [hv, hj, ← huv]
exact hau.symm
· right
have huU : u ∈ Finset.univ \ B :=
(hmemU u).mpr (((hmemU' u).mp (hT'U' huT')).resolve_left huv)
refine ⟨component G (Finset.univ \ B) u, mem_components_of_mem G huU, ?_, ?_⟩
· rw [hv]
exact hattv _ (mem_components_of_mem G huU) (hcomp u huT' huU)
· rw [hj]
exact (mem_attachment G).mpr ⟨haB, u, mem_component_self G huU, hau⟩
calc (attachment G (B.erase v) T').card
≤ (((coreTorso G Finset.univ B).neighborFinset i).image (enumerate B)).card :=
Finset.card_le_card hsub
_ ≤ ((coreTorso G Finset.univ B).neighborFinset i).card := Finset.card_image_le
_ ≤ 2 := by
rw [SimpleGraph.card_neighborFinset_eq_degree]
exact hdeg
have hsplit : T'.erase v =
((components G (Finset.univ \ B)).filter (· ⊆ T')).biUnion id := by
ext u
constructor
· intro hu
obtain ⟨huv, huT'⟩ := Finset.mem_erase.mp hu
have huU : u ∈ Finset.univ \ B :=
(hmemU u).mpr (((hmemU' u).mp (hT'U' huT')).resolve_left huv)
exact Finset.mem_biUnion.mpr ⟨component G (Finset.univ \ B) u,
Finset.mem_filter.mpr ⟨mem_components_of_mem G huU, hcomp u huT' huU⟩,
mem_component_self G huU⟩
· intro hu
obtain ⟨T, hT, huT⟩ := Finset.mem_biUnion.mp hu
obtain ⟨hTc, hTT'⟩ := Finset.mem_filter.mp hT
refine Finset.mem_erase.mpr ⟨?_, hTT' huT⟩
intro huv
rw [huv] at huT
exact (hmemU v).mp ((mem_components G hTc).1 huT) hvB
have hchild : Piece G (T'.erase v) (insert v (attachment G (B.erase v) T')) := by
rw [hsplit]
apply Piece.biUnion
intro T hT
obtain ⟨hTc, hTT'⟩ := Finset.mem_filter.mp hT
apply Piece.mono (hB T hTc).2
intro w hw
obtain ⟨hwB, x, hxT, hwx⟩ := (mem_attachment G).mp hw
by_cases hwv : w = v
· rw [hwv]
exact Finset.mem_insert_self _ _
· exact Finset.mem_insert_of_mem ((mem_attachment G).mpr
⟨Finset.mem_erase.mpr ⟨hwv, hwB⟩, x, hTT' hxT, hwx⟩)
have hnode := Piece.node (G := G) (v := v) (T := T'.erase v)
(A := attachment G (B.erase v) T')
(by rw [Finset.card_insert_of_notMem hvA]; omega)
(by
intro u hu
by_cases huB : u ∈ B
· right
exact (mem_attachment G).mpr
⟨Finset.mem_erase.mpr ⟨hu.ne.symm, huB⟩, v, hvT, hu.symm⟩
· left
have huU' : u ∈ Finset.univ \ B.erase v := (hmemU' u).mpr (Or.inr huB)
exact Finset.mem_erase.mpr ⟨hu.ne.symm, hT'cl v hvT u huU' hu⟩)
hchild
rw [Finset.insert_erase hvT] at hnode
exact ⟨hA'card, hnode⟩
· have hT'U : T' ⊆ Finset.univ \ B := by
intro u hu
refine (hmemU u).mpr (((hmemU' u).mp (hT'U' hu)).resolve_left ?_)
intro h
rw [h] at hu
exact hvT hu
have hT'cl' : ClosedIn G (Finset.univ \ B) T' :=
fun a ha w hw hadj => hT'cl a ha w (hUU' hw) hadj
have hT'mem : T' ∈ components G (Finset.univ \ B) := by
obtain ⟨u, hu⟩ := hT'conn.1
rw [← component_eq_of_connected G hT'U hT'cl' hT'conn hu]
exact mem_components_of_mem G (hT'U hu)
have hatt : attachment G (B.erase v) T' = attachment G B T' := by
ext w
rw [mem_attachment, mem_attachment]
constructor
· rintro ⟨hw, h⟩
exact ⟨Finset.mem_of_mem_erase hw, h⟩
· rintro ⟨hw, x, hx, hwx⟩
refine ⟨Finset.mem_erase.mpr ⟨?_, hw⟩, x, hx, hwx⟩
intro hwv
rw [hwv] at hwx
exact hvT (hT'cl x hx v ((hmemU' v).mpr (Or.inl rfl)) hwx.symm)
rw [hatt]
exact hB T' hT'mem
open Classical in
/-- A good core of minimum size has a torso of minimum degree at least three. -/
theorem exists_minimal_core : ∃ B : Finset (Fin n), GoodCore G B ∧
∀ i : Fin B.card, 3 ≤ (coreTorso G Finset.univ B).degree i := by
obtain ⟨B, hB, hmin⟩ := Finset.exists_min_image
((Finset.univ : Finset (Finset (Fin n))).filter (GoodCore G)) Finset.card
⟨Finset.univ, Finset.mem_filter.mpr ⟨Finset.mem_univ _, goodCore_univ G⟩⟩
have hgood := (Finset.mem_filter.mp hB).2
refine ⟨B, hgood, ?_⟩
intro i
by_contra h
have hg := goodCore_erase G hgood (i := i) (by omega)
have hle := hmin _ (Finset.mem_filter.mpr ⟨Finset.mem_univ _, hg⟩)
have hvB : enumerate B i ∈ B := (mem_iff_enumerate B _).mpr ⟨i, rfl⟩
have := Finset.card_erase_lt_of_mem hvB
omega
open Classical in
/-- Degree-count transfer along a degree-dominated injection. -/
theorem degreeCount_transfer {m : ℕ} (R : SimpleGraph (Fin m)) (e : Fin m ↪ Fin n)
(hdeg : ∀ i, R.degree i ≤ G.degree (e i)) (hG : MaxDegreeAtMost 4 G)
{a₃ a₄ : ℝ} (h3 : 0 ≤ a₃) (h34 : a₃ ≤ a₄) :
a₃ * (degreeCount R 3 : ℝ) + a₄ * (degreeCount R 4 : ℝ) ≤
a₃ * (degreeCount G 3 : ℝ) + a₄ * (degreeCount G 4 : ℝ) := by
have hG' : ∀ v, G.degree v ≤ 4 := by
intro v
have := hG v
convert this
have h4 : degreeCount R 4 ≤ degreeCount G 4 := by
unfold degreeCount
apply Finset.card_le_card_of_injOn e
· intro i hi
have hi' : R.degree i = 4 := by
have := (Finset.mem_filter.mp hi).2
convert this
have h1 := hdeg i
have h2 := hG' (e i)
simp only [Finset.coe_filter, Finset.mem_univ, true_and]
change G.degree (e i) = 4
omega
· intro i _ j _ hij
exact e.injective hij
have hsum : ∀ {k : ℕ} (H : SimpleGraph (Fin k)),
degreeCount H 3 + degreeCount H 4 =
(Finset.univ.filter fun v => H.degree v = 3 ∨ H.degree v = 4).card := by
intro k H
unfold degreeCount
rw [Finset.filter_or, Finset.card_union_of_disjoint]
exact Finset.disjoint_filter.mpr (fun v _ h3 h4 => by omega)
have h34c : degreeCount R 3 + degreeCount R 4 ≤ degreeCount G 3 + degreeCount G 4 := by
rw [hsum R, hsum G]
apply Finset.card_le_card_of_injOn e
· intro i hi
have hi' := (Finset.mem_filter.mp hi).2
have h1 := hdeg i
have h2 := hG' (e i)
simp only [Finset.coe_filter, Finset.mem_univ, true_and]
change G.degree (e i) = 3 ∨ G.degree (e i) = 4
omega
· intro i _ j _ hij
exact e.injective hij
have c4 : (degreeCount R 4 : ℝ) ≤ degreeCount G 4 := by exact_mod_cast h4
have c34 : (degreeCount R 3 : ℝ) + degreeCount R 4 ≤ degreeCount G 3 + degreeCount G 4 := by
exact_mod_cast h34c
have := mul_le_mul_of_nonneg_left c34 h3
have := mul_le_mul_of_nonneg_left c4 (sub_nonneg.mpr h34)
nlinarith
/-- (B5) Vertices of degree at most two cost `o(n)` in pathwidth. -/
theorem reduction : ReductionClaim := by
intro a₃ a₄ h3 h34 hbound ε hε
obtain ⟨N₁, hN₁⟩ := hbound (ε / 2) (by linarith)
obtain ⟨N₂, hN₂⟩ := coreOverhead_sublinear (ε / 8) (by linarith)
obtain ⟨M, hM⟩ := exists_nat_ge (4 * ((N₁ : ℝ) + 1) / ε)
refine ⟨max N₂ M, ?_⟩
intro n hn G hG
classical
obtain ⟨B, hgood, hmin3⟩ := exists_minimal_core G
have hattach : ∀ T ∈ components G (Finset.univ \ B), (attachment G B T).card ≤ 2 :=
fun T hT => (hgood T hT).1
have hdom := torso_degree_le G Finset.univ B hattach
have hRmin : MinDegreeAtLeast 3 (coreTorso G Finset.univ B) := by
intro i
convert hmin3 i
have hRmax : MaxDegreeAtMost 4 (coreTorso G Finset.univ B) := by
intro i
have h1 := hdom i
have h2 := hG (enumerate B i)
convert h1.trans (by convert h2)
have hcount := degreeCount_transfer G (coreTorso G Finset.univ B) (enumerate B)
(by intro i; convert hdom i) hG h3 h34
have ha4 : 0 ≤ a₄ := h3.trans h34
have hS : 0 ≤ a₃ * (degreeCount G 3 : ℝ) + a₄ * (degreeCount G 4 : ℝ) := by positivity
have hBn : (B.card : ℝ) ≤ n := by
have := Finset.card_le_univ B
simp only [Fintype.card_fin] at this
exact_mod_cast this
have hn0 : (0 : ℝ) ≤ n := Nat.cast_nonneg n
have hRpw : HasPathwidthAtMost (coreTorso G Finset.univ B)
(a₃ * (degreeCount G 3 : ℝ) + a₄ * (degreeCount G 4 : ℝ) + ε / 2 * n + N₁) := by
by_cases hm : N₁ ≤ B.card
· obtain ⟨D, hD⟩ := hN₁ B.card hm _ hRmin hRmax
refine ⟨D, fun i => (hD i).trans ?_⟩
have : ε / 2 * (B.card : ℝ) ≤ ε / 2 * n :=
mul_le_mul_of_nonneg_left hBn (by linarith)
have : (0 : ℝ) ≤ N₁ := Nat.cast_nonneg _
linarith
· obtain ⟨D, hD⟩ := trivial_pathwidth_bound (coreTorso G Finset.univ B)
refine ⟨D, fun i => (hD i).trans ?_⟩
have : (B.card : ℝ) ≤ N₁ := by exact_mod_cast (not_le.mp hm).le
have : 0 ≤ ε / 2 * (n : ℝ) := by positivity
linarith
obtain ⟨D, hD⟩ := hRpw
have hP := liftTorso_width G Finset.univ B D hD
have hpieces : ∀ T ∈ components G (Finset.univ \ B),
∃ Q : SectionDecomposition G T, Q.toBagPath.WidthAtMost (12 * Real.sqrt (n : ℝ)) := by
intro T hT
obtain ⟨Q, hQ⟩ := (hgood T hT).2.section_decomposition (by have := (hgood T hT).1; omega)
have hc : (T.card : ℝ) ≤ n := by
have := Finset.card_le_univ T
simp only [Fintype.card_fin] at this
exact_mod_cast this
exact ⟨Q, hQ.mono (by linarith [Real.sqrt_le_sqrt hc])⟩
obtain ⟨R', hR'⟩ := insert_components G (Finset.subset_univ B) (liftTorso G Finset.univ B D) hP
(by positivity) hpieces
(fun T hT => torso_attachment_bag G Finset.univ B D hT (hattach T hT))
refine ⟨R'.toFull, toFull_width R' (hR'.mono ?_)⟩
have h1 := hN₂ n ((le_max_left _ _).trans hn)
unfold coreOverhead at h1
have hMn : (M : ℝ) ≤ n := by exact_mod_cast (le_max_right _ _).trans hn
have h2 : 4 * ((N₁ : ℝ) + 1) ≤ ε * n := by
have := hM.trans hMn
rw [div_le_iff₀ hε] at this
linarith
have : (0 : ℝ) ≤ Real.sqrt n := Real.sqrt_nonneg _
nlinarith
end T2
end CubicPathwidth
#print axioms CubicPathwidth.T2.reduction
Back to top