CubicPathwidth.Alg.Proofs2.L5SwitchedWidth
Source file CubicPathwidth/Alg/Proofs2/L5SwitchedWidth.lean of the Lean project (how it is built).
import CubicPathwidth.Alg.Spec2
import CubicPathwidth.Alg.Proofs.C4Switched
import CubicPathwidth.Alg.Proofs.C1Perm
/-!
# L5: width of the median-switched layout (`SwitchedLayoutWidth`)
Bag by bag, as sets (paper: Lemma 8.4 (`lem:median-layout`); port: `switchedLayoutF`, with the
block structure of `C4.layoutB`). Inner bag `i`: `{v_i} ∪ innerFr (Y v_{i-1})`; the
bag `C_{-1}` has at most `lowerZeroP` elements; the connector bags `C_j` have at most
`|D| + max(|P|, |W'|) + 2 ≤ max(L₀, L₀') + 2` elements (`lem:connector-linear` gives the count);
outer bag `k`: `{v} ∪ outerFr (Y v)` with `Y v > 0`.
-/
namespace CubicPathwidth.Alg
open Graph
namespace L5
/-! ## 1. Generic list facts -/
theorem len_filter_or_and {α : Type} (p q : α → Bool) (L : List α) :
(L.filter p).length + (L.filter q).length =
(L.filter (fun x => p x || q x)).length + (L.filter (fun x => p x && q x)).length := by
induction L with
| nil => simp
| cons a L ih =>
cases hp : p a <;> cases hq : q a <;> simp [hp, hq] at ih ⊢ <;> omega
theorem len_filter_not_add {α : Type} (s : α → Bool) (L : List α) :
(L.filter (fun x => !s x)).length + (L.filter s).length = L.length := by
induction L with
| nil => simp
| cons a L ih =>
cases hs : s a <;> simp [hs] at ih ⊢ <;> omega
theorem len_filter_mono {α : Type} {p q : α → Bool} (L : List α)
(h : ∀ x, p x = true → q x = true) :
(L.filter p).length ≤ (L.filter q).length :=
(List.monotone_filter_right L h).length_le
theorem len_filter_eq_zero {α : Type} {p : α → Bool} (L : List α) (h : ∀ x, p x = false) :
(L.filter p).length = 0 := by
have : (L.filter p).length ≤ (L.filter (fun _ => false)).length :=
len_filter_mono L (fun x hx => by rw [h x] at hx; exact absurd hx (by simp))
simpa using this
theorem card_le_length (B : List Nat) : B.toFinset.card ≤ B.length :=
List.toFinset_card_le B
theorem card_cons_le (v : Nat) (F S : List Nat) (h : ∀ x ∈ F, x ∈ S) :
(v :: F).toFinset.card ≤ S.length + 1 := by
rw [List.toFinset_cons]
refine (Finset.card_insert_le _ _).trans ?_
have h1 : F.toFinset ⊆ S.toFinset := fun x hx => by
rw [List.mem_toFinset] at hx ⊢
exact h x hx
have h2 := Finset.card_le_card h1
have h3 := List.toFinset_card_le S
omega
/-- A list of bags of width at most `w` (as sets) has `pdWidth ≤ w`, when `w + 1 ≥ 0`. -/
theorem pdWidth_le_of (bags : List Bag) (w : ℝ) (hw : 0 ≤ w + 1)
(h : ∀ B ∈ bags, (B.toFinset.card : ℝ) ≤ w + 1) : pdWidth bags ≤ w := by
have key : ∀ bs : List Bag, (∀ B ∈ bs, (B.toFinset.card : ℝ) ≤ w + 1) →
((maxBagCard bs : ℕ) : ℝ) ≤ w + 1 := by
intro bs
induction bs with
| nil =>
intro _
simpa [maxBagCard] using hw
| cons B bs ih =>
intro hB
have h1 : (B.toFinset.card : ℝ) ≤ w + 1 := hB B (by simp)
have h2 := ih (fun B' hB' => hB B' (by simp [hB']))
have e : maxBagCard (B :: bs) = max B.toFinset.card (maxBagCard bs) := by
simp [maxBagCard]
rw [e, Nat.cast_max]
exact max_le h1 h2
have := key bags h
unfold pdWidth
linarith
/-! ## 2. Order and thresholds -/
theorem switchedOrder_sorted (G : Graph) (Y : Labels) :
(switchedOrder G Y).Pairwise (fun a b => Y a ≤ Y b) := by
have trans : ∀ a b c : Nat,
(decide (Y a < Y b) || (decide (Y a = Y b) && decide (a ≤ b))) = true →
(decide (Y b < Y c) || (decide (Y b = Y c) && decide (b ≤ c))) = true →
(decide (Y a < Y c) || (decide (Y a = Y c) && decide (a ≤ c))) = true := by
intro a b c h1 h2
simp only [Bool.or_eq_true, Bool.and_eq_true, decide_eq_true_eq] at h1 h2 ⊢
rcases h1 with h1 | ⟨h1, h1'⟩ <;> rcases h2 with h2 | ⟨h2, h2'⟩
· exact Or.inl (lt_trans h1 h2)
· exact Or.inl (by rw [← h2]; exact h1)
· exact Or.inl (by rw [h1]; exact h2)
· exact Or.inr ⟨h1.trans h2, by omega⟩
have total : ∀ a b : Nat,
((decide (Y a < Y b) || (decide (Y a = Y b) && decide (a ≤ b))) ||
(decide (Y b < Y a) || (decide (Y b = Y a) && decide (b ≤ a)))) = true := by
intro a b
simp only [Bool.or_eq_true, Bool.and_eq_true, decide_eq_true_eq]
rcases lt_trichotomy (Y a) (Y b) with h | h | h
· exact Or.inl (Or.inl h)
· rcases le_total a b with hab | hab
· exact Or.inl (Or.inr ⟨h, hab⟩)
· exact Or.inr (Or.inr ⟨h.symm, hab⟩)
· exact Or.inr (Or.inl h)
have hs := List.pairwise_mergeSort trans total G.nodes
unfold switchedOrder
refine hs.imp ?_
intro a b hab
simp only [Bool.or_eq_true, Bool.and_eq_true, decide_eq_true_eq] at hab
rcases hab with h | ⟨h, _⟩
· exact h.le
· exact le_of_eq h
theorem pos_le {Y : Labels} {order : List Nat} (hs : order.Pairwise (fun a b => Y a ≤ Y b))
{i j : Nat} (hi : i < order.length) (hj : j < order.length) (hij : i ≤ j) :
Y (order[i]) ≤ Y (order[j]) := by
rcases Nat.lt_or_ge i j with h | h
· exact List.pairwise_iff_getElem.1 hs i j hi hj h
· have : i = j := by omega
subst this
exact le_refl _
/-- Threshold lemma: for a node `x` of a sorted injective order, the position of `x` is at
most `m` iff `Y x ≤ Y (order[m])`. -/
theorem thr_iff {G : Graph} {Y : Labels} (hG : G.WF) (hinj : LabelsInjOn G Y)
{order : List Nat} (hperm : order.Perm G.nodes)
(hs : order.Pairwise (fun a b => Y a ≤ Y b))
{m : Nat} (hm : m < order.length) {x : Nat} (hx : x ∈ G.nodes) :
order.idxOf x ≤ m ↔ Y x ≤ Y (order.getD m 0) := by
have hnd : order.Nodup := hperm.nodup_iff.2 hG.nodup
have hxo : x ∈ order := hperm.mem_iff.2 hx
have hym : order[m] ∈ G.nodes := hperm.mem_iff.1 (List.getElem_mem hm)
have ha : order.idxOf x < order.length := List.idxOf_lt_length_iff.2 hxo
have hxa : order[order.idxOf x] = x := List.getElem_idxOf ha
have hy : order.getD m 0 = order[m] := by
rw [List.getD_eq_getElem?_getD, List.getElem?_eq_getElem hm]
rfl
rw [hy]
rcases lt_trichotomy (order.idxOf x) m with h | h | h
· refine iff_of_true (by omega) ?_
have := pos_le hs ha hm h.le
rwa [hxa] at this
· subst h
exact iff_of_true le_rfl (le_of_eq (by rw [hxa]))
· refine iff_of_false (by omega) ?_
intro hle
have h1 := pos_le hs hm ha h.le
rw [hxa] at h1
have heq : Y x = Y order[m] := le_antisymm hle h1
have hxm : x = order[m] := hinj x hx _ hym heq
have : order.idxOf x = m := by
rw [hxm]
exact hnd.idxOf_getElem m hm
omega
/-! ## 3. Frontiers and bag membership -/
theorem mem_innerFr {G : Graph} {Y : Labels} {t : ℚ} {x : Nat} :
x ∈ innerFr G Y t ↔ x ∈ G.nodes ∧ Y x ≤ t ∧ ∃ w ∈ G.nbrs x, t < Y w := by
unfold innerFr
simp [List.mem_filter, List.any_eq_true]
theorem mem_outerFr {G : Graph} {Y : Labels} {t : ℚ} {x : Nat} :
x ∈ outerFr G Y t ↔ x ∈ G.nodes ∧ t < Y x ∧ ∃ u ∈ G.nbrs x, Y u ≤ t := by
unfold outerFr
simp [List.mem_filter, List.any_eq_true]
theorem bag_cases {G : Graph} {Y : Labels} {order q : List Nat} {B : Bag}
(hB : B ∈ C4.layoutB G Y order q) :
(∃ i, i < C4.nLow G Y ∧ B = C4.innerB G order i) ∨ B = C4.cm1B G Y ∨
(∃ j, j ≤ q.length ∧ B = C4.csB G Y q j) ∨
(∃ k, k < order.length - C4.nLow G Y ∧ B = C4.outB G Y order k) := by
unfold C4.layoutB at hB
simp only [List.mem_append, List.mem_map, List.mem_range, List.mem_singleton] at hB
rcases hB with ((⟨i, hi, rfl⟩ | rfl) | ⟨j, hj, rfl⟩) | ⟨k, hk, rfl⟩
· exact Or.inl ⟨i, hi, rfl⟩
· exact Or.inr (Or.inl rfl)
· exact Or.inr (Or.inr (Or.inl ⟨j, by omega, rfl⟩))
· exact Or.inr (Or.inr (Or.inr ⟨k, hk, rfl⟩))
/-! ## 4. Inner bags -/
theorem inner_card {G : Graph} {Y : Labels} {order q : List Nat} (hG : G.WF)
(h : C4.OrdOK G Y order q) (hinj : LabelsInjOn G Y)
(hs : order.Pairwise (fun a b => Y a ≤ Y b)) {i : Nat} (hi : i < C4.nLow G Y)
{w : ℝ} (hinner : ∀ t : ℚ, t < 0 → ((innerFr G Y t).length : ℝ) ≤ w) (hw0 : 0 ≤ w) :
((C4.innerB G order i).toFinset.card : ℝ) ≤ w + 1 := by
have hnl : C4.nLow G Y ≤ order.length := by
rw [h.length]
exact C4.nLow_le
have hnd : order.Nodup := h.nodup hG.nodup
rcases i with _ | j
· have h1 : (C4.innerB G order 0).toFinset.card ≤ 1 := by
refine (card_le_length _).trans ?_
simp [C4.innerB]
have h2 : ((C4.innerB G order 0).toFinset.card : ℝ) ≤ 1 := by exact_mod_cast h1
linarith
· have hj : j < order.length := by omega
have hjn : order.getD j 0 ∈ G.nodes := h.mem.1 (C4.getD_mem_order hj)
have hlow : isLow Y (order.getD j 0) = true := by
apply (h.low_iff hjn).2
rw [C4.idxOf_getD hnd hj]
omega
have ht : Y (order.getD j 0) < 0 := by
unfold isLow at hlow
simpa using hlow
have hsub : ∀ x ∈ (order.take (j + 1)).filter
(fun u => (G.nbrs u).any fun y => !decide (y ∈ order.take (j + 1))),
x ∈ innerFr G Y (Y (order.getD j 0)) := by
intro x hx
obtain ⟨hxT, hany⟩ := List.mem_filter.1 hx
obtain ⟨y, hy, hyT⟩ := List.any_eq_true.1 hany
have hxo : x ∈ order := List.mem_of_mem_take hxT
have hxn : x ∈ G.nodes := h.mem.1 hxo
have hidx : order.idxOf x < j + 1 := (List.mem_take_iff_idxOf_lt hxo).1 hxT
rw [mem_innerFr]
refine ⟨hxn, ?_, ?_⟩
· exact (thr_iff hG hinj h.perm hs hj hxn).1 (by omega)
· have hyn : y ∈ G.nodes := hG.nbrs_sub x y hy
have hyo : y ∈ order := h.mem.2 hyn
have hyT' : y ∉ order.take (j + 1) := by simpa using hyT
have hyidx : j + 1 ≤ order.idxOf y := by
by_contra hc
exact hyT' ((List.mem_take_iff_idxOf_lt hyo).2 (by omega))
refine ⟨y, hy, ?_⟩
by_contra hc
have hle : Y y ≤ Y (order.getD j 0) := not_lt.1 hc
have := (thr_iff hG hinj h.perm hs hj hyn).2 hle
omega
have hc := card_cons_le (order.getD (j + 1) 0) _ _ hsub
have hc2 : ((innerFr G Y (Y (order.getD j 0))).length : ℝ) ≤ w := hinner _ ht
have hc3 : (C4.innerB G order (j + 1)).toFinset.card ≤
(innerFr G Y (Y (order.getD j 0))).length + 1 := by
unfold C4.innerB
exact hc
have hc4 : ((C4.innerB G order (j + 1)).toFinset.card : ℝ) ≤
((innerFr G Y (Y (order.getD j 0))).length : ℝ) + 1 := by
exact_mod_cast hc3
linarith
/-! ## 5. Outer bags -/
theorem outer_card {G : Graph} {Y : Labels} {order q : List Nat} (hG : G.WF)
(h : C4.OrdOK G Y order q) (hinj : LabelsInjOn G Y)
(hs : order.Pairwise (fun a b => Y a ≤ Y b)) (hnz : ∀ v ∈ G.nodes, Y v ≠ 0)
{k : Nat} (hk : k < order.length - C4.nLow G Y)
{w : ℝ} (houter : ∀ t : ℚ, 0 < t → ((outerFr G Y t).length : ℝ) ≤ w) :
((C4.outB G Y order k).toFinset.card : ℝ) ≤ w + 1 := by
have hnl : C4.nLow G Y + k < order.length := by omega
have hnodup : order.Nodup := h.nodup hG.nodup
have hvn : order.getD (C4.nLow G Y + k) 0 ∈ G.nodes :=
h.mem.1 (C4.getD_mem_order hnl)
have hvidx : order.idxOf (order.getD (C4.nLow G Y + k) 0) = C4.nLow G Y + k :=
C4.idxOf_getD hnodup hnl
have hvhigh : isLow Y (order.getD (C4.nLow G Y + k) 0) = false := by
cases hl : isLow Y (order.getD (C4.nLow G Y + k) 0)
· rfl
· have := (h.low_iff hvn).1 hl
omega
have ht : 0 < Y (order.getD (C4.nLow G Y + k) 0) := by
have h1 : ¬ (Y (order.getD (C4.nLow G Y + k) 0) < 0) := by
intro hc
have hl : isLow Y (order.getD (C4.nLow G Y + k) 0) = true := by
unfold isLow
simpa using hc
rw [hvhigh] at hl
exact absurd hl (by simp)
exact lt_of_le_of_ne (not_lt.1 h1) (fun e => hnz _ hvn e.symm)
have hsub : ∀ x ∈ G.nodes.filter (fun x => !decide (x ∈ G.nodes.filter (isLow Y) ++
(order.drop (C4.nLow G Y)).take (k + 1)) &&
(G.nbrs x).any fun u => decide (u ∈ G.nodes.filter (isLow Y) ++
(order.drop (C4.nLow G Y)).take (k + 1))),
x ∈ outerFr G Y (Y (order.getD (C4.nLow G Y + k) 0)) := by
intro x hx
obtain ⟨hxn, hxf⟩ := List.mem_filter.1 hx
simp only [Bool.and_eq_true, Bool.not_eq_true', decide_eq_false_iff_not,
decide_eq_true_eq, List.any_eq_true] at hxf
obtain ⟨hxT, u, hu, huT⟩ := hxf
have hun : u ∈ G.nodes := hG.nbrs_sub x u hu
have hT1 := h.mem_T (k := k) hxn
have hT2 := h.mem_T (k := k) hun
rw [mem_outerFr]
refine ⟨hxn, ?_, u, hu, ?_⟩
· by_contra hc
have hle := not_lt.1 hc
have hidx := (thr_iff hG hinj h.perm hs hnl hxn).2 hle
exact hxT (hT1.2 (by omega))
· exact (thr_iff hG hinj h.perm hs hnl hun).1 (by
have := hT2.1 huT
omega)
have hc : (C4.outB G Y order k).toFinset.card ≤
(outerFr G Y (Y (order.getD (C4.nLow G Y + k) 0))).length + 1 := by
unfold C4.outB
exact card_cons_le _ _ _ hsub
have hN : ((C4.outB G Y order k).toFinset.card : ℝ) ≤
((outerFr G Y (Y (order.getD (C4.nLow G Y + k) 0))).length : ℝ) + 1 := by
exact_mod_cast hc
have := houter _ ht
linarith
/-! ## 6. The bag `C_{-1}` and the level-zero counts -/
theorem U_W_disj (G : Graph) (Y : Labels) (x : Nat) :
(inU G Y x && (inD G Y x && inW G Y x)) = false := by
by_contra hc
simp only [Bool.not_eq_false, Bool.and_eq_true] at hc
obtain ⟨h1, _, h3⟩ := hc
have hl := (C4.inU_iff.1 h1).1
have hh := (C4.inW_iff.1 h3).1
rw [hl] at hh
exact absurd hh (by simp)
theorem cm1_card (G : Graph) (Y : Labels) :
(C4.cm1B G Y).toFinset.card ≤ lowerZeroP G Y := by
refine (card_le_length _).trans ?_
have e : (G.nodes.filter (inU G Y)).length + (G.nodes.filter fun v => inD G Y v && inW G Y v).length
= (G.nodes.filter fun v => inU G Y v || (inD G Y v && inW G Y v)).length +
(G.nodes.filter fun v => inU G Y v && (inD G Y v && inW G Y v)).length :=
len_filter_or_and _ _ _
have z : (G.nodes.filter fun v => inU G Y v && (inD G Y v && inW G Y v)).length = 0 :=
len_filter_eq_zero _ (U_W_disj G Y)
unfold C4.cm1B lowerZeroP
omega
/-! ## 7. Degrees and the connector items -/
theorem items_filter_len (G : Graph) (Y : Labels) (X : List Nat) :
(((C4.pSet G Y).map (C4.eSet G Y)).filter (fun e => subsetB e X)).length =
((C4.pSet G Y).filter (fun u => subsetB (C4.eSet G Y u) X)).length := by
rw [List.filter_map, List.length_map]
rfl
theorem eSet_len_le {G : Graph} {Y : Labels} (hdeg : G.MaxDegLE 3) {u : Nat} (hu : u ∈ G.nodes)
(hU : inU G Y u = true) (hD : inD G Y u = false) : (C4.eSet G Y u).length ≤ 2 := by
unfold C4.eSet
have hdu := hdeg u hu
have hlen : (G.nbrs u).length = G.degree u := rfl
by_cases h3 : G.degree u = 3
· have hnot : ∃ x ∈ G.nbrs u, C4.wpF G Y x = false := by
by_contra hcon
push Not at hcon
have hall : (G.nbrs u).all (fun x => isLow Y x != isLow Y u) = true := by
rw [List.all_eq_true]
intro x hx
have hw : C4.wpF G Y x = true := by simpa using hcon x hx
have hlx : isLow Y x = false := (C4.wpF_iff.1 hw).1.1
have hlu : isLow Y u = true := (C4.inU_iff.1 hU).1
simp [hlx, hlu]
have hDt : inD G Y u = true := by
unfold inD
simp [h3, hall]
rw [hD] at hDt
exact absurd hDt (by simp)
obtain ⟨x, hx, hxw⟩ := hnot
have hlt := (List.length_filter_lt_length_iff_exists (p := C4.wpF G Y)
(l := G.nbrs u)).2 ⟨x, hx, by simp [hxw]⟩
omega
· have := List.length_filter_le (C4.wpF G Y) (G.nbrs u)
omega
/-- `|D| + |P| ≤ L₀`. -/
theorem sum_D_P (G : Graph) (Y : Labels) :
(G.nodes.filter (inD G Y)).length + (C4.pSet G Y).length ≤ lowerZeroP G Y := by
have e1 : (G.nodes.filter (inD G Y)).length ≤
(G.nodes.filter fun v => inD G Y v && isLow Y v).length +
(G.nodes.filter fun v => inD G Y v && inW G Y v).length := by
have a : (G.nodes.filter fun v => inD G Y v && isLow Y v).length +
(G.nodes.filter fun v => inD G Y v && inW G Y v).length =
(G.nodes.filter fun v => (inD G Y v && isLow Y v) || (inD G Y v && inW G Y v)).length +
(G.nodes.filter fun v => (inD G Y v && isLow Y v) && (inD G Y v && inW G Y v)).length :=
len_filter_or_and _ _ _
have b : (G.nodes.filter (inD G Y)).length ≤
(G.nodes.filter fun v => (inD G Y v && isLow Y v) || (inD G Y v && inW G Y v)).length := by
refine len_filter_mono _ (fun x hx => ?_)
cases hl : isLow Y x
· have hw := C4.inW_of_inD_high hx hl
simp [hx, hw]
· simp [hx]
have z : (G.nodes.filter fun v => (inD G Y v && isLow Y v) && (inD G Y v && inW G Y v)).length
= 0 := by
refine len_filter_eq_zero _ (fun x => ?_)
cases hw : inW G Y x with
| false => simp
| true =>
have := (C4.inW_iff.1 hw).1
simp [this]
omega
have e2 : (C4.pSet G Y).length + (G.nodes.filter fun v => inD G Y v && isLow Y v).length ≤
(G.nodes.filter (inU G Y)).length := by
have hP : C4.pSet G Y = G.nodes.filter fun u =>
inU G Y u && !inD G Y u && (G.nbrs u).any (C4.wpF G Y) := rfl
rw [hP]
have a : (G.nodes.filter fun u => inU G Y u && !inD G Y u && (G.nbrs u).any (C4.wpF G Y)).length +
(G.nodes.filter fun v => inD G Y v && isLow Y v).length =
(G.nodes.filter fun u => (inU G Y u && !inD G Y u && (G.nbrs u).any (C4.wpF G Y)) ||
(inD G Y u && isLow Y u)).length +
(G.nodes.filter fun u => (inU G Y u && !inD G Y u && (G.nbrs u).any (C4.wpF G Y)) &&
(inD G Y u && isLow Y u)).length :=
len_filter_or_and _ _ _
have z : (G.nodes.filter fun u => (inU G Y u && !inD G Y u && (G.nbrs u).any (C4.wpF G Y)) &&
(inD G Y u && isLow Y u)).length = 0 := by
refine len_filter_eq_zero _ (fun x => ?_)
cases inD G Y x <;> simp
have b : (G.nodes.filter fun u => (inU G Y u && !inD G Y u && (G.nbrs u).any (C4.wpF G Y)) ||
(inD G Y u && isLow Y u)).length ≤ (G.nodes.filter (inU G Y)).length := by
refine len_filter_mono _ (fun x hx => ?_)
simp only [Bool.or_eq_true, Bool.and_eq_true] at hx
rcases hx with hr | hs
· exact hr.1.1
· exact C4.inU_of_inD_low hs.1 hs.2
omega
unfold lowerZeroP
omega
/-- `|D| + |W'| ≤ L₀'`, where `W' = W \ D`. -/
theorem sum_D_W (G : Graph) (Y : Labels) :
(G.nodes.filter (inD G Y)).length + (G.nodes.filter (C4.wpF G Y)).length ≤
upperZeroP G Y := by
have hW : G.nodes.filter (C4.wpF G Y) = G.nodes.filter fun v => inW G Y v && !inD G Y v := rfl
rw [hW]
have e1 : (G.nodes.filter (inD G Y)).length + (G.nodes.filter fun v => inW G Y v && !inD G Y v).length =
(G.nodes.filter fun v => inD G Y v || (inW G Y v && !inD G Y v)).length +
(G.nodes.filter fun v => inD G Y v && (inW G Y v && !inD G Y v)).length :=
len_filter_or_and _ _ _
have z1 : (G.nodes.filter fun v => inD G Y v && (inW G Y v && !inD G Y v)).length = 0 := by
refine len_filter_eq_zero _ (fun x => ?_)
cases inD G Y x <;> simp
have e2 : (G.nodes.filter fun v => inD G Y v || (inW G Y v && !inD G Y v)).length ≤
(G.nodes.filter fun v => inW G Y v || (inD G Y v && isLow Y v)).length := by
refine len_filter_mono _ (fun x hx => ?_)
simp only [Bool.or_eq_true, Bool.and_eq_true, Bool.not_eq_true'] at hx ⊢
rcases hx with hd | ⟨hw, hnd⟩
· cases hl : isLow Y x
· exact Or.inl (C4.inW_of_inD_high hd hl)
· exact Or.inr ⟨hd, rfl⟩
· exact Or.inl hw
have e3 : (G.nodes.filter (inW G Y)).length + (G.nodes.filter fun v => inD G Y v && isLow Y v).length =
(G.nodes.filter fun v => inW G Y v || (inD G Y v && isLow Y v)).length +
(G.nodes.filter fun v => inW G Y v && (inD G Y v && isLow Y v)).length :=
len_filter_or_and _ _ _
have z3 : (G.nodes.filter fun v => inW G Y v && (inD G Y v && isLow Y v)).length = 0 := by
refine len_filter_eq_zero _ (fun x => ?_)
cases hw : inW G Y x with
| false => simp
| true =>
have := (C4.inW_iff.1 hw).1
simp [this]
unfold upperZeroP
omega
/-! ## 8. The connector bags `C_j` -/
/-- Size of `C_j`: `|D| + (|P| - c(j-1)) + j`, with `c` the number of items covered by the
first `j - 1` connector elements; Lemma A.33 (`lem:connector-linear`) bounds `c` from below. -/
theorem cs_card {G : Graph} {Y : Labels} {q : List Nat}
{j : Nat} (hj : j ≤ q.length) (hqlen : q.length = (G.nodes.filter (C4.wpF G Y)).length)
(hcon : ∀ J, J ≤ (G.nodes.filter (C4.wpF G Y)).length →
(J : ℤ) - ((C4.pSet G Y).filter (fun u => subsetB (C4.eSet G Y u) (q.take J))).length ≤
max 0 (((G.nodes.filter (C4.wpF G Y)).length : ℤ) - (C4.pSet G Y).length) + 1) :
((C4.csB G Y q j).toFinset.card : ℤ) ≤
((G.nodes.filter (inD G Y)).length : ℤ) + (C4.pSet G Y).length +
max 0 (((G.nodes.filter (C4.wpF G Y)).length : ℤ) - (C4.pSet G Y).length) + 2 := by
have hl : (C4.csB G Y q j).toFinset.card ≤ (C4.csB G Y q j).length := card_le_length _
have hl' : ((C4.csB G Y q j).toFinset.card : ℤ) ≤ ((C4.csB G Y q j).length : ℤ) := by
exact_mod_cast hl
refine hl'.trans ?_
unfold C4.csB
rw [List.length_append, List.length_append, List.length_take]
have hA : ((C4.pSet G Y).filter (fun u => !subsetB (C4.eSet G Y u) (q.take (j - 1)))).length +
((C4.pSet G Y).filter (fun u => subsetB (C4.eSet G Y u) (q.take (j - 1)))).length =
(C4.pSet G Y).length :=
len_filter_not_add _ _
rcases Nat.eq_zero_or_pos j with rfl | hjpos
· have h0 : (0 : ℤ) ≤ max 0 (((G.nodes.filter (C4.wpF G Y)).length : ℤ) - (C4.pSet G Y).length) :=
le_max_left _ _
have hm : min 0 q.length = 0 := Nat.zero_min _
rw [hm]
omega
· have hc := hcon (j - 1) (by omega)
have htk : min j q.length ≤ j := min_le_left _ _
omega
/-- The connector bag bound in the form used by the main theorem. -/
theorem cs_bag_le {G : Graph} {Y : Labels} {q : List Nat}
{j : Nat} (hj : j ≤ q.length) (hqlen : q.length = (G.nodes.filter (C4.wpF G Y)).length)
(hcon : ∀ J, J ≤ (G.nodes.filter (C4.wpF G Y)).length →
(J : ℤ) - ((C4.pSet G Y).filter (fun u => subsetB (C4.eSet G Y u) (q.take J))).length ≤
max 0 (((G.nodes.filter (C4.wpF G Y)).length : ℤ) - (C4.pSet G Y).length) + 1) :
((C4.csB G Y q j).toFinset.card : ℤ) ≤ ((max (lowerZeroP G Y) (upperZeroP G Y) : ℕ) : ℤ) + 2 := by
have hz := cs_card hj hqlen hcon
have hDA := sum_D_P G Y
have hDQ := sum_D_W G Y
have hKA : ((G.nodes.filter (inD G Y)).length : ℤ) + ((C4.pSet G Y).length : ℤ) ≤
((max (lowerZeroP G Y) (upperZeroP G Y) : ℕ) : ℤ) := by
have : (G.nodes.filter (inD G Y)).length + (C4.pSet G Y).length ≤
max (lowerZeroP G Y) (upperZeroP G Y) := hDA.trans (le_max_left _ _)
exact_mod_cast this
have hKQ : ((G.nodes.filter (inD G Y)).length : ℤ) +
((G.nodes.filter (C4.wpF G Y)).length : ℤ) ≤
((max (lowerZeroP G Y) (upperZeroP G Y) : ℕ) : ℤ) := by
have : (G.nodes.filter (inD G Y)).length + (G.nodes.filter (C4.wpF G Y)).length ≤
max (lowerZeroP G Y) (upperZeroP G Y) := hDQ.trans (le_max_right _ _)
exact_mod_cast this
rcases le_total ((G.nodes.filter (C4.wpF G Y)).length : ℤ) ((C4.pSet G Y).length : ℤ) with h | h
· rw [max_eq_left (by omega)] at hz
omega
· rw [max_eq_right (by omega)] at hz
omega
end L5
open L5
/-! ## 9. The main theorem -/
/-- `switched_layout` (median-switched layout, Lemma 8.4 (`lem:median-layout`)) has width at most `w`
under the frontier hypotheses of `SwitchedLayoutWidth`, and its connector does not fall
back. Uses Lemma A.33 (`lem:connector-linear`, `ConnectorLemma10`) for the count of connector bags and the connector
no-fallback statement `ConnectorNoFallback` (`Spec.lean` §7). -/
theorem switchedLayoutWidth_of (hL10 : ConnectorLemma10) (hN : ConnectorNoFallback) :
SwitchedLayoutWidth := by
intro G hG hdeg Y hinj hnz w hinner houter hw
have hK0 : (0 : ℝ) ≤ ((max (lowerZeroP G Y) (upperZeroP G Y) : ℕ) : ℝ) := Nat.cast_nonneg _
have hw' : ((max (lowerZeroP G Y) (upperZeroP G Y) : ℕ) : ℝ) + 1 ≤ w := by
rw [Nat.cast_max]
exact hw
have hw0 : (0 : ℝ) ≤ w := by linarith
have hQsnd : (G.nodes.filter (C4.wpF G Y)).Nodup := hG.nodup.filter _
have hitems_ok : ∀ e ∈ (C4.pSet G Y).map (C4.eSet G Y),
e.Nodup ∧ 1 ≤ e.length ∧ e.length ≤ 2 ∧ ∀ z ∈ e, z ∈ G.nodes.filter (C4.wpF G Y) := by
intro e he
obtain ⟨u, hu, rfl⟩ := List.mem_map.1 he
obtain ⟨hun, hU, hD, x, hx, hxw⟩ := C4.mem_pSet.1 hu
refine ⟨(hG.nbrs_nodup u).filter _, List.length_pos_of_mem (List.mem_filter.2 ⟨hx, hxw⟩),
eSet_len_le hdeg hun hU hD, ?_⟩
intro z hz
obtain ⟨hz1, hz2⟩ := List.mem_filter.1 hz
exact List.mem_filter.2 ⟨hG.nbrs_sub u z hz1, hz2⟩
have hflag : (switchedLayoutF G Y).2 = false :=
hN (G.nodes.filter (C4.wpF G Y)) ((C4.pSet G Y).map (C4.eSet G Y)) hQsnd hitems_ok
obtain ⟨hperm, hcount⟩ :=
hL10 (G.nodes.filter (C4.wpF G Y)) ((C4.pSet G Y).map (C4.eSet G Y)) hQsnd hitems_ok
refine ⟨hflag, ?_⟩
rw [C4.switchedLayout_eq]
have hperm_o : (switchedOrder G Y).Perm G.nodes := switchedOrderPerm G Y
have hsplit : switchedOrder G Y = (switchedOrder G Y).filter (isLow Y) ++
(switchedOrder G Y).filter (fun x => !isLow Y x) :=
C4.lows_first (isLow Y) _ (C4.switchedOrder_pairwise G Y)
have hqmem : ∀ x, x ∈ connectorOrder (G.nodes.filter (C4.wpF G Y))
((C4.pSet G Y).map (C4.eSet G Y)) ↔ x ∈ G.nodes.filter (C4.wpF G Y) :=
fun x => hperm.mem_iff
have hOK : C4.OrdOK G Y (switchedOrder G Y)
(connectorOrder (G.nodes.filter (C4.wpF G Y)) ((C4.pSet G Y).map (C4.eSet G Y))) :=
⟨hperm_o, hsplit, hqmem⟩
have hs := switchedOrder_sorted G Y
have hqlen : (connectorOrder (G.nodes.filter (C4.wpF G Y))
((C4.pSet G Y).map (C4.eSet G Y))).length = (G.nodes.filter (C4.wpF G Y)).length :=
hperm.length_eq
have hcon : ∀ J, J ≤ (G.nodes.filter (C4.wpF G Y)).length →
(J : ℤ) - ((C4.pSet G Y).filter (fun u => subsetB (C4.eSet G Y u)
((connectorOrder (G.nodes.filter (C4.wpF G Y))
((C4.pSet G Y).map (C4.eSet G Y))).take J))).length ≤
max 0 (((G.nodes.filter (C4.wpF G Y)).length : ℤ) - (C4.pSet G Y).length) + 1 := by
intro J hJ
have h1 := hcount J hJ
rw [items_filter_len, List.length_map] at h1
exact h1
apply pdWidth_le_of _ w (by linarith)
intro B hB
rcases bag_cases hB with ⟨i, hi, rfl⟩ | rfl | ⟨j, hj, rfl⟩ | ⟨k, hk, rfl⟩
· exact inner_card hG hOK hinj hs hi hinner hw0
· have h1 : ((C4.cm1B G Y).toFinset.card : ℝ) ≤ ((lowerZeroP G Y : ℕ) : ℝ) := by
exact_mod_cast cm1_card G Y
have h2 : ((lowerZeroP G Y : ℕ) : ℝ) ≤
((max (lowerZeroP G Y) (upperZeroP G Y) : ℕ) : ℝ) := by
exact_mod_cast le_max_left _ _
linarith
· have hz := cs_bag_le hj hqlen hcon
have hfin : ∀ n : ℕ, (n : ℤ) ≤ ((max (lowerZeroP G Y) (upperZeroP G Y) : ℕ) : ℤ) + 2 →
(n : ℝ) ≤ w + 1 := by
intro n hn
have h3 : n ≤ max (lowerZeroP G Y) (upperZeroP G Y) + 2 := by omega
have h4 : (n : ℝ) ≤ ((max (lowerZeroP G Y) (upperZeroP G Y) : ℕ) : ℝ) + 2 := by
exact_mod_cast h3
linarith
exact hfin _ hz
· exact outer_card hG hOK hinj hs hnz hk houter
end CubicPathwidth.Alg
#print axioms CubicPathwidth.Alg.switchedLayoutWidth_of
Back to top