CubicPathwidth.Alg.Proofs2.R7Balanced
Source file CubicPathwidth/Alg/Proofs2/R7Balanced.lean of the Lean project (how it is built).
import CubicPathwidth.Alg.Plan2
import CubicPathwidth.Alg.Proofs.Targets
/-!
# R7: balanced elimination bag (`cl:alg-elim` and Claim A.30 (`cl:alg-balanced`), port form)
Route (no tree decompositions). Let `E_t` be the set of the first `t` eliminated vertices
of `reduce_record` (`ops.take t`). Let `k` be least such that `H[E_k]` has a component `K`
with more than `N/2` vertices, `v = v_k`, `X = {v} ∪ nb_k`. Every component `C` of `H - X`
has at most `N/2` vertices:
* if `C` misses `K`, then `|C| ≤ N - |K| < N/2`;
* otherwise `C` lies in a component `S` of `H[E_{k-1}]` (all of them have at most `N/2`
vertices by minimality), and the attachment of `S` lies in `X`: a neighbour `y` of `S`
outside `E_{k-1}` is adjacent in the record graph `G_{k-1}` to `v` (walk `v → S → y`
through `E_{k-1}`, invariant `St`), hence `y ∈ nb_k`.
Edges of the record graph are described by `W` (walks with interior in `E_t`).
-/
namespace CubicPathwidth.Alg.R7
open Graph
/-! ## Generic lemmas -/
theorem rtg_closed {α : Type} (r : α → α → Prop) (P : α → Prop)
(hP : ∀ p q, P p → r p q → P q) {p q : α} (h : Relation.ReflTransGen r p q)
(hp : P p) : P q := by
induction h with
| refl => exact hp
| tail _ hbc ih => exact hP _ _ ih hbc
theorem rtg_mono {α : Type} {r p : α → α → Prop} (h : ∀ a b, r a b → p a b) {a b : α}
(hab : Relation.ReflTransGen r a b) : Relation.ReflTransGen p a b := by
induction hab with
| refl => exact Relation.ReflTransGen.refl
| tail _ hbc ih => exact Relation.ReflTransGen.tail ih (h _ _ hbc)
/-! ## Walks with interior in a set -/
/-- `W H E a b`: a walk from `a` to `b` in `H` whose interior vertices all satisfy `E`. -/
inductive W (H : Graph) (E : Nat → Prop) : Nat → Nat → Prop
| adj {a b : Nat} : H.Adj a b → W H E a b
| step {a x b : Nat} : H.Adj a x → E x → W H E x b → W H E a b
theorem W.split {H : Graph} {E E' : Nat → Prop} {v : Nat}
(hE : ∀ x, E' x → E x ∨ x = v) :
∀ {a b : Nat}, W H E' a b → W H E a b ∨ (W H E a v ∧ W H E v b) := by
intro a b h
induction h with
| adj hab => exact Or.inl (W.adj hab)
| @step a x b hax hx _ ih =>
rcases hE x hx with hEx | hxv
· rcases ih with h1 | ⟨h1, h2⟩
· exact Or.inl (W.step hax hEx h1)
· exact Or.inr ⟨W.step hax hEx h1, h2⟩
· subst hxv
rcases ih with h1 | ⟨h1, h2⟩
· exact Or.inr ⟨W.adj hax, h1⟩
· exact Or.inr ⟨W.adj hax, h2⟩
theorem W.snoc {H : Graph} {E : Nat → Prop} {a b c : Nat} (h : W H E a b) :
E b → H.Adj b c → W H E a c := by
induction h with
| adj hab => intro hb hbc; exact W.step hab hb (W.adj hbc)
| step hax hx _ ih => intro hb hbc; exact W.step hax hx (ih hb hbc)
theorem W.of_rtg {H : Graph} {E : Nat → Prop} (x0 x : Nat)
(h : Relation.ReflTransGen (fun p q => H.Adj p q ∧ E p ∧ E q) x0 x) :
∀ y, H.Adj x y → E x → W H E x0 y := by
induction h with
| refl => intro y hy _; exact W.adj hy
| @tail c d _ hcd ih =>
intro y hdy hEd
exact W.snoc (ih d hcd.1 hcd.2.1) hcd.2.2 hdy
/-! ## One reduction step -/
theorem redStep_wf {G : Graph} (hG : G.WF) (v : Nat) : (redStep G v).WF := by
have hR := removeNodeSpec G v hG
unfold redStep
split
next a b hab =>
have hnd := hG.nbrs_nodup v
rw [hab] at hnd
have hne : a ≠ b := by simpa using hnd
exact (addEdgeSpec _ a b hR.1 hne).1
next => exact hR.1
theorem redStep_nodes {G : Graph} (hG : G.WF) (v x : Nat) (hx : x ∈ (redStep G v).nodes) :
x ∈ G.nodes ∧ x ≠ v := by
have hR := removeNodeSpec G v hG
unfold redStep at hx
split at hx
next a b hab =>
have ha : a ∈ G.nbrs v := by rw [hab]; simp
have hb : b ∈ G.nbrs v := by rw [hab]; simp
have hne : a ≠ b := by
have hnd := hG.nbrs_nodup v
rw [hab] at hnd
simpa using hnd
have hav : a ≠ v := fun h => hG.loopless v (by rw [h] at ha; exact ha)
have hbv : b ≠ v := fun h => hG.loopless v (by rw [h] at hb; exact hb)
rw [(addEdgeSpec _ a b hR.1 hne).2.1 x, hR.2.1 x] at hx
rcases hx with ⟨h1, h2⟩ | h1 | h1
· exact ⟨h1, h2⟩
· subst h1; exact ⟨hG.nbrs_sub v _ ha, hav⟩
· subst h1; exact ⟨hG.nbrs_sub v _ hb, hbv⟩
next =>
exact (hR.2.1 x).1 hx
theorem redStep_adj_of {G : Graph} (hG : G.WF) {v x y : Nat} (hxv : x ≠ v) (hyv : y ≠ v)
(h : G.Adj x y) : (redStep G v).Adj x y := by
have hR := removeNodeSpec G v hG
unfold redStep
split
next a b hab =>
have hnd := hG.nbrs_nodup v
rw [hab] at hnd
have hne : a ≠ b := by simpa using hnd
rw [(addEdgeSpec _ a b hR.1 hne).2.2 x y]
exact Or.inl ((hR.2.2 x y).2 ⟨h, hxv, hyv⟩)
next => exact (hR.2.2 x y).2 ⟨h, hxv, hyv⟩
theorem redStep_adj_pair {G : Graph} (hG : G.WF) (v a b : Nat)
(ha : a ∈ G.nbrs v) (hb : b ∈ G.nbrs v) (hab : a ≠ b) (hlen : (G.nbrs v).length ≤ 2) :
(redStep G v).Adj a b := by
have hR := removeNodeSpec G v hG
have hnd := hG.nbrs_nodup v
obtain ⟨p, q, hpq⟩ : ∃ p q, G.nbrs v = [p, q] := by
rcases hL : G.nbrs v with _ | ⟨p, _ | ⟨q, _ | ⟨r, l⟩⟩⟩
· rw [hL] at ha; simp at ha
· rw [hL] at ha hb
simp only [List.mem_cons, List.not_mem_nil, or_false] at ha hb
exact absurd (ha.trans hb.symm) hab
· exact ⟨p, q, rfl⟩
· rw [hL] at hlen
simp only [List.length_cons] at hlen
omega
have hpq' : p ≠ q := by
rw [hpq] at hnd
simpa using hnd
simp only [redStep, hpq]
rw [(addEdgeSpec _ p q hR.1 hpq').2.2 a b]
rw [hpq] at ha hb
simp only [List.mem_cons, List.not_mem_nil, or_false] at ha hb
rcases ha with h1 | h1 <;> rcases hb with h2 | h2
· exact absurd (h1.trans h2.symm) hab
· exact Or.inr (Or.inl ⟨h1, h2⟩)
· exact Or.inr (Or.inr ⟨h1, h2⟩)
· exact absurd (h1.trans h2.symm) hab
theorem nbrs_len_le {G : Graph} (hG : G.WF) {v : Nat} {nb : List Nat}
(hlen : nb.length ≤ 2) (hadj : ∀ x, x ∈ nb ↔ G.Adj v x) : (G.nbrs v).length ≤ 2 := by
have hsub : G.nbrs v ⊆ nb := by
intro x hx
exact (hadj x).2 hx
exact le_trans (((hG.nbrs_nodup v).subperm hsub).length_le) hlen
/-! ## Elimination sets along the record -/
/-- Membership of `x` in the set of vertices eliminated by the first `t` operations. -/
def elimKeep (ops : List Op) (t : Nat) (x : Nat) : Bool :=
(redVertices (ops.take t)).contains x
/-- Propositional form of `elimKeep`. -/
def elimSet (ops : List Op) (t : Nat) (x : Nat) : Prop := elimKeep ops t x = true
theorem elimSet_succ {ops : List Op} {t v : Nat} {nb : List Nat}
(hop : ops[t]? = some (Op.red v nb)) (x : Nat) :
elimSet ops (t + 1) x ↔ elimSet ops t x ∨ x = v := by
unfold elimSet elimKeep
rw [List.take_add_one, hop]
simp [redVertices]
theorem elimKeep_of_le (ops : List Op) {t : Nat} (h : ops.length ≤ t) :
elimKeep ops t = elimKeep ops ops.length := by
unfold elimKeep
rw [List.take_of_length_le h, List.take_length]
theorem elimSet_zero (ops : List Op) (x : Nat) : ¬ elimSet ops 0 x := by
unfold elimSet elimKeep
simp [redVertices]
/-! ## Invariant of the record -/
/-- The record graph after the first `t` operations: a well-formed graph `G` with
`OpsRecord G (ops.drop t) R`, no vertex eliminated so far, and whose adjacency among
the vertices not eliminated so far is given by walks in `H` through eliminated vertices. -/
structure St (H : Graph) (ops : List Op) (R : Graph) (t : Nat) (G : Graph) : Prop where
wf : G.WF
recd : OpsRecord G (ops.drop t) R
elim : ∀ x, elimSet ops t x → x ∉ G.nodes
walk : ∀ a b, ¬ elimSet ops t a → ¬ elimSet ops t b → a ≠ b →
W H (elimSet ops t) a b → G.Adj a b
theorem exists_St (H : Graph) (ops : List Op) (R G0 : Graph)
(hG0 : G0.WF) (hG0adj : ∀ a b, G0.Adj a b ↔ H.Adj a b)
(hrec : OpsRecord G0 ops R) (hred : ∀ o ∈ ops, ∃ v nb, o = Op.red v nb) :
∀ t, t ≤ ops.length → ∃ G, St H ops R t G := by
intro t
induction t with
| zero =>
intro _
refine ⟨G0, ⟨hG0, by simpa using hrec, fun x hx => absurd hx (elimSet_zero ops x), ?_⟩⟩
intro a b _ _ _ hw
cases hw with
| adj h => exact (hG0adj a b).2 h
| step _ hx _ => exact absurd hx (elimSet_zero ops _)
| succ t ih =>
intro ht
obtain ⟨G, hG⟩ := ih (Nat.le_of_succ_le ht)
have hlt : t < ops.length := Nat.lt_of_succ_le ht
have hmem : ops[t] ∈ ops := List.getElem_mem hlt
obtain ⟨v, nb, hop⟩ := hred _ hmem
have hop' : ops[t]? = some (Op.red v nb) := by
rw [List.getElem?_eq_getElem hlt, hop]
have hdrop : ops.drop t = Op.red v nb :: ops.drop (t + 1) := by
rw [List.drop_eq_getElem_cons hlt, hop]
have hrt := hG.recd
rw [hdrop] at hrt
obtain ⟨hv, hnd, hlen, hadj, hrest⟩ := hrt
have hsucc := elimSet_succ hop'
refine ⟨redStep G v, redStep_wf hG.wf v, hrest, ?_, ?_⟩
· intro x hx hmem'
rcases (hsucc x).1 hx with h | h
· exact hG.elim x h (redStep_nodes hG.wf v x hmem').1
· exact (redStep_nodes hG.wf v x hmem').2 h
· intro a b ha hb hab hw
have ha' : ¬ elimSet ops t a ∧ a ≠ v := by
refine ⟨fun h => ha ((hsucc a).2 (Or.inl h)), fun h => ha ((hsucc a).2 (Or.inr h))⟩
have hb' : ¬ elimSet ops t b ∧ b ≠ v := by
refine ⟨fun h => hb ((hsucc b).2 (Or.inl h)), fun h => hb ((hsucc b).2 (Or.inr h))⟩
have hvE : ¬ elimSet ops t v := fun h => hG.elim v h hv
rcases W.split (E := elimSet ops t) (E' := elimSet ops (t + 1)) (v := v)
(fun x hx => (hsucc x).1 hx) hw with h | ⟨h1, h2⟩
· exact redStep_adj_of hG.wf ha'.2 hb'.2 (hG.walk a b ha'.1 hb'.1 hab h)
· have hav : G.Adj a v := hG.walk a v ha'.1 hvE ha'.2 h1
have hvb : G.Adj v b := hG.walk v b hvE hb'.1 (Ne.symm hb'.2) h2
have hav' : a ∈ G.nbrs v := hG.wf.symm a v hav
have hlen2 := nbrs_len_le hG.wf hlen hadj
exact redStep_adj_pair hG.wf v a b hav' hvb hab hlen2
/-! ## Component facts -/
theorem comp_nodup {G : Graph} (hG : G.WF) {c : List Nat} (hc : c ∈ G.components) :
c.Nodup := by
have hp := (componentsSpec G hG).1
have hnd : G.components.flatten.Nodup := hp.nodup_iff.mpr hG.nodup
exact (List.nodup_flatten.mp hnd).1 c hc
theorem comp_mem_nodes {G : Graph} (hG : G.WF) {c : List Nat} (hc : c ∈ G.components)
{x : Nat} (hx : x ∈ c) : x ∈ G.nodes := by
have hp := (componentsSpec G hG).1
exact hp.subset (List.mem_flatten.mpr ⟨c, hc, hx⟩)
theorem comp_exists_mem {G : Graph} (hG : G.WF) {c : List Nat} (hc : c ∈ G.components) :
∃ x, x ∈ c :=
List.exists_mem_of_ne_nil c ((componentsSpec G hG).2.1 c hc)
theorem comp_closed {G : Graph} (hG : G.WF) {c : List Nat} (hc : c ∈ G.components)
{x : Nat} (hx : x ∈ c) {y : Nat} (hxy : G.Adj x y) : y ∈ c :=
(componentsSpec G hG).2.2 c hc x hx y hxy
theorem comp_exists {G : Graph} (hG : G.WF) {x : Nat} (hx : x ∈ G.nodes) :
∃ c ∈ G.components, x ∈ c := by
have hp := (componentsSpec G hG).1
obtain ⟨c, hc, hxc⟩ := List.mem_flatten.mp (hp.symm.subset hx)
exact ⟨c, hc, hxc⟩
/-- Members of a component of an induced graph are nodes with the right keep value. -/
theorem comp_keep {H : Graph} (hH : H.WF) {keep : Nat → Bool} {c : List Nat}
(hc : c ∈ (H.induced keep).components) {x : Nat} (hx : x ∈ c) :
x ∈ H.nodes ∧ keep x = true :=
(inducedSpec H keep hH).2.1 x |>.1 (comp_mem_nodes (inducedSpec H keep hH).1 hc hx)
theorem rtg_ind {H : Graph} (hH : H.WF) {keep : Nat → Bool} {x y : Nat}
(h : Relation.ReflTransGen (H.induced keep).Adj x y) :
Relation.ReflTransGen (fun p q => H.Adj p q ∧ keep p = true ∧ keep q = true) x y :=
rtg_mono (fun p q hpq => (inducedSpec H keep hH).2.2 p q |>.1 hpq) h
/-- Absorption: a component `C` of `H[kZ]` that meets a set `S` closed under `H`-edges
into `kZ` lies in `S`. -/
theorem comp_absorb {H : Graph} (hH : H.WF) (hConn : ComponentsConnected)
{kZ : Nat → Bool} {S C : List Nat} {u : Nat}
(hC : C ∈ (H.induced kZ).components) (huS : u ∈ S) (huC : u ∈ C)
(hcl : ∀ p q, p ∈ S → H.Adj p q → kZ q = true → q ∈ S) :
∀ w ∈ C, w ∈ S := by
intro w hw
have hR := rtg_ind hH (hConn (H.induced kZ) (inducedSpec H kZ hH).1 C hC u huC w hw)
exact rtg_closed (fun p q => H.Adj p q ∧ kZ p = true ∧ kZ q = true) (fun x => x ∈ S)
(fun p q hp hpq => hcl p q hp hpq.1 hpq.2.2) hR huS
theorem len_le_of_sub {A B : List Nat} (hA : A.Nodup) (_hB : B.Nodup)
(hsub : ∀ w ∈ A, w ∈ B) : A.length ≤ B.length :=
(hA.subperm hsub).length_le
theorem len_add_le {H : Graph} {A B : List Nat} (hA : A.Nodup) (hB : B.Nodup)
(hd : ∀ a ∈ A, a ∉ B) (hsub : ∀ a ∈ A ++ B, a ∈ H.nodes) :
A.length + B.length ≤ H.numNodes := by
have hnd : (A ++ B).Nodup :=
List.nodup_append.2 ⟨hA, hB, fun a ha b hb hab => hd a ha (hab ▸ hb)⟩
have := (hnd.subperm hsub).length_le
simp only [List.length_append] at this
exact this
/-! ## The balanced bag -/
theorem keep_notin {X : List Nat} {u : Nat} (h : (fun y => !X.contains y) u = true) :
u ∉ X := by
intro hu
simp [hu] at h
/-- `H[E_t]` has a component with more than `N/2` vertices. -/
def Big (H : Graph) (ops : List Op) (t : Nat) : Prop :=
∃ c ∈ (H.induced (elimKeep ops t)).components, H.numNodes < 2 * c.length
theorem not_big_zero (H : Graph) (hH : H.WF) (ops : List Op) : ¬ Big H ops 0 := by
rintro ⟨c, hc, _⟩
obtain ⟨x, hx⟩ := comp_exists_mem (inducedSpec H _ hH).1 hc
have := (comp_keep hH hc hx).2
exact elimSet_zero ops x this
theorem balanced_core (H : Graph) (hH : H.WF) (ops : List Op) (R : Graph)
(hred : ∀ o ∈ ops, ∃ v nb, o = Op.red v nb)
(hall : ∀ x ∈ H.nodes, elimSet ops ops.length x)
(hSt : ∀ t, t ≤ ops.length → ∃ G, St H ops R t G)
(hConn : ComponentsConnected) (hN : 1 ≤ H.numNodes) :
∃ X ∈ elimBags ops, ∀ c ∈ (H.induced fun v => !X.contains v).components,
2 * c.length ≤ H.numNodes := by
classical
by_cases hA : ∃ t, Big H ops t
· obtain ⟨k, hk, hmin⟩ : ∃ k, Big H ops k ∧ ∀ j < k, ¬ Big H ops j :=
⟨Nat.find hA, Nat.find_spec hA, fun j hj => Nat.find_min hA hj⟩
have hk0 : k ≠ 0 := fun h => not_big_zero H hH ops (h ▸ hk)
have hkM : k ≤ ops.length := by
by_contra hcon
apply hmin ops.length (by omega)
unfold Big at hk ⊢
rw [elimKeep_of_le ops (by omega)] at hk
exact hk
obtain ⟨j, rfl⟩ : ∃ j, k = j + 1 := ⟨k - 1, by omega⟩
have hjlt : j < ops.length := by omega
have hmemj : ops[j] ∈ ops := List.getElem_mem hjlt
obtain ⟨v, nb, hop⟩ := hred _ hmemj
have hop' : ops[j]? = some (Op.red v nb) := by
rw [List.getElem?_eq_getElem hjlt, hop]
have hmem : Op.red v nb ∈ ops := by rw [← hop]; exact hmemj
obtain ⟨G, hG⟩ := hSt j (by omega)
have hdrop : ops.drop j = Op.red v nb :: ops.drop (j + 1) := by
rw [List.drop_eq_getElem_cons hjlt, hop]
have hrt := hG.recd
rw [hdrop] at hrt
obtain ⟨hv, hnd, hlen, hadj, hrest⟩ := hrt
have hXmem : v :: nb ∈ elimBags ops :=
List.mem_filterMap.2 ⟨Op.red v nb, hmem, rfl⟩
refine ⟨v :: nb, hXmem, ?_⟩
intro C hC
have hCnd : C.Nodup := comp_nodup (inducedSpec H (fun y => !(v :: nb).contains y) hH).1 hC
obtain ⟨K, hKmem, hKbig⟩ := hk
have hKnd : K.Nodup := comp_nodup (inducedSpec H (elimKeep ops (j + 1)) hH).1 hKmem
have hmin' : ¬ Big H ops j := hmin j (Nat.lt_succ_self j)
by_cases hCK : ∃ u ∈ C, u ∈ K
· obtain ⟨u, huC, huK⟩ := hCK
have huZ := comp_keep hH hC huC
have huX : u ≠ v ∧ u ∉ nb := by
have hnotin : u ∉ v :: nb := keep_notin huZ.2
exact ⟨fun h => hnotin (h ▸ List.mem_cons_self), fun h => hnotin (List.mem_cons_of_mem _ h)⟩
have huE : elimSet ops j u := by
have h1 : elimSet ops (j + 1) u := (comp_keep hH hKmem huK).2
rcases (elimSet_succ hop' u).1 h1 with h | h
· exact h
· exact absurd h huX.1
obtain ⟨S0, hS0mem, huS0⟩ := comp_exists (inducedSpec H (elimKeep ops j) hH).1
((inducedSpec H (elimKeep ops j) hH).2.1 u |>.2 ⟨huZ.1, huE⟩)
have hS0nd : S0.Nodup := comp_nodup (inducedSpec H (elimKeep ops j) hH).1 hS0mem
have hS0size : 2 * S0.length ≤ H.numNodes := by
by_contra hc
exact hmin' ⟨S0, hS0mem, by omega⟩
-- (i) the component `S0` of `H[E_j]` containing `u` is attached to `v`
have hx0 : ∃ x0 ∈ S0, H.Adj x0 v := by
by_contra hno
push Not at hno
have hcl0 : ∀ p q, p ∈ S0 → H.Adj p q → elimKeep ops (j + 1) q = true → q ∈ S0 := by
intro p q hp hpq hq
rcases (elimSet_succ hop' q).1 hq with h | h
· exact comp_closed (inducedSpec H (elimKeep ops j) hH).1 hS0mem hp
(((inducedSpec H (elimKeep ops j) hH).2.2 p q).2
⟨hpq, (comp_keep hH hS0mem hp).2, h⟩)
· subst h
exact absurd hpq (hno p hp)
have hKS := comp_absorb hH hConn hKmem huS0 huK hcl0
have := len_le_of_sub hKnd hS0nd hKS
omega
-- (ii) attachment: every outside neighbour of `S0` lies in `X`
have hatt : ∀ x ∈ S0, ∀ y, H.Adj x y → ¬ elimSet ops j y → y ∈ v :: nb := by
intro x hx y hxy hyE
by_cases hyv : y = v
· exact List.mem_cons.2 (Or.inl hyv)
· obtain ⟨x0, hx0, hx0v⟩ := hx0
have hvx0 : H.Adj v x0 := hH.symm x0 v hx0v
have hrtg := rtg_ind hH
(hConn (H.induced (elimKeep ops j)) (inducedSpec H (elimKeep ops j) hH).1 S0 hS0mem
x0 hx0 x hx)
have hWx : W H (elimSet ops j) x0 y :=
W.of_rtg (E := elimSet ops j) x0 x hrtg y hxy (comp_keep hH hS0mem hx).2
have hWv : W H (elimSet ops j) v y :=
W.step hvx0 (comp_keep hH hS0mem hx0).2 hWx
have hvE : ¬ elimSet ops j v := fun h => hG.elim v h hv
have hGadj : G.Adj v y := hG.walk v y hvE hyE (Ne.symm hyv) hWv
exact List.mem_cons_of_mem _ ((hadj y).2 hGadj)
-- (iii) `S0` is closed outside `X`; `C` lies in `S0`
have hcl : ∀ p q, p ∈ S0 → H.Adj p q →
(fun y => !(v :: nb).contains y) q = true → q ∈ S0 := by
intro p q hp hpq hq
have hqX : q ∉ v :: nb := keep_notin hq
by_cases hE : elimSet ops j q
· exact comp_closed (inducedSpec H (elimKeep ops j) hH).1 hS0mem hp
(((inducedSpec H (elimKeep ops j) hH).2.2 p q).2 ⟨hpq, (comp_keep hH hS0mem hp).2, hE⟩)
· exact absurd (hatt p hp q hpq hE) hqX
have hCS0 := comp_absorb hH hConn hC huS0 huC hcl
have := len_le_of_sub hCnd hS0nd hCS0
omega
· push Not at hCK
have hCH : ∀ w ∈ C, w ∈ H.nodes := fun w hw => (comp_keep hH hC hw).1
have hKH : ∀ w ∈ K, w ∈ H.nodes := fun w hw => (comp_keep hH hKmem hw).1
have hsum := len_add_le (H := H) hCnd hKnd (fun a ha hb => hCK a ha hb)
(fun a ha => (List.mem_append.1 ha).elim (hCH a) (hKH a))
omega
· -- no component of `H[E_t]` is big: in particular `H` itself
have hBM : ¬ Big H ops ops.length := fun h => hA ⟨_, h⟩
obtain ⟨x, hx⟩ : ∃ x, x ∈ H.nodes := by
cases hn : H.nodes with
| nil => simp [Graph.numNodes, hn] at hN
| cons x _ => exact ⟨x, by simp⟩
have hxE := hall x hx
obtain ⟨nb, hnb⟩ : ∃ nb, Op.red x nb ∈ ops := by
unfold elimSet elimKeep at hxE
rw [List.take_length] at hxE
have hmem := (List.contains_iff_mem).1 hxE
unfold redVertices at hmem
obtain ⟨a, ha, hfa⟩ := List.mem_filterMap.1 hmem
cases a with
| red w nb' =>
simp only [Option.some.injEq] at hfa
subst hfa
exact ⟨nb', ha⟩
| del w => simp at hfa
refine ⟨x :: nb, List.mem_filterMap.2 ⟨Op.red x nb, hnb, rfl⟩, ?_⟩
intro C hC
have hCnd : C.Nodup := comp_nodup (inducedSpec H (fun y => !(x :: nb).contains y) hH).1 hC
obtain ⟨u, huC⟩ := comp_exists_mem (inducedSpec H (fun y => !(x :: nb).contains y) hH).1 hC
have huZ := comp_keep hH hC huC
obtain ⟨S0, hS0mem, huS0⟩ := comp_exists (inducedSpec H (elimKeep ops ops.length) hH).1
((inducedSpec H (elimKeep ops ops.length) hH).2.1 u |>.2 ⟨huZ.1, hall u huZ.1⟩)
have hS0size : 2 * S0.length ≤ H.numNodes := by
by_contra hc
exact hBM ⟨S0, hS0mem, by omega⟩
have hcl : ∀ p q, p ∈ S0 → H.Adj p q →
(fun y => !(x :: nb).contains y) q = true → q ∈ S0 := by
intro p q hp hpq _hq
have hqH : q ∈ H.nodes := hH.nbrs_sub p q hpq
exact comp_closed (inducedSpec H (elimKeep ops ops.length) hH).1 hS0mem hp
(((inducedSpec H (elimKeep ops ops.length) hH).2.2 p q).2
⟨hpq, (comp_keep hH hS0mem hp).2, hall q hqH⟩)
have hCS0 := comp_absorb hH hConn hC huS0 huC hcl
have := len_le_of_sub hCnd (comp_nodup (inducedSpec H _ hH).1 hS0mem) hCS0
omega
theorem reduceLoop_red (fuel : Nat) : ∀ (G : Graph) (stack : List Nat) (opsRev : List Op),
(∀ o ∈ opsRev, ∃ v nb, o = Op.red v nb) →
∀ o ∈ (reduceLoop fuel G stack opsRev).2.1, ∃ v nb, o = Op.red v nb := by
induction fuel with
| zero =>
intro G stack opsRev h o ho
cases stack with
| nil => simp only [reduceLoop] at ho; exact h o (List.mem_reverse.1 ho)
| cons _ _ => simp only [reduceLoop] at ho; exact h o (List.mem_reverse.1 ho)
| succ f ih =>
intro G stack opsRev h o ho
cases stack with
| nil => simp only [reduceLoop] at ho; exact h o (List.mem_reverse.1 ho)
| cons v rest =>
simp only [reduceLoop] at ho
split at ho
· exact ih _ _ _ h o ho
· refine ih _ _ _ ?_ o ho
intro o' ho'
rcases List.mem_cons.1 ho' with rfl | ho''
· exact ⟨v, _, rfl⟩
· exact h o' ho''
theorem reduceRecord_red (G : Graph) : ∀ o ∈ (reduceRecord G).2, ∃ v nb, o = Op.red v nb := by
intro o ho
simp only [reduceRecord, reduceRecordF] at ho
exact reduceLoop_red _ _ _ [] (by simp) o ho
/-! ## Main theorem -/
theorem balancedElimBag_aux (hMax : ReduceRecordMaximal)
(hConn : ComponentsConnected) : BalancedElimBag := by
unfold BalancedElimBag
intro H hH hN hEmpty
have hI := inducedSpec H (fun _ => true) hH
have hG0 : H.copy.WF := hI.1
have hG0adj : ∀ a b, H.copy.Adj a b ↔ H.Adj a b := by
intro a b
show (H.induced fun _ => true).Adj a b ↔ H.Adj a b
rw [hI.2.2 a b]
simp
have hrec : OpsRecord H.copy (reduceRecord H.copy).2 (reduceRecord H.copy).1 :=
(hMax H.copy hG0).1
have hred := reduceRecord_red H.copy
have hspec := reduceRecordSpec H.copy hG0
have hnil : (reduceRecord H.copy).1.nodes = [] := by
have h0 : (reduceRecord H.copy).1.nodes.length = 0 := hEmpty
exact List.length_eq_zero_iff.1 h0
have hall : ∀ x ∈ H.nodes, elimSet (reduceRecord H.copy).2 (reduceRecord H.copy).2.length x := by
intro x hx
have hxc : x ∈ H.copy.nodes := (hI.2.1 x).2 ⟨hx, rfl⟩
rcases hspec.2.2.2.2 x hxc with h | h
· rw [hnil] at h
exact absurd h List.not_mem_nil
· unfold elimSet elimKeep
rw [List.take_length]
simp [h]
exact balanced_core H hH _ _ hred hall
(fun t ht => exists_St H _ _ H.copy hG0 hG0adj hrec hred t ht) hConn hN
end CubicPathwidth.Alg.R7
namespace CubicPathwidth.Alg
set_option linter.unusedVariables false in
/-- `R7` (`cl:alg-elim` and Claim A.30 (`cl:alg-balanced`)): some elimination bag of `reduce_record`
is a balanced separator. Route without tree decompositions (see the module docstring of
`CubicPathwidth.Alg.R7`). The hypotheses `hSim`, `hCongr`, `hApp` are part of the planned
signature and are not needed by this proof (the attachment facts come from the record
itself, see `R7.balanced_core`); they are kept unused. -/
theorem balancedElimBag_of (hSim : TorsoSim) (hMax : ReduceRecordMaximal)
(hConn : ComponentsConnected) (hCongr : OpsRecordCongr) (hApp : OpsRecordAppend) :
BalancedElimBag :=
R7.balancedElimBag_aux hMax hConn
end CubicPathwidth.Alg
#print axioms CubicPathwidth.Alg.balancedElimBag_of
Back to top