CubicPathwidth.T2.ReductionPieces

Source file CubicPathwidth/T2/ReductionPieces.lean of the Lean project (how it is built).

import CubicPathwidth.CoreLifting

/-!
# Pieces removed by degree-at-most-two reductions have small pathwidth

`Piece G T A` records how a vertex set `T` was removed by reductions while
attached to the vertex set `A`. It is a rooted tree decomposition with bags of
at most three vertices: a `node` bag is `insert v A`, and its subtree `T`
hangs from that bag. From this structure we extract, for every subset `S` of
the piece, a balanced separator of at most three vertices. Recursive balanced
separators give a section decomposition of width at most `12 * √|T|`.
-/

noncomputable section
namespace CubicPathwidth
namespace T2
open SectionDecomposition

variable {n : ℕ} (G : SimpleGraph (Fin n))

/-- A rooted tree decomposition of width at most two, hanging from `A`. -/
inductive Piece : Finset (Fin n) → Finset (Fin n) → Prop
  | empty (A : Finset (Fin n)) : Piece ∅ A
  | union {T₁ T₂ A : Finset (Fin n)} : Piece T₁ A → Piece T₂ A → Piece (T₁ ∪ T₂) A
  | node {v : Fin n} {T A : Finset (Fin n)} : (insert v A).card ≤ 3 →
      (∀ u, G.Adj v u → u ∈ T ∨ u ∈ A) → Piece T (insert v A) → Piece (insert v T) A
  | mono {T A A' : Finset (Fin n)} : Piece T A → A ⊆ A' → Piece T A'

variable {G}

/-- Every edge leaving a piece ends in its attachment set. -/
theorem Piece.edges {T A : Finset (Fin n)} (h : Piece G T A) :
    ∀ u ∈ T, ∀ w, G.Adj u w → w ∈ T ∨ w ∈ A := by
  induction h with
  | empty A => intro u hu; simp at hu
  | union _ _ ih₁ ih₂ =>
    intro u hu w hw
    rcases Finset.mem_union.mp hu with hu | hu
    · rcases ih₁ u hu w hw with h | h
      · exact Or.inl (Finset.mem_union_left _ h)
      · exact Or.inr h
    · rcases ih₂ u hu w hw with h | h
      · exact Or.inl (Finset.mem_union_right _ h)
      · exact Or.inr h
  | @node v T A _ hv _ ih =>
    intro u hu w hw
    rcases Finset.mem_insert.mp hu with rfl | hu
    · rcases hv w hw with h | h
      · exact Or.inl (Finset.mem_insert_of_mem h)
      · exact Or.inr h
    · rcases ih u hu w hw with h | h
      · exact Or.inl (Finset.mem_insert_of_mem h)
      · rcases Finset.mem_insert.mp h with rfl | h
        · exact Or.inl (Finset.mem_insert_self _ _)
        · exact Or.inr h
  | mono _ hAA' ih =>
    intro u hu w hw
    rcases ih u hu w hw with h | h
    · exact Or.inl h
    · exact Or.inr (hAA' h)

variable (G) in

/-- A finite union of pieces with a common attachment set is a piece. -/
theorem Piece.biUnion (A : Finset (Fin n)) (𝒯 : Finset (Finset (Fin n)))
    (h : ∀ T ∈ 𝒯, Piece G T A) : Piece G (𝒯.biUnion id) A := by
  classical
  induction 𝒯 using Finset.induction_on with
  | empty => simpa using Piece.empty (G := G) A
  | @insert T 𝒯 _ ih =>
    rw [Finset.biUnion_insert]
    exact Piece.union (h T (Finset.mem_insert_self _ _))
      (ih fun S hS => h S (Finset.mem_insert_of_mem hS))

variable (G) in

/-- A connected component of `S \ X` cannot leave a region whose outgoing
edges all end in `Y`, when `Y ∩ S ⊆ X`. -/
theorem component_region {S X R Y C : Finset (Fin n)}
    (hR : ∀ u ∈ R, ∀ w, G.Adj u w → w ∈ R ∨ w ∈ Y)
    (hY : ∀ w ∈ Y, w ∈ S → w ∈ X) (hC : C ∈ components G (S \ X)) :
    C ⊆ R ∨ Disjoint C R := by
  classical
  obtain ⟨hCU, _, hconn⟩ := mem_components G hC
  have hclosed : ClosedIn G (S \ X) (R ∩ (S \ X)) := by
    intro u hu w hw hadj
    obtain ⟨huR, _⟩ := Finset.mem_inter.mp hu
    refine Finset.mem_inter.mpr ⟨?_, hw⟩
    rcases hR u huR w hadj with h | h
    · exact h
    · exact False.elim ((Finset.mem_sdiff.mp hw).2 (hY w h (Finset.mem_sdiff.mp hw).1))
  rcases connected_subset_or_disjoint G hCU hconn hclosed with h | h
  · exact Or.inl (h.trans Finset.inter_subset_left)
  · right
    apply Finset.disjoint_left.mpr
    intro u huC huR
    exact Finset.disjoint_left.mp h huC (Finset.mem_inter.mpr ⟨huR, hCU huC⟩)

theorem card_inter_of_sdiff {S T : Finset (Fin n)} (h : S.card < 2 * (S \ T).card) :
    2 * (S ∩ T).card < S.card := by
  have := Finset.card_sdiff_add_card_inter S T
  omega

/-- Balanced separators of at most three vertices inside a piece. -/
theorem Piece.separator {T A : Finset (Fin n)} (h : Piece G T A) (hA : A.card ≤ 3) :
    ∀ S : Finset (Fin n), 2 * (S \ T).card ≤ S.card →
      ∃ X ⊆ S, X.card ≤ 3 ∧ ∀ C ∈ components G (S \ X), 2 * C.card ≤ S.card := by
  classical
  induction h with
  | empty A =>
    intro S hS
    refine ⟨∅, Finset.empty_subset _, by simp, ?_⟩
    intro C hC
    have hCS : C ⊆ S := (mem_components G hC).1.trans Finset.sdiff_subset
    have h1 := Finset.card_le_card hCS
    simp only [Finset.sdiff_empty] at hS
    omega
  | @union T₁ T₂ A h₁ h₂ ih₁ ih₂ =>
    intro S hS
    by_cases hS₁ : 2 * (S \ T₁).card ≤ S.card
    · exact ih₁ hA S hS₁
    by_cases hS₂ : 2 * (S \ T₂).card ≤ S.card
    · exact ih₂ hA S hS₂
    have hi₁ := card_inter_of_sdiff (by omega : S.card < 2 * (S \ T₁).card)
    have hi₂ := card_inter_of_sdiff (by omega : S.card < 2 * (S \ T₂).card)
    refine ⟨A ∩ S, Finset.inter_subset_right,
      (Finset.card_le_card Finset.inter_subset_left).trans hA, ?_⟩
    intro C hC
    have hY : ∀ w ∈ A, w ∈ S → w ∈ A ∩ S := fun w hw hwS => Finset.mem_inter.mpr ⟨hw, hwS⟩
    have hCS : C ⊆ S := (mem_components G hC).1.trans Finset.sdiff_subset
    rcases component_region G h₁.edges hY hC with hc₁ | hd₁
    · have := Finset.card_le_card (Finset.subset_inter hCS hc₁)
      omega
    rcases component_region G h₂.edges hY hC with hc₂ | hd₂
    · have := Finset.card_le_card (Finset.subset_inter hCS hc₂)
      omega
    have hsub : C ⊆ S \ (T₁ ∪ T₂) := by
      intro u hu
      refine Finset.mem_sdiff.mpr ⟨hCS hu, ?_⟩
      rw [Finset.mem_union, not_or]
      exact ⟨Finset.disjoint_left.mp hd₁ hu, Finset.disjoint_left.mp hd₂ hu⟩
    have := Finset.card_le_card hsub
    omega
  | @node v T A hcard hv hT ih =>
    intro S hS
    by_cases hS' : 2 * (S \ T).card ≤ S.card
    · exact ih hcard S hS'
    have hi := card_inter_of_sdiff (by omega : S.card < 2 * (S \ T).card)
    refine ⟨insert v A ∩ S, Finset.inter_subset_right,
      (Finset.card_le_card Finset.inter_subset_left).trans hcard, ?_⟩
    intro C hC
    have hY : ∀ w ∈ insert v A, w ∈ S → w ∈ insert v A ∩ S :=
      fun w hw hwS => Finset.mem_inter.mpr ⟨hw, hwS⟩
    have hCU := (mem_components G hC).1
    have hCS : C ⊆ S := hCU.trans Finset.sdiff_subset
    rcases component_region G hT.edges hY hC with hc | hd
    · have := Finset.card_le_card (Finset.subset_inter hCS hc)
      omega
    have hsub : C ⊆ S \ insert v T := by
      intro u hu
      refine Finset.mem_sdiff.mpr ⟨hCS hu, ?_⟩
      intro hmem
      rcases Finset.mem_insert.mp hmem with rfl | hmem
      · exact (Finset.mem_sdiff.mp (hCU hu)).2
          (Finset.mem_inter.mpr ⟨Finset.mem_insert_self _ _, hCS hu⟩)
      · exact Finset.disjoint_left.mp hd hu hmem
    have := Finset.card_le_card hsub
    omega
  | @mono T A A' _ hAA' ih =>
    intro S hS
    exact ih ((Finset.card_le_card hAA').trans hA) S hS

variable (G) in

/-- Recursive balanced separators of at most three vertices give width
`O(√|U|)`. -/
theorem separator_section_decomposition (U : Finset (Fin n))
    (hsep : ∀ S ⊆ U, ∃ X ⊆ S, X.card ≤ 3 ∧
      ∀ C ∈ components G (S \ X), 2 * C.card ≤ S.card) :
    ∃ P : SectionDecomposition G U,
      P.toBagPath.WidthAtMost (12 * Real.sqrt (U.card : ℝ)) := by
  have go : ∀ m : ℕ, ∀ S : Finset (Fin n), S.card = m → S ⊆ U →
      ∃ P : SectionDecomposition G S,
        P.toBagPath.WidthAtMost (12 * Real.sqrt (S.card : ℝ)) := by
    intro m
    induction m using Nat.strong_induction_on with
    | h m ih =>
      intro S hm hSU
      obtain ⟨X, hXS, hX, hbal⟩ := hsep S hSU
      have hroot := Real.sqrt_nonneg (S.card : ℝ)
      obtain ⟨P, hP⟩ := section_of_components G (S \ X)
        (show -1 ≤ 9 * Real.sqrt (S.card : ℝ) by linarith) (by
          intro C hC
          have hc := hbal C hC
          have hne := Finset.card_pos.mpr (mem_components G hC).2.2.1
          have hlt : C.card < m := by omega
          have hCS : C ⊆ U := (mem_components G hC).1.trans (Finset.sdiff_subset.trans hSU)
          obtain ⟨Q, hQ⟩ := ih _ hlt C rfl hCS
          refine ⟨Q, hQ.mono ?_⟩
          have := sqrt_half_bound hc
          linarith)
      have hwidth := (hold_width P X hP).mono
        (show 9 * Real.sqrt (S.card : ℝ) + (X.card : ℝ) ≤ 12 * Real.sqrt (S.card : ℝ) by
          by_cases hS : S.Nonempty
          · have h1 : (1 : ℝ) ≤ Real.sqrt (S.card : ℝ) := by
              have : (1 : ℝ) ≤ S.card := by exact_mod_cast Finset.card_pos.mpr hS
              simpa using Real.sqrt_le_sqrt this
            have : (X.card : ℝ) ≤ 3 := by exact_mod_cast hX
            linarith
          · have hS0 : S = ∅ := Finset.not_nonempty_iff_eq_empty.mp hS
            subst hS0
            have hX0 : X = ∅ := Finset.subset_empty.mp hXS
            subst hX0
            simp)
      have heq : (S \ X) ∪ X = S := Finset.sdiff_union_of_subset hXS
      have h : ∃ Q : SectionDecomposition G ((S \ X) ∪ X),
          Q.toBagPath.WidthAtMost (12 * Real.sqrt (S.card : ℝ)) := ⟨P.hold X, hwidth⟩
      rw [heq] at h
      exact h
  exact go _ U rfl Finset.Subset.rfl

/-- Every piece hanging from at most three vertices has width `O(√|T|)`. -/
theorem Piece.section_decomposition {T A : Finset (Fin n)} (h : Piece G T A)
    (hA : A.card ≤ 3) :
    ∃ P : SectionDecomposition G T,
      P.toBagPath.WidthAtMost (12 * Real.sqrt (T.card : ℝ)) := by
  apply separator_section_decomposition G T
  intro S hS
  apply h.separator hA S
  rw [Finset.sdiff_eq_empty_iff_subset.mpr hS]
  simp

end T2
end CubicPathwidth
Back to top