CubicPathwidth.SectionInsertion
Source file CubicPathwidth/SectionInsertion.lean of the Lean project (how it is built).
import CubicPathwidth.SectionAssembly
/-! Insert a disjoint attached section at an existing bag, retaining that bag. -/
noncomputable section
namespace CubicPathwidth
namespace BagPath
variable {V : Type*}
def takeUntil (P : BagPath V) (i : ℕ) (hi : i ≤ P.lastIndex) : BagPath V where
lastIndex := i
bag := P.bag
interval := by
intro a b c hab hbc hc v hv
exact P.interval a b c hab hbc (hc.trans hi) v hv
def suffix (P : BagPath V) (i : ℕ) (_hi : i ≤ P.lastIndex) : BagPath V where
lastIndex := P.lastIndex - i
bag := fun j => P.bag (j + i)
interval := by
intro a b c hab hbc hc v hv
exact P.interval (a + i) (b + i) (c + i) (by omega) (by omega) (by omega) v hv
theorem takeUntil_width (P : BagPath V) (i) (hi) {w : ℝ} (hP : P.WidthAtMost w) :
(P.takeUntil i hi).WidthAtMost w := fun j hj => hP j (hj.trans hi)
theorem suffix_width (P : BagPath V) (i) (hi) {w : ℝ} (hP : P.WidthAtMost w) :
(P.suffix i hi).WidthAtMost w := by
intro j hj
exact hP (j + i) (by change j ≤ P.lastIndex - i at hj; omega)
theorem concat_subset (P Q : BagPath V) (hc : Compatible P Q) (W : Finset V)
(hP : ∀ i, i ≤ P.lastIndex → P.bag i ⊆ W)
(hQ : ∀ i, i ≤ Q.lastIndex → Q.bag i ⊆ W) :
∀ i, i ≤ (P.concat Q hc).lastIndex → (P.concat Q hc).bag i ⊆ W := by
intro i hi
change i ≤ P.lastIndex + Q.lastIndex + 1 at hi
by_cases h : i ≤ P.lastIndex
· rw [concat_bag_left _ _ _ _ h]
exact hP i h
· change (if i ≤ P.lastIndex then P.bag i else Q.bag (i - (P.lastIndex + 1))) ⊆ W
rw [ite_eq_right h]
exact hQ _ (by omega)
end BagPath
namespace SectionDecomposition
variable {n : ℕ} {G : SimpleGraph (Fin n)} {U V : Finset (Fin n)}
/-- The inserted section meets the old graph only through the chosen bag.
Every old bag survives unchanged. Repeated insertions at those surviving
bags therefore take a maximum of costs, rather than accumulating overhead. -/
theorem insert_at_bag (P : SectionDecomposition G U) (Q : SectionDecomposition G V)
(hdis : Disjoint U V) (i : ℕ) (hi : i ≤ P.lastIndex)
(hsep : ∀ v ∈ V, ∀ u ∈ U, G.Adj v u → u ∈ P.bag i)
{a b : ℝ} (hP : P.toBagPath.WidthAtMost a) (hQ : Q.toBagPath.WidthAtMost b) :
∃ R : SectionDecomposition G (U ∪ V),
R.toBagPath.WidthAtMost (max a (b + ((P.bag i).card : ℝ))) ∧
∀ k, k ≤ P.lastIndex → ∃ j, j ≤ R.lastIndex ∧ R.bag j = P.bag k := by
let A := P.toBagPath.takeUntil i hi
let M := Q.hold (P.bag i)
let B := P.toBagPath.suffix i hi
have hAM : BagPath.Compatible A M.toBagPath := by
intro v j k hj hk hvj hvk
have hvU : v ∈ U := P.bag_subset j (hj.trans hi) hvj
have hvI : v ∈ P.bag i := by
rcases Finset.mem_union.mp hvk with hvQ | hvI
· exact False.elim (Finset.disjoint_left.mp hdis hvU (Q.bag_subset k hk hvQ))
· exact hvI
exact ⟨hvI, Finset.mem_union_right _ hvI⟩
let T := A.concat M.toBagPath hAM
have hTB : BagPath.Compatible T B := by
intro v j k hj hk hvj hvk
have hk' : k + i ≤ P.lastIndex := by change k ≤ P.lastIndex - i at hk; omega
have hvU : v ∈ U := P.bag_subset (k + i) hk' hvk
have hvI : v ∈ P.bag i := by
by_cases hjA : j ≤ i
· have hvold : v ∈ P.bag j := by
rw [BagPath.concat_bag_left _ _ _ _ hjA] at hvj
exact hvj
exact P.interval j i (k + i) hjA (by omega) hk' v ⟨hvold, hvk⟩
· have hjM : j - (i + 1) ≤ Q.lastIndex := by
change j ≤ i + Q.lastIndex + 1 at hj
omega
have hvM : v ∈ Q.bag (j - (i + 1)) ∪ P.bag i := by
change v ∈ (if j ≤ i then P.bag j else Q.bag (j - (i + 1)) ∪ P.bag i) at hvj
rwa [ite_eq_right hjA] at hvj
rcases Finset.mem_union.mp hvM with hvQ | hvI
· exact False.elim (Finset.disjoint_left.mp hdis hvU (Q.bag_subset _ hjM hvQ))
· exact hvI
constructor
· rw [BagPath.concat_last]
exact Finset.mem_union_right _ hvI
· change v ∈ P.bag (0 + i)
simpa only [Nat.zero_add] using hvI
let R := T.concat B hTB
have hRlen : R.lastIndex = T.lastIndex + B.lastIndex + 1 := rfl
have hTlen : T.lastIndex = i + Q.lastIndex + 1 := rfl
have hBlen : B.lastIndex = P.lastIndex - i := rfl
have hOld : ∀ k, k ≤ P.lastIndex → ∃ j, j ≤ R.lastIndex ∧ R.bag j = P.bag k := by
intro k hk
by_cases hki : k ≤ i
· refine ⟨k, ?_, ?_⟩
· rw [hRlen, hTlen, hBlen]; omega
· rw [BagPath.concat_bag_left _ _ _ _ (by rw [hTlen]; omega),
BagPath.concat_bag_left _ _ _ _ hki]
rfl
· refine ⟨T.lastIndex + 1 + (k - i), ?_, ?_⟩
· rw [hRlen, hBlen]; omega
· rw [BagPath.concat_bag_right]
change P.bag (k - i + i) = P.bag k
rw [Nat.sub_add_cancel (by omega)]
have hMid : ∀ k, k ≤ Q.lastIndex →
i + 1 + k ≤ R.lastIndex ∧ R.bag (i + 1 + k) = Q.bag k ∪ P.bag i := by
intro k hk
constructor
· rw [hRlen, hTlen, hBlen]; omega
· rw [BagPath.concat_bag_left _ _ _ _ (by rw [hTlen]; omega)]
exact BagPath.concat_bag_right A M.toBagPath hAM k
have hsubset : ∀ j, j ≤ R.lastIndex → R.bag j ⊆ U ∪ V := by
apply BagPath.concat_subset
· apply BagPath.concat_subset
· intro j hj
exact (P.bag_subset j (hj.trans hi)).trans Finset.subset_union_left
· intro j hj v hv
rcases Finset.mem_union.mp hv with hv | hv
· exact Finset.mem_union_right _ (Q.bag_subset j hj hv)
· exact Finset.mem_union_left _ (P.bag_subset i hi hv)
· intro j hj
exact (P.bag_subset (j + i) (by change j ≤ P.lastIndex - i at hj; omega)).trans
Finset.subset_union_left
let D : SectionDecomposition G (U ∪ V) := {
toBagPath := R
bag_subset := hsubset
vertex_covered := by
intro v hv
rcases Finset.mem_union.mp hv with hvU | hvV
· obtain ⟨k, hk, hvk⟩ := P.vertex_covered v hvU
obtain ⟨j, hj, he⟩ := hOld k hk
exact ⟨j, hj, he.symm ▸ hvk⟩
· obtain ⟨k, hk, hvk⟩ := Q.vertex_covered v hvV
exact ⟨i + 1 + k, (hMid k hk).1, (hMid k hk).2.symm ▸ Finset.mem_union_left _ hvk⟩
edge_covered := by
intro u hu v hv huv
by_cases huU : u ∈ U
· by_cases hvU : v ∈ U
· obtain ⟨k, hk, huk, hvk⟩ := P.edge_covered u huU v hvU huv
obtain ⟨j, hj, he⟩ := hOld k hk
exact ⟨j, hj, he.symm ▸ huk, he.symm ▸ hvk⟩
· have hvV := (Finset.mem_union.mp hv).resolve_left hvU
obtain ⟨k, hk, hvk⟩ := Q.vertex_covered v hvV
exact ⟨i + 1 + k, (hMid k hk).1,
(hMid k hk).2.symm ▸ Finset.mem_union_right _ (hsep v hvV u huU huv.symm),
(hMid k hk).2.symm ▸ Finset.mem_union_left _ hvk⟩
· have huV := (Finset.mem_union.mp hu).resolve_left huU
by_cases hvU : v ∈ U
· obtain ⟨k, hk, huk⟩ := Q.vertex_covered u huV
exact ⟨i + 1 + k, (hMid k hk).1,
(hMid k hk).2.symm ▸ Finset.mem_union_left _ huk,
(hMid k hk).2.symm ▸ Finset.mem_union_right _ (hsep u huV v hvU huv)⟩
· have hvV := (Finset.mem_union.mp hv).resolve_left hvU
obtain ⟨k, hk, huk, hvk⟩ := Q.edge_covered u huV v hvV huv
exact ⟨i + 1 + k, (hMid k hk).1,
(hMid k hk).2.symm ▸ Finset.mem_union_left _ huk,
(hMid k hk).2.symm ▸ Finset.mem_union_left _ hvk⟩ }
refine ⟨D, ?_, hOld⟩
have hw := BagPath.concat_width hTB
(BagPath.concat_width hAM (BagPath.takeUntil_width _ _ _ hP) (hold_width Q _ hQ))
(BagPath.suffix_width _ _ _ hP)
exact hw.mono (max_le le_rfl (le_max_left _ _))
end SectionDecomposition
end CubicPathwidth
Back to top