CubicPathwidth.PseudotreeDecomposition
Source file CubicPathwidth/PseudotreeDecomposition.lean of the Lean project (how it is built).
import CubicPathwidth.ForestDecomposition
/-! Decomposing a connected subcubic section with at most as many edges as vertices. -/
noncomputable section
namespace CubicPathwidth
open SectionDecomposition
variable {n : ℕ} (G : SimpleGraph (Fin n))
theorem sectionNeighbors_mono {U V : Finset (Fin n)} (h : U ⊆ V) (v : Fin n) :
sectionNeighbors G U v ⊆ sectionNeighbors G V v := by
intro w hw
exact mem_sectionNeighbors.mpr ⟨h (mem_sectionNeighbors.mp hw).1, (mem_sectionNeighbors.mp hw).2⟩
theorem forest_restore_leaf {U : Finset (Fin n)} {v : Fin n} (_hv : v ∈ U)
(hforest : ForestSection G (U.erase v)) (hdeg : (sectionNeighbors G U v).card ≤ 1) :
ForestSection G U := by
classical
intro S hS hne
by_cases hvS : v ∈ S
· by_cases he : (S.erase v).Nonempty
· have hs := hforest (S.erase v) (Finset.erase_subset_erase v hS) he
have hd := (Finset.card_le_card (sectionNeighbors_mono G
((Finset.erase_subset v S).trans hS) v)).trans hdeg
have hi := degreeExcess_insert G (Finset.notMem_erase v S)
rw [Finset.insert_erase hvS] at hi
omega
· have hz := Finset.not_nonempty_iff_eq_empty.mp he
have hsingle : S = {v} := by
rw [← Finset.insert_erase hvS, hz]
rfl
simp [hsingle, degreeExcess, incidence_singleton]
· apply hforest S _ hne
intro w hw
exact Finset.mem_erase.mpr ⟨by intro he; subst w; exact hvS hw, hS hw⟩
theorem connected_erase_leaf {U : Finset (Fin n)} {v : Fin n}
(hconn : SectionConnected G U) (hv : v ∈ U)
(hdeg : (sectionNeighbors G U v).card = 1) : SectionConnected G (U.erase v) := by
classical
obtain ⟨u, hu⟩ := Finset.card_eq_one.mp hdeg
have hn : u ∈ sectionNeighbors G U v := by rw [hu]; simp
obtain ⟨huU, hvu⟩ := mem_sectionNeighbors.mp hn
have unique : ∀ w ∈ U, G.Adj v w → w = u := by
intro w hw hadj
have hmem := mem_sectionNeighbors.mpr ⟨hw, hadj⟩
rw [hu] at hmem
exact Finset.mem_singleton.mp hmem
refine ⟨⟨u, Finset.mem_erase.mpr ⟨hvu.ne.symm, huU⟩⟩, ?_⟩
intro S hS hc hne
have hvS : v ∉ S := fun h => Finset.notMem_erase v U (hS h)
have hSU := hS.trans (Finset.erase_subset v U)
by_cases huS : u ∈ S
· have hclosed : ClosedIn G U (insert v S) := by
intro a ha w hw hadj
by_cases hwv : w = v
· subst w
exact Finset.mem_insert_self _ _
· rcases Finset.mem_insert.mp ha with rfl | haS
· rw [unique w hw hadj]
exact Finset.mem_insert_of_mem huS
· exact Finset.mem_insert_of_mem (hc a haS w (Finset.mem_erase.mpr ⟨hwv, hw⟩) hadj)
have he := hconn.2 (insert v S) (Finset.insert_subset hv hSU) hclosed
(Finset.insert_nonempty _ _)
have he' := congrArg (fun A : Finset (Fin n) => A.erase v) he
simpa [Finset.erase_insert hvS] using he'
· have hclosed : ClosedIn G U S := by
intro a ha w hw hadj
have hwv : w ≠ v := by
intro he
subst w
exact huS ((unique a (hSU ha) hadj.symm) ▸ ha)
exact hc a ha w (Finset.mem_erase.mpr ⟨hwv, hw⟩) hadj
have he := hconn.2 S hSU hclosed hne
exact False.elim (hvS (he.symm ▸ hv))
theorem LeafPrunes.connected {U C : Finset (Fin n)} (h : LeafPrunes G U C)
(hconn : SectionConnected G U) : SectionConnected G C := by
induction h with
| refl U => exact hconn
| step v hv hdeg rest ih => exact ih (connected_erase_leaf G hconn hv hdeg)
theorem LeafPrunes.forest_erase {U C : Finset (Fin n)} (h : LeafPrunes G U C)
{z : Fin n} (hz : z ∈ C) (hforest : ForestSection G (C.erase z)) :
ForestSection G (U.erase z) := by
classical
induction h with
| refl U => exact hforest
| @step V C v hv hdeg rest ih =>
have hzV := LeafPrunes.subset G rest hz
have hvz : v ≠ z := by intro he; subst v; exact Finset.notMem_erase z V hzV
apply forest_restore_leaf G (Finset.mem_erase.mpr ⟨hvz, hv⟩)
· simpa only [Finset.erase_right_comm] using ih hz hforest
· exact (Finset.card_le_card (sectionNeighbors_mono G (Finset.erase_subset _ _) _)).trans hdeg.le
theorem connected_nonnegativeComponentExcess {U : Finset (Fin n)}
(hconn : SectionConnected G U) (he : 0 ≤ degreeExcess G U) :
NonnegativeComponentExcess G U := by
classical
intro S hS hc
by_cases hn : S.Nonempty
· rw [hconn.2 S hS hc hn]
exact he
· have hz := Finset.not_nonempty_iff_eq_empty.mp hn
simp [hz, degreeExcess, incidence]
theorem incidence_positive {U V : Finset (Fin n)}
{u v : Fin n} (hu : u ∈ U) (hv : v ∈ V) (huv : G.Adj u v) : 0 < incidence G U V := by
have hn : 0 < (sectionNeighbors G V u).card :=
Finset.card_pos.mpr ⟨v, mem_sectionNeighbors.mpr ⟨hv, huv⟩⟩
exact hn.trans_le (Finset.single_le_sum
(f := fun w => (sectionNeighbors G V w).card) (fun _ _ => Nat.zero_le _) hu)
theorem degree_two_erase_forest {U : Finset (Fin n)} (hconn : SectionConnected G U)
(hdeg : ∀ v ∈ U, (sectionNeighbors G U v).card = 2) {z : Fin n} (hz : z ∈ U) :
ForestSection G (U.erase z) := by
classical
intro S hS hne
have hSU := hS.trans (Finset.erase_subset z U)
have hproper : S ≠ U := by intro he; exact Finset.notMem_erase z U (hS (he.symm ▸ hz))
obtain ⟨u, hu, v, hv, huv⟩ := connected_cross_edge G hconn hSU hne hproper
have hpos := incidence_positive G hu hv huv
have hsum : incidence G S U = 2 * S.card := by
unfold incidence
simp only [Finset.sum_congr rfl (fun v hv => hdeg v (hSU hv))]
simp [Nat.mul_comm]
have heq : S ∪ (U \ S) = U := Finset.union_sdiff_of_subset hSU
have he := incidence_union_right G (U := S) (Finset.sdiff_disjoint.symm : Disjoint S (U \ S))
rw [heq] at he
unfold degreeExcess
omega
theorem pseudotree_section_decomposition (hG : IsSubcubic G) (U : Finset (Fin n))
(hconn : SectionConnected G U) (hex : degreeExcess G U ≤ 0) :
∃ P : SectionDecomposition G U,
P.toBagPath.WidthAtMost (4 * Real.sqrt (U.card : ℝ) + 1) := by
classical
by_cases hneg : degreeExcess G U < 0
· obtain ⟨P, hP⟩ := forest_section_decomposition G U (forest_of_connected_negative G hconn hneg)
exact ⟨P, hP.mono (by linarith)⟩
· have heq : degreeExcess G U = 0 := by omega
obtain ⟨C, hp, hm⟩ := exists_leafPrunes_minDegree_two G U
(connected_nonnegativeComponentExcess G hconn (by omega))
have hCconn := LeafPrunes.connected G hp hconn
have heC := hp.excess_eq
have hcount := degreeExcess_eq_branch_card G hG C hm
have hCdeg : ∀ v ∈ C, (sectionNeighbors G C v).card = 2 := by
intro v hv
have hl := hm v hv
have hu : (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 w hw
exact (G.mem_neighborFinset _ _).mpr (mem_sectionNeighbors.mp hw).2
by_contra hn
have hthree : (sectionNeighbors G C v).card = 3 := by omega
have hnz : 0 < (C.filter (fun v => (sectionNeighbors G C v).card = 3)).card :=
Finset.card_pos.mpr ⟨v, Finset.mem_filter.mpr ⟨hv, hthree⟩⟩
omega
obtain ⟨z, hz⟩ := hCconn.1
have hforest := LeafPrunes.forest_erase G hp hz (degree_two_erase_forest G hCconn hCdeg hz)
obtain ⟨P, hP⟩ := forest_section_decomposition G (U.erase z) hforest
have hzU := LeafPrunes.subset G hp hz
have hU : (U.erase z) ∪ {z} = U := by
rw [Finset.union_comm, Finset.singleton_union, Finset.insert_erase hzU]
have hc : ((U.erase z).card : ℝ) ≤ U.card := by exact_mod_cast Finset.card_le_card (Finset.erase_subset z U)
have hwidth := (hold_width P {z} hP).mono
(show 4 * Real.sqrt ((U.erase z).card : ℝ) + (({z} : Finset (Fin n)).card : ℝ) ≤
4 * Real.sqrt (U.card : ℝ) + 1 by
simp only [Finset.card_singleton, Nat.cast_one]
linarith [Real.sqrt_le_sqrt hc])
have hout : ∃ Q : SectionDecomposition G ((U.erase z) ∪ {z}),
Q.toBagPath.WidthAtMost (4 * Real.sqrt (U.card : ℝ) + 1) := ⟨P.hold {z}, hwidth⟩
rw [hU] at hout
exact hout
end CubicPathwidth
Back to top