CubicPathwidth.CorePieces

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

import CubicPathwidth.PseudotreeDecomposition

/-! Components outside the core's branch vertices have at most two attachments. -/

noncomputable section
namespace CubicPathwidth
variable {n : ℕ} (G : SimpleGraph (Fin n))

def branchVertices (C : Finset (Fin n)) : Finset (Fin n) :=
  C.filter (fun v => (sectionNeighbors G C v).card = 3)

def attachment (B T : Finset (Fin n)) : Finset (Fin n) :=
  T.biUnion (sectionNeighbors G B)

theorem mem_attachment {B T : Finset (Fin n)} {v : Fin n} :
    v ∈ attachment G B T ↔ v ∈ B ∧ ∃ u ∈ T, G.Adj v u := by
  simp only [attachment, Finset.mem_biUnion, mem_sectionNeighbors]
  constructor
  · rintro ⟨u, hu, hv, huv⟩
    exact ⟨hv, u, hu, huv.symm⟩
  · rintro ⟨hv, u, hu, hvu⟩
    exact ⟨u, hu, hv, hvu.symm⟩

theorem attachment_subset (B T : Finset (Fin n)) : attachment G B T ⊆ B :=
  fun _ h => (mem_attachment G).mp h |>.1

theorem attachment_card_le (B T : Finset (Fin n)) :
    (attachment G B T).card ≤ incidence G T B := Finset.card_biUnion_le

theorem incidence_mono_right (U : Finset (Fin n)) {V W : Finset (Fin n)} (h : V ⊆ W) :
    incidence G U V ≤ incidence G U W :=
  Finset.sum_le_sum (fun v _ => Finset.card_le_card (sectionNeighbors_mono G h v))

theorem incidence_insert_left {U V : Finset (Fin n)} {v : Fin n} (hv : v ∉ U) :
    incidence G (insert v U) V = incidence G U V + (sectionNeighbors G V v).card := by
  simp [incidence, Finset.sum_insert hv, Nat.add_comm]

theorem incidence_insert_right {U V : Finset (Fin n)} {v : Fin n} (hv : v ∉ V) :
    incidence G U (insert v V) = incidence G U V + (sectionNeighbors G U v).card := by
  rw [incidence_symm G U, incidence_insert_left G hv, incidence_symm G V U]

/-- Leaf restoration preserves the degree budget on every closed subset
outside a retained set B. The closure condition is essential. -/
theorem LeafPrunes.closed_incidence_le_two {F C B : Finset (Fin n)}
    (hp : LeafPrunes G F C) (hBC : B ⊆ C)
    (hC : ∀ v ∈ C \ B, (sectionNeighbors G C v).card ≤ 2) :
    ∀ S : Finset (Fin n), S ⊆ F \ B → ClosedIn G (F \ B) S →
      incidence G S F ≤ 2 * S.card := by
  classical
  induction hp with
  | refl C =>
    intro S hS _
    calc
      incidence G S C ≤ ∑ _v ∈ S, 2 := Finset.sum_le_sum (fun v hv => hC v (hS hv))
      _ = _ := by simp [Nat.mul_comm]
  | @step U C v hv hdeg rest ih =>
    intro S hS hclosed
    have hBU : B ⊆ U.erase v := hBC.trans (LeafPrunes.subset G rest)
    have hvB : v ∉ B := fun h => Finset.notMem_erase v U (hBU h)
    have hinsert : insert v (U.erase v) = U := Finset.insert_erase hv
    by_cases hvS : v ∈ S
    · have hsub : S.erase v ⊆ (U.erase v) \ B := by
        intro u hu
        obtain ⟨huv, huS⟩ := Finset.mem_erase.mp hu
        obtain ⟨huU, huB⟩ := Finset.mem_sdiff.mp (hS huS)
        exact Finset.mem_sdiff.mpr ⟨Finset.mem_erase.mpr ⟨huv, huU⟩, huB⟩
      have hc : ClosedIn G ((U.erase v) \ B) (S.erase v) := by
        intro u hu w hw hadj
        have hwU := Finset.mem_sdiff.mp hw
        exact Finset.mem_erase.mpr ⟨(Finset.mem_erase.mp hwU.1).1,
          hclosed u (Finset.mem_of_mem_erase hu) w
            (Finset.mem_sdiff.mpr ⟨Finset.mem_of_mem_erase hwU.1, hwU.2⟩) hadj⟩
      have hrec := ih hBC hC (S.erase v) hsub hc
      have hin := incidence_insert_left G (V := U) (Finset.notMem_erase v S)
      rw [Finset.insert_erase hvS, hdeg] at hin
      have hin' := incidence_insert_right G (U := S.erase v) (Finset.notMem_erase v U)
      rw [hinsert] at hin'
      have hd : (sectionNeighbors G (S.erase v) v).card ≤ 1 :=
        (Finset.card_le_card (sectionNeighbors_mono G
          ((Finset.erase_subset v S).trans (hS.trans Finset.sdiff_subset)) v)).trans hdeg.le
      have hcard := Finset.card_erase_add_one hvS
      omega
    · have hsub : S ⊆ (U.erase v) \ B := by
        intro u hu
        obtain ⟨huU, huB⟩ := Finset.mem_sdiff.mp (hS hu)
        exact Finset.mem_sdiff.mpr ⟨Finset.mem_erase.mpr
          ⟨by intro he; subst u; exact hvS hu, huU⟩, huB⟩
      have hc : ClosedIn G ((U.erase v) \ B) S := by
        intro u hu w hw hadj
        obtain ⟨hwU, hwB⟩ := Finset.mem_sdiff.mp hw
        exact hclosed u hu w (Finset.mem_sdiff.mpr ⟨Finset.mem_of_mem_erase hwU, hwB⟩) hadj
      have hrec := ih hBC hC S hsub hc
      have hn : sectionNeighbors G S v = ∅ := by
        apply Finset.eq_empty_iff_forall_notMem.mpr
        intro u hu
        obtain ⟨huS, hvu⟩ := mem_sectionNeighbors.mp hu
        exact hvS (hclosed u huS v (Finset.mem_sdiff.mpr ⟨hv, hvB⟩) hvu.symm)
      have hi := incidence_insert_right G (U := S) (Finset.notMem_erase v U)
      rw [hinsert, hn] at hi
      simpa only [hi, Finset.card_empty, Nat.add_zero] using hrec

