CubicPathwidth.CoreTorso

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

import CubicPathwidth.CorePieces
import CubicPathwidth.Relabelling

/-! A simple subcubic torso on the retained branch vertices. -/

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

def coreTorso (F B : Finset (Fin n)) : SimpleGraph (Fin B.card) where
  Adj i j := i ≠ j ∧ (G.Adj (enumerate B i) (enumerate B j) ∨
    ∃ T ∈ components G (F \ B),
      enumerate B i ∈ attachment G B T ∧ enumerate B j ∈ attachment G B T)
  symm := ⟨by
    intro i j h
    refine ⟨h.1.symm, ?_⟩
    rcases h.2 with h | ⟨T, hT, hi, hj⟩
    · exact Or.inl h.symm
    · exact Or.inr ⟨T, hT, hj, hi⟩⟩
  loopless := ⟨fun i h => h.1 rfl⟩

theorem two_attachment_unique {A : Finset (Fin n)} (hA : A.card ≤ 2)
    {x y z : Fin n} (hx : x ∈ A) (hy : y ∈ A) (hz : z ∈ A)
    (hxy : x ≠ y) (hxz : x ≠ z) : y = z := by
  have hc : (A.erase x).card ≤ 1 := by
    have := Finset.card_erase_add_one hx
    omega
  exact (Finset.card_le_one.mp hc) y
    (Finset.mem_erase.mpr ⟨hxy.symm, hy⟩) z (Finset.mem_erase.mpr ⟨hxz.symm, hz⟩)

/-- A torso edge can be charged to a neighbour in the original graph. -/
theorem torso_edge_witness {F B : Finset (Fin n)} {i j : Fin B.card}
    (h : (coreTorso G F B).Adj i j) :
    ∃ w, G.Adj (enumerate B i) w ∧
      (w = enumerate B j ∨ ∃ T ∈ components G (F \ B),
        w ∈ T ∧ enumerate B i ∈ attachment G B T ∧ enumerate B j ∈ attachment G B T) := by
  rcases h.2 with h | ⟨T, hT, hi, hj⟩
  · exact ⟨enumerate B j, h, Or.inl rfl⟩
  · obtain ⟨_, w, hw, hiw⟩ := (mem_attachment G).mp hi
    exact ⟨w, hiw, Or.inr ⟨T, hT, hw, hi, hj⟩⟩

theorem coreTorso_subcubic (hG : IsSubcubic G) (F B : Finset (Fin n))
    (hattach : ∀ T ∈ components G (F \ B), (attachment G B T).card ≤ 2) :
    IsSubcubic (coreTorso G F B) := by
  classical
  let K := coreTorso G F B
  intro i
  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'.trans (hG _)

/-- Lift any torso decomposition, retaining exact images of its bags. -/
def liftTorso (F B : Finset (Fin n)) (D : PathDecomposition (coreTorso G F B)) :
    SectionDecomposition G B := by
  classical
  let E : PathDecomposition (inducedOnFin G B) := {
    lastIndex := D.lastIndex
    bag := D.bag
    vertex_covered := D.vertex_covered
    edge_covered := by
      intro i j hij
      exact D.edge_covered i j ⟨by intro he; subst j; exact G.irrefl hij, Or.inl hij⟩
    interval := D.interval }
  exact lift G B E

theorem liftTorso_width (F B : Finset (Fin n)) (D : PathDecomposition (coreTorso G F B))
    {p : ℝ} (hD : D.WidthAtMost p) : (liftTorso G F B D).toBagPath.WidthAtMost p :=
  lift_width G B _ hD

theorem liftTorso_bag (F B : Finset (Fin n)) (D : PathDecomposition (coreTorso G F B))
    (i : Fin (D.lastIndex + 1)) :
    (liftTorso G F B D).bag i.val = (D.bag i).image (enumerate B) := by
  classical
  have hi : i.val ≤ D.lastIndex := by have := i.isLt; omega
  simp [liftTorso, lift, restrict, hi]

/-- Each attachment, including an empty or singleton attachment, fits in one
original torso bag. -/
theorem torso_attachment_bag (F B : Finset (Fin n))
    (D : PathDecomposition (coreTorso G F B)) {T : Finset (Fin n)}
    (hT : T ∈ components G (F \ B)) (hc : (attachment G B T).card ≤ 2) :
    ∃ i, i ≤ (liftTorso G F B D).lastIndex ∧
      attachment G B T ⊆ (liftTorso G F B D).bag i := by
  classical
  let A := attachment G B T
  by_cases hne : A.Nonempty
  · obtain ⟨x, hx⟩ := hne
    obtain ⟨a, ha⟩ := (mem_iff_enumerate B x).mp (attachment_subset G B T hx)
    by_cases he : (A.erase x).Nonempty
    · obtain ⟨y, hy⟩ := he
      obtain ⟨hyx, hyA⟩ := Finset.mem_erase.mp hy
      obtain ⟨b, hb⟩ := (mem_iff_enumerate B y).mp (attachment_subset G B T hyA)
      have hab : (coreTorso G F B).Adj a b :=
        ⟨by intro h; subst b; exact hyx (hb.symm.trans ha), Or.inr ⟨T, hT, ha.symm ▸ hx, hb.symm ▸ hyA⟩⟩
      obtain ⟨i, hai, hbi⟩ := D.edge_covered a b hab
      refine ⟨i.val, by change i.val ≤ D.lastIndex; have := i.isLt; omega, ?_⟩
      rw [liftTorso_bag]
      intro z hz
      by_cases hzx : z = x
      · exact Finset.mem_image.mpr ⟨a, hai, ha.trans hzx.symm⟩
      · have hzy : z = y := two_attachment_unique hc hx hz hyA (Ne.symm hzx) hyx.symm
        exact Finset.mem_image.mpr ⟨b, hbi, hb.trans hzy.symm⟩
    · obtain ⟨i, hai⟩ := D.vertex_covered a
      refine ⟨i.val, by change i.val ≤ D.lastIndex; have := i.isLt; omega, ?_⟩
      rw [liftTorso_bag]
      intro z hz
      have hzx : z = x := by
        by_contra h
        exact he ⟨z, Finset.mem_erase.mpr ⟨h, hz⟩⟩
      exact Finset.mem_image.mpr ⟨a, hai, ha.trans hzx.symm⟩
  · refine ⟨0, Nat.zero_le _, ?_⟩
    have he : attachment G B T = ∅ := Finset.not_nonempty_iff_eq_empty.mp hne
    rw [he]
    exact Finset.empty_subset _

end CubicPathwidth
Back to top