theorem incidence_closed_split {F B T : Finset (Fin n)}
    (hB : B ⊆ F) (hT : T ⊆ F \ B) (hc : ClosedIn G (F \ B) T) :
    incidence G T F = incidence G T T + incidence G T B := by
  have heq : incidence G T F = incidence G T (T ∪ B) := by
    apply Finset.sum_congr rfl
    intro v hv
    congr 1
    ext w
    simp only [mem_sectionNeighbors, Finset.mem_union]
    constructor
    · intro h
      by_cases hwB : w ∈ B
      · exact ⟨Or.inr hwB, h.2⟩
      · exact ⟨Or.inl (hc v hv w (Finset.mem_sdiff.mpr ⟨h.1, hwB⟩) h.2), h.2⟩
    · rintro ⟨hw | hw, hadj⟩
      · exact ⟨(Finset.mem_sdiff.mp (hT hw)).1, hadj⟩
      · exact ⟨hB hw, hadj⟩
  rw [heq, incidence_union_right]
  exact Finset.disjoint_left.mpr (fun v hv hvB => (Finset.mem_sdiff.mp (hT hv)).2 hvB)

theorem core_piece_bounds (hG : IsSubcubic G) {F C : Finset (Fin n)}
    (hp : LeafPrunes G F C) (_hmin : ∀ v ∈ C, 2 ≤ (sectionNeighbors G C v).card)
    {T : Finset (Fin n)} (hT : T ∈ components G (F \ branchVertices G C)) :
    degreeExcess G T ≤ 0 ∧ (attachment G (branchVertices G C) T).card ≤ 2 ∧
      incidence G T (branchVertices G C) ≤ 2 := by
  classical
  have ht := mem_components G hT
  have hBC : branchVertices G C ⊆ C := Finset.filter_subset _ _
  have hB := hBC.trans (LeafPrunes.subset G hp)
  have hdeg : ∀ v ∈ C \ branchVertices G C, (sectionNeighbors G C v).card ≤ 2 := by
    intro v hv
    obtain ⟨hvC, hvB⟩ := Finset.mem_sdiff.mp hv
    have hupper : (sectionNeighbors G C v).card ≤ 3 := by
      apply le_trans (Finset.card_le_card (show sectionNeighbors G C v ⊆ G.neighborFinset v from ?_)) (hG v)
      intro u hu
      exact (G.mem_neighborFinset _ _).mpr (mem_sectionNeighbors.mp hu).2
    have hn : (sectionNeighbors G C v).card ≠ 3 := by
      intro he
      exact hvB (Finset.mem_filter.mpr ⟨hvC, he⟩)
    omega
  have hbudget := LeafPrunes.closed_incidence_le_two G hp hBC hdeg T ht.1 ht.2.1
  have hsplit := incidence_closed_split G hB ht.1 ht.2.1
  have hlow := connected_excess_lower G ht.2.2
  have hcard := attachment_card_le G (branchVertices G C) T
  unfold degreeExcess at *
  omega

end CubicPathwidth
Back to top