CubicPathwidth.Alg.Proofs.C7Undo
Source file CubicPathwidth/Alg/Proofs/C7Undo.lean of the Lean project (how it is built).
import CubicPathwidth.Alg.Spec
/-!
# C7: `UndoValid` (validity of `undo`, Lemma A.28 (`lem:undo`))
Proof of `undoValid_of`, with all hypotheses supplied by other tasks. Helpers live in
the namespace `CubicPathwidth.Alg.C7`.
-/
noncomputable section
namespace CubicPathwidth.Alg
open Graph
namespace C7
/-! ## 1. Basic facts about `InBag` and index convexity -/
/-- Index convexity: the positions of the bags containing `v` form an interval.
This is the second clause of `ValidPD`, stated for an arbitrary list of bags. -/
def ConvL (L : List Bag) (v : Nat) : Prop :=
∀ i j k, i ≤ j → j ≤ k → InBag L i v → InBag L k v → InBag L j v
theorem inBag_append (X Y : List Bag) (i v : Nat) :
InBag (X ++ Y) i v ↔
(i < X.length ∧ InBag X i v) ∨ (X.length ≤ i ∧ InBag Y (i - X.length) v) := by
unfold InBag
by_cases h : i < X.length
· rw [List.getElem?_append_left h]
constructor
· intro h'; exact Or.inl ⟨h, h'⟩
· rintro (⟨_, h'⟩ | ⟨h2, _⟩)
· exact h'
· omega
· rw [List.getElem?_append_right (by omega)]
constructor
· intro h'; exact Or.inr ⟨by omega, h'⟩
· rintro (⟨h1, _⟩ | ⟨_, h'⟩)
· omega
· exact h'
theorem inBag_lt {L : List Bag} {i : Nat} {v : Nat} (h : InBag L i v) : i < L.length := by
obtain ⟨B, hB, _⟩ := h
exact (List.getElem?_eq_some_iff.1 hB).1
theorem inBag_mem {L : List Bag} {i v : Nat} (h : InBag L i v) : ∃ B ∈ L, v ∈ B := by
obtain ⟨B, hB, hv⟩ := h
exact ⟨B, List.mem_of_getElem? hB, hv⟩
theorem inBag_of_mem {L : List Bag} {B : Bag} {v : Nat} (hB : B ∈ L) (hv : v ∈ B) :
∃ i, InBag L i v := by
obtain ⟨i, hi, rfl⟩ := List.mem_iff_getElem.1 hB
exact ⟨i, _, List.getElem?_eq_getElem hi, hv⟩
theorem inBag_full {L : List Bag} {v : Nat} (h : ∀ B ∈ L, v ∈ B) {j : Nat}
(hj : j < L.length) : InBag L j v :=
⟨L[j], List.getElem?_eq_getElem hj, h _ (List.getElem_mem hj)⟩
theorem inBag_cons_succ (B : Bag) (L : List Bag) (i v : Nat) :
InBag (B :: L) (i + 1) v ↔ InBag L i v := Iff.rfl
theorem inBag_cons_zero (B : Bag) (L : List Bag) (v : Nat) :
InBag (B :: L) 0 v ↔ v ∈ B := by
unfold InBag
simp
theorem inBag_map (f : Bag → Bag) (L : List Bag) (v : Nat)
(h : ∀ B ∈ L, (v ∈ f B ↔ v ∈ B)) (i : Nat) :
InBag (L.map f) i v ↔ InBag L i v := by
unfold InBag
rw [List.getElem?_map]
cases hL : L[i]? with
| none => simp
| some B =>
have hB : B ∈ L := List.mem_of_getElem? hL
simp only [Option.map_some, Option.some.injEq, exists_eq_left']
exact h B hB
theorem convL_nil (v : Nat) : ConvL [] v := by
intro i j k _ _ hi _
exact absurd (inBag_lt hi) (by simp)
theorem convL_free {L : List Bag} {v : Nat} (h : ∀ B ∈ L, v ∉ B) : ConvL L v := by
intro i j k _ _ hi _
obtain ⟨B, hB, hv⟩ := inBag_mem hi
exact absurd hv (h B hB)
theorem convL_full {L : List Bag} {v : Nat} (h : ∀ B ∈ L, v ∈ B) : ConvL L v := by
intro i j k _ hjk _ hk
exact inBag_full h (Nat.lt_of_le_of_lt hjk (inBag_lt hk))
theorem convL_of_cons {B : Bag} {L : List Bag} {v : Nat} (h : ConvL (B :: L) v) :
ConvL L v := by
intro i j k hij hjk hi hk
have := h (i + 1) (j + 1) (k + 1) (by omega) (by omega)
((inBag_cons_succ B L i v).2 hi) ((inBag_cons_succ B L k v).2 hk)
exact (inBag_cons_succ B L j v).1 this
/-- Touching concatenation: if one side is free of `v`, or the left side ends with a bag
containing `v` and the right side starts with one, the concatenation is convex. -/
theorem convL_append {X Y : List Bag} {v : Nat} (hX : ConvL X v) (hY : ConvL Y v)
(h : (∀ B ∈ X, v ∉ B) ∨ (∀ B ∈ Y, v ∉ B) ∨
(InBag X (X.length - 1) v ∧ InBag Y 0 v)) :
ConvL (X ++ Y) v := by
intro i j k hij hjk hi hk
rw [inBag_append] at hi hk ⊢
rcases hi with ⟨hin, hi⟩ | ⟨hin, hi⟩ <;> rcases hk with ⟨hkn, hk⟩ | ⟨hkn, hk⟩
· -- i, k in X
exact Or.inl ⟨by omega, hX i j k hij hjk hi hk⟩
· -- i in X, k in Y: the touching cases
rcases h with h | h | ⟨hlast, hhead⟩
· obtain ⟨B, hB, hv⟩ := inBag_mem hi
exact absurd hv (h B hB)
· obtain ⟨B, hB, hv⟩ := inBag_mem hk
exact absurd hv (h B hB)
· by_cases hjn : j < X.length
· exact Or.inl ⟨hjn, hX i j (X.length - 1) hij (by omega) hi hlast⟩
· exact Or.inr ⟨by omega, hY 0 (j - X.length) (k - X.length) (Nat.zero_le _)
(by omega) hhead hk⟩
· -- i in Y, k in X: impossible since i ≤ k
omega
· -- both in Y
exact Or.inr ⟨by omega, hY (i - X.length) (j - X.length) (k - X.length)
(by omega) (by omega) hi hk⟩
/-- Mapping bags by `f` preserves convexity when `f` preserves membership of `v`. -/
theorem convL_map {L : List Bag} {v : Nat} (f : Bag → Bag)
(h : ∀ B ∈ L, (v ∈ f B ↔ v ∈ B)) (hL : ConvL L v) : ConvL (L.map f) v := by
intro i j k hij hjk hi hk
have hi' := (inBag_map f L v h i).1 hi
have hk' := (inBag_map f L v h k).1 hk
exact (inBag_map f L v h j).2 (hL i j k hij hjk hi' hk')
/-! ## 2. Block structure of `undoF`
`plans` is the list of plans `(S, P, flag, idx)`, one per component. The bags of
`undoF` before the final `++ D` are `outFrom plans 0 bagsR ++ tailOf plans`. -/
/-- A plan `(S, P, flag, idx)` of `undoF`. -/
abbrev Plan := List Nat × List Bag × Bool × Option Nat
/-- The inserted copies `P_bag ∪ B` for the plans attached at index `k`. -/
def copies (plans : List Plan) (k : Nat) (B : Bag) : List Bag :=
plans.flatMap fun ⟨_, P, _, idx⟩ => if idx == some k then P.map (bagUnion · B) else []
/-- Block `k` of `undo`: the bag `B = bagsR[k]`, followed by its inserted copies. -/
def blk (plans : List Plan) (k : Nat) (B : Bag) : List Bag := B :: copies plans k B
/-- The blocks of `bs` read from index `k` on (`out` of `undoF`). -/
def outFrom (plans : List Plan) : Nat → List Bag → List Bag
| _, [] => []
| k, B :: bs => blk plans k B ++ outFrom plans (k + 1) bs
/-- The tail: the bags `P` of the plans with `S = []`. -/
def tailOf (plans : List Plan) : List Bag :=
plans.flatMap fun ⟨S, P, _, _⟩ => if S.isEmpty then P else []
theorem copies_append (X Y : List Plan) (k : Nat) (B : Bag) :
copies (X ++ Y) k B = copies X k B ++ copies Y k B := by
unfold copies
rw [List.flatMap_append]
theorem copies_cons (p : Plan) (Y : List Plan) (k : Nat) (B : Bag) :
copies (p :: Y) k B = copies [p] k B ++ copies Y k B := by
rw [← copies_append]; rfl
theorem tailOf_append (X Y : List Plan) :
tailOf (X ++ Y) = tailOf X ++ tailOf Y := by
unfold tailOf
rw [List.flatMap_append]
theorem mem_copies {plans : List Plan} {k : Nat} {B X : Bag} :
X ∈ copies plans k B ↔ ∃ p ∈ plans, p.2.2.2 = some k ∧ ∃ Y ∈ p.2.1, X = Y ++ B := by
unfold copies
rw [List.mem_flatMap]
constructor
· rintro ⟨⟨S, P, f, idx⟩, hp, hX⟩
dsimp only at hX
by_cases hidx : (idx == some k) = true
· rw [if_pos hidx] at hX
obtain ⟨Y, hY, rfl⟩ := List.mem_map.1 hX
exact ⟨(S, P, f, idx), hp, beq_iff_eq.1 hidx, Y, hY, rfl⟩
· rw [if_neg hidx] at hX
exact absurd hX (List.not_mem_nil)
· rintro ⟨⟨S, P, f, idx⟩, hp, hidx, Y, hY, rfl⟩
refine ⟨(S, P, f, idx), hp, ?_⟩
have hidx' : (idx == some k) = true := beq_iff_eq.2 hidx
dsimp only
rw [if_pos hidx']
exact List.mem_map.2 ⟨Y, hY, rfl⟩
theorem mem_tailOf {plans : List Plan} {Y : Bag} :
Y ∈ tailOf plans ↔ ∃ p ∈ plans, p.1.isEmpty = true ∧ Y ∈ p.2.1 := by
unfold tailOf
rw [List.mem_flatMap]
constructor
· rintro ⟨⟨S, P, f, idx⟩, hp, hY⟩
dsimp only at hY
by_cases hS : S.isEmpty = true
· rw [if_pos hS] at hY
exact ⟨(S, P, f, idx), hp, hS, hY⟩
· rw [if_neg hS] at hY
exact absurd hY (List.not_mem_nil)
· rintro ⟨⟨S, P, f, idx⟩, hp, hS, hY⟩
refine ⟨(S, P, f, idx), hp, ?_⟩
dsimp only at hS hY ⊢
rw [if_pos hS]
exact hY
theorem mem_outFrom_of_mem (plans : List Plan) :
∀ (bs : List Bag) (k : Nat) (B : Bag), B ∈ bs → B ∈ outFrom plans k bs
| [], _, _, h => by simp at h
| B' :: bs, k, B, h => by
rcases List.mem_cons.1 h with rfl | h
· show B ∈ blk plans k B ++ outFrom plans (k + 1) bs
exact List.mem_append_left _ (List.mem_cons_self)
· show B ∈ blk plans k B' ++ outFrom plans (k + 1) bs
exact List.mem_append_right _ (mem_outFrom_of_mem plans bs (k + 1) B h)
/-- Copies at the position `k + j` of a bag `B` of `bs` lie in `outFrom plans k bs`. -/
theorem copies_sub_outFrom (plans : List Plan) :
∀ (bs : List Bag) (k j : Nat) (B X : Bag), bs[j]? = some B →
X ∈ copies plans (k + j) B → X ∈ outFrom plans k bs
| [], _, _, _, _, hj, _ => by simp at hj
| B' :: bs, k, j, B, X, hj, hX => by
cases j with
| zero =>
have hB : B' = B := by
simpa using hj
subst hB
show X ∈ blk plans k B' ++ outFrom plans (k + 1) bs
apply List.mem_append_left
exact List.mem_cons_of_mem _ (by simpa using hX)
| succ j =>
show X ∈ blk plans k B' ++ outFrom plans (k + 1) bs
apply List.mem_append_right
have hX' : X ∈ copies plans ((k + 1) + j) B := by
have : k + 1 + j = k + (j + 1) := by omega
rw [this]; exact hX
exact copies_sub_outFrom plans bs (k + 1) j B X (by simpa using hj) hX'
/-- The bags `out` of `undoF`, as written in the code (a `zipIdx` flatMap). -/
theorem zipIdx_outFrom (plans : List Plan) :
∀ (bs : List Bag) (k : Nat),
(bs.zipIdx k).flatMap (fun ⟨B, i⟩ =>
B :: plans.flatMap fun ⟨_, P, _, idx⟩ => if idx == some i then P.map (bagUnion · B) else [])
= outFrom plans k bs
| [], _ => by simp [outFrom]
| B :: bs, k => by
rw [List.zipIdx_cons, List.flatMap_cons, outFrom]
congr 1
exact zipIdx_outFrom plans bs (k + 1)
/-! ## 3. Index convexity of the block structure -/
theorem copies_vf {plans : List Plan} {v k : Nat} {B : Bag}
(hP : ∀ p ∈ plans, ∀ Y ∈ p.2.1, v ∉ Y) (hB : v ∉ B) :
∀ X ∈ copies plans k B, v ∉ X := by
intro X hX
obtain ⟨p, hp, _, Y, hY, rfl⟩ := mem_copies.1 hX
intro h
rcases List.mem_append.1 h with h | h
· exact hP p hp Y hY h
· exact hB h
/-- Inside a block, every bag contains `v` iff the bag `B` does (when no plan bag has `v`). -/
theorem blk_uniform {plans : List Plan} {v : Nat}
(hP : ∀ p ∈ plans, ∀ Y ∈ p.2.1, v ∉ Y) (k : Nat) (B : Bag) :
∀ X ∈ blk plans k B, (v ∈ X ↔ v ∈ B) := by
intro X hX
unfold blk at hX
rcases List.mem_cons.1 hX with rfl | hX
· exact Iff.rfl
· obtain ⟨p, hp, _, Y, hY, rfl⟩ := mem_copies.1 hX
constructor
· intro h
rcases List.mem_append.1 h with h | h
· exact absurd h (hP p hp Y hY)
· exact h
· intro h
exact List.mem_append.2 (Or.inr h)
theorem exists_mem_of_outFrom {plans : List Plan} {v : Nat}
(hP : ∀ p ∈ plans, ∀ Y ∈ p.2.1, v ∉ Y) :
∀ (bs : List Bag) (k : Nat) (X : Bag), X ∈ outFrom plans k bs → v ∈ X →
∃ B ∈ bs, v ∈ B
| [], _, X, hX, _ => by simp [outFrom] at hX
| B :: bs, k, X, hX, hv => by
have hX' : X ∈ blk plans k B ++ outFrom plans (k + 1) bs := hX
rcases List.mem_append.1 hX' with h | h
· exact ⟨B, List.mem_cons_self, (blk_uniform hP k B X h).1 hv⟩
· obtain ⟨B', hB', hv'⟩ := exists_mem_of_outFrom hP bs (k + 1) X h hv
exact ⟨B', List.mem_cons_of_mem _ hB', hv'⟩
theorem inBag_zero_outFrom (plans : List Plan) (v : Nat) :
∀ (bs : List Bag) (k : Nat), InBag bs 0 v → InBag (outFrom plans k bs) 0 v
| [], _, h => absurd (inBag_lt h) (by simp)
| B :: bs, k, h => by
have hv : v ∈ B := (inBag_cons_zero B bs v).1 h
show InBag (blk plans k B ++ outFrom plans (k + 1) bs) 0 v
unfold blk
rw [List.cons_append]
exact (inBag_cons_zero _ _ v).2 hv
/-- Index convexity of the `R`-part: if `bs` is convex for `v` and no plan bag contains
`v`, then so are its blocks. -/
theorem convL_outFrom_R {plans : List Plan} {v : Nat}
(hP : ∀ p ∈ plans, ∀ Y ∈ p.2.1, v ∉ Y) :
∀ (bs : List Bag) (k : Nat), ConvL bs v → ConvL (outFrom plans k bs) v
| [], _, _ => by simpa [outFrom] using convL_nil v
| B :: bs, k, hconv => by
show ConvL (blk plans k B ++ outFrom plans (k + 1) bs) v
have hbs : ConvL bs v := convL_of_cons hconv
have hY : ConvL (outFrom plans (k + 1) bs) v := convL_outFrom_R hP bs (k + 1) hbs
by_cases hB : v ∈ B
· have hfull : ∀ X ∈ blk plans k B, v ∈ X := fun X hX => (blk_uniform hP k B X hX).2 hB
by_cases hYv : ∃ X ∈ outFrom plans (k + 1) bs, v ∈ X
· obtain ⟨X, hX, hvX⟩ := hYv
obtain ⟨B0, hB0, hv0⟩ := exists_mem_of_outFrom hP bs (k + 1) X hX hvX
obtain ⟨m, hm⟩ := inBag_of_mem hB0 hv0
have h0 : InBag (B :: bs) 0 v := (inBag_cons_zero B bs v).2 hB
have h1 : InBag (B :: bs) (m + 1) v := (inBag_cons_succ B bs m v).2 hm
have h10 : InBag (B :: bs) 1 v := hconv 0 1 (m + 1) (by omega) (by omega) h0 h1
have hbs0 : InBag bs 0 v := h10
exact convL_append (convL_full hfull) hY
(Or.inr (Or.inr ⟨by
have : (blk plans k B).length - 1 < (blk plans k B).length := by
unfold blk; simp
exact inBag_full hfull this, inBag_zero_outFrom plans v bs (k + 1) hbs0⟩))
· exact convL_append (convL_full hfull) hY
(Or.inr (Or.inl (fun X hX hvX => hYv ⟨X, hX, hvX⟩)))
· have hfree : ∀ X ∈ blk plans k B, v ∉ X := fun X hX h => hB ((blk_uniform hP k B X hX).1 h)
exact convL_append (convL_free hfree) hY (Or.inl hfree)
theorem vf_outFrom_of_gt {plans : List Plan} {v k0 : Nat}
(hV : ∀ k B, k ≠ k0 → v ∉ B → ∀ X ∈ blk plans k B, v ∉ X) :
∀ (bs : List Bag) (k : Nat), k0 < k → (∀ B ∈ bs, v ∉ B) →
∀ X ∈ outFrom plans k bs, v ∉ X
| [], _, _, _, X, hX => by simp [outFrom] at hX
| B :: bs, k, hk, hB, X, hX => by
have hX' : X ∈ blk plans k B ++ outFrom plans (k + 1) bs := hX
rcases List.mem_append.1 hX' with h | h
· exact hV k B (by omega) (hB B List.mem_cons_self) X h
· exact vf_outFrom_of_gt hV bs (k + 1) (by omega)
(fun B' hB' => hB B' (List.mem_cons_of_mem _ hB')) X h
/-- Index convexity of the blocks when a single block index `k0` may contain `v`. -/
theorem convL_outFrom_C {plans : List Plan} {v k0 : Nat}
(hV : ∀ k B, k ≠ k0 → v ∉ B → ∀ X ∈ blk plans k B, v ∉ X)
(hP : ∀ B, v ∉ B → ConvL (blk plans k0 B) v) :
∀ (bs : List Bag) (k : Nat), (∀ B ∈ bs, v ∉ B) → ConvL (outFrom plans k bs) v
| [], _, _ => by simpa [outFrom] using convL_nil v
| B :: bs, k, hB => by
have hbs : ∀ B' ∈ bs, v ∉ B' := fun B' h => hB B' (List.mem_cons_of_mem _ h)
have hBv : v ∉ B := hB B List.mem_cons_self
show ConvL (blk plans k B ++ outFrom plans (k + 1) bs) v
by_cases hk : k = k0
· subst hk
have hY := vf_outFrom_of_gt hV bs (k + 1) (by omega) hbs
exact convL_append (hP B hBv) (convL_free hY) (Or.inr (Or.inl hY))
· have hXv := hV k B hk hBv
exact convL_append (convL_free hXv) (convL_outFrom_C hV hP bs (k + 1) hbs) (Or.inl hXv)
theorem copies_single_pos {p : Plan} {k : Nat} {B : Bag} (h : p.2.2.2 = some k) :
copies [p] k B = p.2.1.map (bagUnion · B) := by
obtain ⟨S, P, f, idx⟩ := p
dsimp only at h
subst h
unfold copies
simp
theorem copies_single_neg {p : Plan} {k : Nat} {B : Bag} (h : p.2.2.2 ≠ some k) :
copies [p] k B = [] := by
obtain ⟨S, P, f, idx⟩ := p
dsimp only at h
have hne : (idx == some k) = false := by
rw [beq_eq_false_iff_ne]; exact h
have hne' : ¬ ((idx == some k) = true) := by rw [hne]; decide
unfold copies
rw [List.flatMap_cons, List.flatMap_nil, List.append_nil]
dsimp only
rw [if_neg hne']
/-- Blocks of a plan list `pre ++ p0 :: post` where the plan bags of `pre` and `post` avoid
`v`, `p0` is convex for `v`, and `p0` is attached only at `k0`. -/
theorem pivot_blocks {pre post : List Plan} {p0 : Plan} {v k0 : Nat}
(hpre : ∀ p ∈ pre ++ post, ∀ Y ∈ p.2.1, v ∉ Y) (hP0 : ConvL p0.2.1 v)
(hidx : ∀ k', p0.2.2.2 = some k' → k' = k0) :
(∀ k B, k ≠ k0 → v ∉ B → ∀ X ∈ blk (pre ++ p0 :: post) k B, v ∉ X) ∧
(∀ B, v ∉ B → ConvL (blk (pre ++ p0 :: post) k0 B) v) := by
have hpreV : ∀ p ∈ pre, ∀ Y ∈ p.2.1, v ∉ Y := fun p hp => hpre p (List.mem_append_left _ hp)
have hpostV : ∀ p ∈ post, ∀ Y ∈ p.2.1, v ∉ Y :=
fun p hp => hpre p (List.mem_append_right _ hp)
-- decomposition of a block of the concatenated plan list
have hdec : ∀ k B, blk (pre ++ p0 :: post) k B
= ([B] ++ copies pre k B) ++ (copies [p0] k B ++ copies post k B) := by
intro k B
unfold blk
rw [copies_append, copies_cons]
simp only [List.cons_append, List.nil_append]
constructor
· intro k B hk hB X hX
have hnp : p0.2.2.2 ≠ some k := fun h => hk (hidx k h)
rw [hdec] at hX
rcases List.mem_append.1 hX with h | h
· rcases List.mem_append.1 h with h | h
· rw [List.mem_singleton.1 h]; exact hB
· exact copies_vf hpreV hB X h
· rw [copies_single_neg hnp, List.nil_append] at h
exact copies_vf hpostV hB X h
· intro B hB
by_cases hp0 : p0.2.2.2 = some k0
· have hMid : ConvL (copies [p0] k0 B) v := by
rw [copies_single_pos hp0]
exact convL_map (bagUnion · B)
(fun Y _ => by
simp only [bagUnion, List.mem_append]
exact ⟨fun h => h.elim id (fun h' => absurd h' hB), Or.inl⟩)
hP0
have hpostX : ∀ X ∈ copies post k0 B, v ∉ X := copies_vf hpostV hB
have hpreX : ∀ X ∈ copies pre k0 B, v ∉ X := copies_vf hpreV hB
have hXfree : ∀ X ∈ [B] ++ copies pre k0 B, v ∉ X := by
intro X hX
rcases List.mem_append.1 hX with h | h
· rw [List.mem_singleton.1 h]; exact hB
· exact hpreX X h
have hYc : ConvL (copies [p0] k0 B ++ copies post k0 B) v :=
convL_append hMid (convL_free hpostX) (Or.inr (Or.inl hpostX))
rw [hdec]
exact convL_append (convL_free hXfree) hYc (Or.inl hXfree)
· rw [hdec, copies_single_neg hp0, List.nil_append]
apply convL_free
intro X hX
rcases List.mem_append.1 hX with h | h
· rcases List.mem_append.1 h with h | h
· rw [List.mem_singleton.1 h]; exact hB
· exact copies_vf hpreV hB X h
· exact copies_vf hpostV hB X h
/-- The tail of a plan list: bags of the plans with `S = []`. -/
theorem tailOf_vf {plans : List Plan} {v : Nat}
(hP : ∀ p ∈ plans, ∀ Y ∈ p.2.1, v ∉ Y) : ∀ Y ∈ tailOf plans, v ∉ Y := by
intro Y hY
obtain ⟨p, hp, _, hYp⟩ := mem_tailOf.1 hY
exact hP p hp Y hYp
/-! ## 4. Per-vertex claims -/
theorem blk_split (pre post : List Plan) (p0 : Plan) (k : Nat) (B : Bag) :
blk (pre ++ p0 :: post) k B
= ([B] ++ copies pre k B) ++ (copies [p0] k B ++ copies post k B) := by
unfold blk
rw [copies_append, copies_cons]
simp only [List.cons_append, List.nil_append]
/-- Blocks at an index where `p0` is not attached avoid `v`. -/
theorem blk_vf_of_ne {pre post : List Plan} {p0 : Plan} {v k : Nat} {B : Bag}
(hpre : ∀ p ∈ pre ++ post, ∀ Y ∈ p.2.1, v ∉ Y) (hnp : p0.2.2.2 ≠ some k) (hB : v ∉ B) :
∀ X ∈ blk (pre ++ p0 :: post) k B, v ∉ X := by
have hpreV : ∀ p ∈ pre, ∀ Y ∈ p.2.1, v ∉ Y := fun p hp => hpre p (List.mem_append_left _ hp)
have hpostV : ∀ p ∈ post, ∀ Y ∈ p.2.1, v ∉ Y :=
fun p hp => hpre p (List.mem_append_right _ hp)
intro X hX
rw [blk_split, copies_single_neg hnp, List.nil_append] at hX
rcases List.mem_append.1 hX with h | h
· rcases List.mem_append.1 h with h | h
· rw [List.mem_singleton.1 h]; exact hB
· exact copies_vf hpreV hB X h
· exact copies_vf hpostV hB X h
theorem tailOf_single_nil {p0 : Plan} (h : p0.1 = []) : tailOf [p0] = p0.2.1 := by
obtain ⟨S, P, f, idx⟩ := p0
dsimp only at h
subst h
unfold tailOf
simp
theorem tailOf_single_ne {p0 : Plan} (h : p0.1 ≠ []) : tailOf [p0] = [] := by
obtain ⟨S, P, f, idx⟩ := p0
dsimp only at h
cases S with
| nil => exact absurd rfl h
| cons a S' => unfold tailOf; simp
theorem tailOf_vf_ne {pre post : List Plan} {p0 : Plan} {v : Nat}
(hpre : ∀ p ∈ pre ++ post, ∀ Y ∈ p.2.1, v ∉ Y) (hS : p0.1 ≠ []) :
∀ Y ∈ tailOf (pre ++ p0 :: post), v ∉ Y := by
intro Y hY
obtain ⟨p, hp, hem, hYp⟩ := mem_tailOf.1 hY
rcases List.mem_append.1 hp with h | h
· exact hpre p (List.mem_append_left _ h) Y hYp
· rcases List.mem_cons.1 h with rfl | h
· exact absurd (List.isEmpty_iff.1 hem) hS
· exact hpre p (List.mem_append_right _ h) Y hYp
theorem vf_outFrom_all {plans : List Plan} {v : Nat}
(hV : ∀ k B, v ∉ B → ∀ X ∈ blk plans k B, v ∉ X) :
∀ (bs : List Bag) (k : Nat), (∀ B ∈ bs, v ∉ B) → ∀ X ∈ outFrom plans k bs, v ∉ X
| [], _, _, X, hX => by simp [outFrom] at hX
| B :: bs, k, hB, X, hX => by
have hX' : X ∈ blk plans k B ++ outFrom plans (k + 1) bs := hX
rcases List.mem_append.1 hX' with h | h
· exact hV k B (hB B List.mem_cons_self) X h
· exact vf_outFrom_all hV bs (k + 1)
(fun B' hB' => hB B' (List.mem_cons_of_mem _ hB')) X h
/-- The per-vertex claim for a vertex `v` of a component with plan `p0`, inserted in the
middle of the plans `pre ++ p0 :: post`: convexity of the bags and coverage with the
bags of `P0` (each bag of `P0` lies in a bag of the output, extended by the attachment). -/
theorem vertex_C {pre post : List Plan} {p0 : Plan} {v : Nat} {bagsR : List Bag}
(hpre : ∀ p ∈ pre ++ post, ∀ Y ∈ p.2.1, v ∉ Y)
(hP0 : ConvL p0.2.1 v) (hB : ∀ B ∈ bagsR, v ∉ B)
(hS0 : (p0.1 = [] → p0.2.2.2 = none) ∧
(p0.1 ≠ [] → ∃ i Bi, p0.2.2.2 = some i ∧ bagsR[i]? = some Bi ∧ ∀ x ∈ p0.1, x ∈ Bi)) :
ConvL (outFrom (pre ++ p0 :: post) 0 bagsR ++ tailOf (pre ++ p0 :: post)) v ∧
∀ B0 ∈ p0.2.1, ∃ B ∈ outFrom (pre ++ p0 :: post) 0 bagsR ++ tailOf (pre ++ p0 :: post),
(∀ x ∈ B0, x ∈ B) ∧ (∀ x ∈ p0.1, x ∈ B) := by
have hpreV : ∀ p ∈ pre, ∀ Y ∈ p.2.1, v ∉ Y := fun p hp => hpre p (List.mem_append_left _ hp)
have hpostV : ∀ p ∈ post, ∀ Y ∈ p.2.1, v ∉ Y :=
fun p hp => hpre p (List.mem_append_right _ hp)
by_cases hS : p0.1 = []
· -- no attachment: the plan is in the tail, the blocks avoid `v`
have hnone : p0.2.2.2 = none := hS0.1 hS
have hVall : ∀ k B, v ∉ B → ∀ X ∈ blk (pre ++ p0 :: post) k B, v ∉ X :=
fun k B hB' => blk_vf_of_ne hpre (by rw [hnone]; simp) hB'
have hOutVF := vf_outFrom_all hVall bagsR 0 hB
have hPre : ∀ Y ∈ tailOf pre, v ∉ Y := by
intro Y hY
obtain ⟨p, hp, _, hYp⟩ := mem_tailOf.1 hY
exact hpre p (List.mem_append_left _ hp) Y hYp
have hPost : ∀ Y ∈ tailOf post, v ∉ Y := by
intro Y hY
obtain ⟨p, hp, _, hYp⟩ := mem_tailOf.1 hY
exact hpre p (List.mem_append_right _ hp) Y hYp
have hTail : tailOf (pre ++ p0 :: post) = tailOf pre ++ (p0.2.1 ++ tailOf post) := by
have h1 : p0 :: post = [p0] ++ post := rfl
rw [h1, tailOf_append, tailOf_append, tailOf_single_nil hS]
have hTailConv : ConvL (tailOf (pre ++ p0 :: post)) v := by
rw [hTail]
exact convL_append (convL_free hPre)
(convL_append hP0 (convL_free hPost) (Or.inr (Or.inl hPost))) (Or.inl hPre)
refine ⟨convL_append (convL_free hOutVF) hTailConv (Or.inl hOutVF), ?_⟩
intro B0 hB0
refine ⟨B0, List.mem_append_right _ ?_, fun x hx => hx, fun x hx => ?_⟩
· rw [hTail]; exact List.mem_append_right _ (List.mem_append_left _ hB0)
· rw [hS] at hx; exact absurd hx (List.not_mem_nil)
· -- attached at `i`: the plan's bags go into the block of `bagsR[i]`
obtain ⟨i, Bi, hi, hBi, hsub⟩ := hS0.2 hS
have hidx : ∀ k', p0.2.2.2 = some k' → k' = i :=
fun k' h => (Option.some.inj (hi.symm.trans h)).symm
obtain ⟨hV, hPb⟩ := pivot_blocks hpre hP0 hidx
have hOutConv : ConvL (outFrom (pre ++ p0 :: post) 0 bagsR) v :=
convL_outFrom_C hV hPb bagsR 0 hB
have hTailVF := tailOf_vf_ne hpre hS
refine ⟨convL_append hOutConv (convL_free hTailVF) (Or.inr (Or.inl hTailVF)), ?_⟩
intro B0 hB0
have hX : B0 ++ Bi ∈ copies (pre ++ p0 :: post) (0 + i) Bi := by
rw [Nat.zero_add]
exact mem_copies.2 ⟨p0, List.mem_append_right _ List.mem_cons_self, hi, B0, hB0, rfl⟩
have hX' : B0 ++ Bi ∈ outFrom (pre ++ p0 :: post) 0 bagsR :=
copies_sub_outFrom (pre ++ p0 :: post) bagsR 0 i Bi (B0 ++ Bi) hBi hX
refine ⟨B0 ++ Bi, List.mem_append_left _ hX', fun x hx => List.mem_append_left _ hx,
fun x hx => List.mem_append_right _ (hsub x hx)⟩
/-- The per-vertex claim for an `R`-vertex. -/
theorem vertex_R {plans : List Plan} {bagsR : List Bag} {v : Nat}
(hP : ∀ p ∈ plans, ∀ Y ∈ p.2.1, v ∉ Y) (hconv : ConvL bagsR v) :
ConvL (outFrom plans 0 bagsR ++ tailOf plans) v :=
convL_append (convL_outFrom_R hP bagsR 0 hconv) (convL_free (tailOf_vf hP))
(Or.inr (Or.inl (tailOf_vf hP)))
theorem outFrom_within {G : Graph} (plans : List Plan)
(hP : ∀ p ∈ plans, ∀ Y ∈ p.2.1, ∀ x ∈ Y, x ∈ G.nodes) :
∀ (bs : List Bag) (k : Nat), (∀ B ∈ bs, ∀ x ∈ B, x ∈ G.nodes) →
∀ X ∈ outFrom plans k bs, ∀ x ∈ X, x ∈ G.nodes
| [], _, _, X, hX => by simp [outFrom] at hX
| B :: bs, k, hbs, X, hX => by
have hX' : X ∈ blk plans k B ++ outFrom plans (k + 1) bs := hX
rcases List.mem_append.1 hX' with h | h
· unfold blk at h
rcases List.mem_cons.1 h with rfl | h
· exact hbs X List.mem_cons_self
· obtain ⟨p, hp, _, Y, hY, rfl⟩ := mem_copies.1 h
intro x hx
rcases List.mem_append.1 hx with hx | hx
· exact hP p hp Y hY x hx
· exact hbs B List.mem_cons_self x hx
· exact outFrom_within plans hP bs (k + 1)
(fun B' hB' => hbs B' (List.mem_cons_of_mem _ hB')) X h
theorem tailOf_within {G : Graph} (plans : List Plan)
(hP : ∀ p ∈ plans, ∀ Y ∈ p.2.1, ∀ x ∈ Y, x ∈ G.nodes) :
∀ Y ∈ tailOf plans, ∀ x ∈ Y, x ∈ G.nodes := by
intro Y hY
obtain ⟨p, hp, _, hYp⟩ := mem_tailOf.1 hY
exact hP p hp Y hYp
/-! ## 5. The attachment sets and the components of the rest -/
theorem mem_foldl_nbrs (Q : Nat → Bool) (x : Nat) : ∀ (l acc : List Nat),
x ∈ l.foldl (fun acc y => if Q y || acc.contains y then acc else acc ++ [y]) acc ↔
x ∈ acc ∨ (x ∈ l ∧ Q x = false)
| [], acc => by simp
| y :: l, acc => by
have key : x ∈ (if Q y || acc.contains y then acc else acc ++ [y]) ↔
x ∈ acc ∨ (x = y ∧ Q x = false) := by
by_cases h : (Q y || acc.contains y) = true
· rw [if_pos h]
constructor
· intro hx; exact Or.inl hx
· rintro (hx | ⟨rfl, hQ⟩)
· exact hx
· simp [hQ] at h
exact h
· rw [if_neg h]
have hQy : Q y = false := by
cases hq : Q y
· rfl
· exact absurd (by simp [hq]) h
constructor
· intro hx
rcases List.mem_append.1 hx with hx | hx
· exact Or.inl hx
· rw [List.mem_singleton] at hx
subst hx
exact Or.inr ⟨rfl, hQy⟩
· rintro (hx | ⟨rfl, _⟩)
· exact List.mem_append_left _ hx
· exact List.mem_append_right _ List.mem_cons_self
rw [List.foldl_cons, mem_foldl_nbrs Q x l, key]
simp only [List.mem_cons]
tauto
theorem mem_foldl_outer (Q : Nat → Bool) (G : Nat → List Nat) (x : Nat) :
∀ (C acc : List Nat),
x ∈ C.foldl (fun acc c => (G c).foldl
(fun acc y => if Q y || acc.contains y then acc else acc ++ [y]) acc) acc ↔
x ∈ acc ∨ ∃ c ∈ C, x ∈ G c ∧ Q x = false
| [], acc => by simp
| c :: C, acc => by
rw [List.foldl_cons, mem_foldl_outer Q G x C, mem_foldl_nbrs Q x (G c) acc]
simp only [List.mem_cons]
constructor
· rintro ((hx | ⟨hx, hQ⟩) | ⟨c', hc', hx, hQ⟩)
· exact Or.inl hx
· exact Or.inr ⟨c, Or.inl rfl, hx, hQ⟩
· exact Or.inr ⟨c', Or.inr hc', hx, hQ⟩
· rintro (hx | ⟨c', hc', hx, hQ⟩)
· exact Or.inl (Or.inl hx)
· rcases hc' with rfl | hc'
· exact Or.inl (Or.inr ⟨hx, hQ⟩)
· exact Or.inr ⟨c', hc', hx, hQ⟩
/-- Membership in the attachment set: a neighbour of the component, outside the component and
outside the deleted set. -/
theorem mem_undoAttach (F : Graph) (D C : List Nat) (x : Nat) :
x ∈ undoAttach F D C ↔ (∃ c ∈ C, x ∈ F.nbrs c) ∧ x ∉ C ∧ x ∉ D := by
unfold undoAttach
rw [mem_foldl_outer]
simp only [List.not_mem_nil, false_or]
constructor
· rintro ⟨c, hc, hx, hQ⟩
have h1 : x ∉ C ∧ x ∉ D := by
simp only [Bool.or_eq_false_iff] at hQ
exact ⟨by simpa using hQ.1, by simpa using hQ.2⟩
exact ⟨⟨c, hc, hx⟩, h1⟩
· rintro ⟨⟨c, hc, hx⟩, h1, h2⟩
refine ⟨c, hc, hx, ?_⟩
simp only [Bool.or_eq_false_iff]
exact ⟨by simpa using h1, by simpa using h2⟩
/-- The rest graph: the induced subgraph on the vertices outside `D` and outside `R`. -/
def restG (F R : Graph) (D : List Nat) : Graph :=
F.induced fun v => !D.contains v && !R.mem v
theorem keep_true_iff {R : Graph} (hR : R.WF) (D : List Nat) (x : Nat) :
(!D.contains x && !R.mem x) = true ↔ x ∉ D ∧ x ∉ R.nodes := by
rw [← hR.mem_iff x]
simp
theorem mem_restG {F R : Graph} {D : List Nat} (hInd : InducedSpec) (hF : F.WF) (hR : R.WF)
(x : Nat) : x ∈ (restG F R D).nodes ↔ x ∈ F.nodes ∧ x ∉ D ∧ x ∉ R.nodes := by
have h := (hInd F (fun v => !D.contains v && !R.mem v) hF).2.1 x
constructor
· intro hx
obtain ⟨hF', hk⟩ := h.1 hx
exact ⟨hF', ((keep_true_iff hR D x).1 hk).1, ((keep_true_iff hR D x).1 hk).2⟩
· rintro ⟨hF', hD, hRx⟩
exact h.2 ⟨hF', (keep_true_iff hR D x).2 ⟨hD, hRx⟩⟩
/-- Facts about the components of the rest graph, in the form used by `undoF`. -/
theorem restG_components_facts {F R : Graph} {D : List Nat} (hInd : InducedSpec)
(hComp : ComponentsSpec) (hF : F.WF) (hR : R.WF) :
(∀ C ∈ (restG F R D).components, ∀ x ∈ C, x ∈ F.nodes ∧ x ∉ D ∧ x ∉ R.nodes) ∧
(∀ x ∈ F.nodes, x ∈ D ∨ x ∈ R.nodes ∨ ∃ C ∈ (restG F R D).components, x ∈ C) ∧
(restG F R D).components.flatten.Nodup ∧
(∀ C ∈ (restG F R D).components, ∀ x ∈ C, ∀ y, F.Adj x y →
y ∈ C ∨ y ∈ D ∨ y ∈ R.nodes) := by
have hWF : (restG F R D).WF := (hInd F (fun v => !D.contains v && !R.mem v) hF).1
obtain ⟨hperm, _, hclos⟩ := hComp (restG F R D) hWF
have hmem : ∀ x, x ∈ (restG F R D).components.flatten ↔ x ∈ (restG F R D).nodes :=
fun x => hperm.mem_iff
have hA : ∀ C ∈ (restG F R D).components, ∀ x ∈ C, x ∈ F.nodes ∧ x ∉ D ∧ x ∉ R.nodes := by
intro C hC x hx
exact (mem_restG hInd hF hR x).1 ((hmem x).1 (List.mem_flatten.2 ⟨C, hC, hx⟩))
refine ⟨hA, ?_, ?_, ?_⟩
· intro x hx
by_cases hD : x ∈ D
· exact Or.inl hD
by_cases hRx : x ∈ R.nodes
· exact Or.inr (Or.inl hRx)
right; right
have hxr : x ∈ (restG F R D).nodes := (mem_restG hInd hF hR x).2 ⟨hx, hD, hRx⟩
obtain ⟨z, hz, hxz⟩ := List.mem_flatten.1 ((hmem x).2 hxr)
exact ⟨z, hz, hxz⟩
· exact (hperm.nodup_iff).2 hWF.nodup
· intro C hC x hx y hxy
by_cases hyD : y ∈ D
· exact Or.inr (Or.inl hyD)
by_cases hyR : y ∈ R.nodes
· exact Or.inr (Or.inr hyR)
have hxN := (mem_restG hInd hF hR x).1 ((hmem x).1 (List.mem_flatten.2 ⟨C, hC, hx⟩))
have hyN : y ∈ (restG F R D).nodes :=
(mem_restG hInd hF hR y).2 ⟨hF.nbrs_sub x y hxy, hyD, hyR⟩
have hW := (hInd F (fun v => !D.contains v && !R.mem v) hF).2.2 x y
have hadj : (restG F R D).Adj x y :=
hW.2 ⟨hxy, (keep_true_iff hR D x).2 ⟨hxN.2.1, hxN.2.2⟩,
(keep_true_iff hR D y).2 ⟨hyD, hyR⟩⟩
exact Or.inl (hclos C hC x hx y hadj)
/-! ## 6. The plans of `undoF` and the output bags -/
/-- The plan of a component `C`: the body of the `map` in `undoF`. -/
def planOf (F : Graph) (D : List Nat) (bagsR : List Bag) (C : List Nat) : Plan :=
(undoAttach F D C, (pdTw2F (F.induced C.contains)).1, (pdTw2F (F.induced C.contains)).2,
if (undoAttach F D C).isEmpty then none
else bagsR.findIdx? (subsetB (undoAttach F D C) ·))
/-- The output of `undoF` from the bags `L` (before the flag): `L ∪ D` bagwise, or `[D]`. -/
def resOf (D : List Nat) (L : List Bag) : List Bag :=
if (L.map fun B => bagUnion B D).isEmpty then [D] else L.map fun B => bagUnion B D
theorem induced_mem_iff {F : Graph} (hInd : InducedSpec) (hF : F.WF) (C : List Nat) (x : Nat) :
x ∈ (F.induced C.contains).nodes ↔ x ∈ F.nodes ∧ x ∈ C := by
rw [(hInd F C.contains hF).2.1 x]
simp
theorem induced_adj_iff {F : Graph} (hInd : InducedSpec) (hF : F.WF) (C : List Nat) (x y : Nat) :
(F.induced C.contains).Adj x y ↔ F.Adj x y ∧ x ∈ C ∧ y ∈ C := by
rw [(hInd F C.contains hF).2.2 x y]
simp
/-- Two different components are disjoint: from `nodup` of the flattened list. -/
theorem disj_of_nodup_split {s t : List (List Nat)} {C0 : List Nat}
(h : (s ++ C0 :: t).flatten.Nodup) :
∀ C' ∈ s ++ t, ∀ x ∈ C0, x ∉ C' := by
have h' : (s.flatten ++ (C0 ++ t.flatten)).Nodup := by
simpa [List.flatten_append] using h
rw [List.nodup_append] at h'
have h'' := List.nodup_append.1 h'.2.1
intro C' hC' x hx hxC'
rcases List.mem_append.1 hC' with hC' | hC'
· exact h'.2.2 x (List.mem_flatten.2 ⟨C', hC', hxC'⟩) x (List.mem_append_left _ hx) rfl
· exact h''.2.2 x hx x (List.mem_flatten.2 ⟨C', hC', hxC'⟩) rfl
/-- Facts about the bags of the `undoF` plans, given the component facts. -/
theorem plan_bags_in_comp {F : Graph} {D : List Nat} {bagsR : List Bag}
{comps : List (List Nat)} (hInd : InducedSpec) (hF : F.WF)
(hP : ∀ C ∈ comps, ValidPD (F.induced C.contains) (planOf F D bagsR C).2.1 ∧
BagsWithin (F.induced C.contains) (planOf F D bagsR C).2.1) :
∀ C ∈ comps, ∀ Y ∈ (planOf F D bagsR C).2.1, ∀ x ∈ Y, x ∈ F.nodes ∧ x ∈ C := by
intro C hC Y hY x hx
have hB := (hP C hC).2 Y hY x hx
exact (induced_mem_iff hInd hF C x).1 hB
theorem resOf_contains {D : List Nat} {L : List Bag} {X : Bag} (hX : X ∈ resOf D L) :
∀ x ∈ D, x ∈ X := by
intro x hx
unfold resOf at hX
split at hX
· rw [List.mem_singleton.1 hX]; exact hx
· obtain ⟨B, _, rfl⟩ := List.mem_map.1 hX
exact List.mem_append_right _ hx
theorem resOf_within {F : Graph} {D : List Nat} {L : List Bag} (hDF : ∀ x ∈ D, x ∈ F.nodes)
(hL : ∀ B ∈ L, ∀ x ∈ B, x ∈ F.nodes) :
∀ X ∈ resOf D L, ∀ x ∈ X, x ∈ F.nodes := by
intro X hX x hx
unfold resOf at hX
split at hX
· rw [List.mem_singleton.1 hX] at hx; exact hDF x hx
· obtain ⟨B, hB, rfl⟩ := List.mem_map.1 hX
rcases List.mem_append.1 hx with hx | hx
· exact hL B hB x hx
· exact hDF x hx
theorem resOf_ne_nil_of_mem {D : List Nat} {L : List Bag} {B : Bag} (hB : B ∈ L) :
∃ X ∈ resOf D L, ∀ x ∈ B, x ∈ X := by
refine ⟨bagUnion B D, ?_, fun x hx => List.mem_append_left _ hx⟩
unfold resOf
split
· rename_i h
exfalso
obtain ⟨c, hc⟩ : ∃ c, c = B := ⟨B, rfl⟩
simp only [List.isEmpty_iff, List.map_eq_nil_iff] at h
subst h
exact absurd hB (List.not_mem_nil)
· exact List.mem_map.2 ⟨B, hB, rfl⟩
/-! ## 7. Assembly for the main branch -/
/-- The bags of `undoF` before the final `∪ D` (the list `out ++ tail` of the code). -/
def bags0Of (F : Graph) (D : List Nat) (bagsR : List Bag) (comps : List (List Nat)) :
List Bag :=
outFrom (comps.map (planOf F D bagsR)) 0 bagsR ++ tailOf (comps.map (planOf F D bagsR))
theorem bags0Of_split (F : Graph) (D : List Nat) (bagsR : List Bag) {comps : List (List Nat)}
{s t : List (List Nat)} {C0 : List Nat} (hst : comps = s ++ C0 :: t) :
bags0Of F D bagsR comps =
outFrom (s.map (planOf F D bagsR) ++ planOf F D bagsR C0 :: t.map (planOf F D bagsR)) 0
bagsR ++
tailOf (s.map (planOf F D bagsR) ++ planOf F D bagsR C0 :: t.map (planOf F D bagsR)) := by
unfold bags0Of
rw [hst, List.map_append, List.map_cons]
theorem resOf_ne_nil (D : List Nat) (L : List Bag) : resOf D L ≠ [] := by
unfold resOf
split
· exact List.cons_ne_nil _ _
· rename_i h
intro h'
apply h
simp [h']
theorem resOf_eq_map (D : List Nat) {L : List Bag} (hL : L ≠ []) :
resOf D L = L.map fun B => bagUnion B D := by
unfold resOf
split
· rename_i h
exfalso
apply hL
simpa [List.isEmpty_iff, List.map_eq_nil_iff] using h
· rfl
/-- Facts about the vertices of one component `C0` of the rest. -/
theorem comp_V {F R : Graph} {D : List Nat} {bagsR : List Bag} {comps : List (List Nat)}
(hInd : InducedSpec) (hF : F.WF)
(hBR : BagsWithin R bagsR)
(hcomp_mem : ∀ C ∈ comps, ∀ x ∈ C, x ∈ F.nodes ∧ x ∉ D ∧ x ∉ R.nodes)
(hdisj : comps.flatten.Nodup)
(hclos : ∀ C ∈ comps, ∀ x ∈ C, ∀ y, F.Adj x y → y ∈ C ∨ y ∈ D ∨ y ∈ R.nodes)
(hP : ∀ C ∈ comps, ValidPD (F.induced C.contains) (planOf F D bagsR C).2.1 ∧
BagsWithin (F.induced C.contains) (planOf F D bagsR C).2.1)
(hok : ∀ C ∈ comps, (∀ x ∈ undoAttach F D C, x ∈ R.nodes) ∧
(undoAttach F D C ≠ [] → ∃ i Bi, (planOf F D bagsR C).2.2.2 = some i ∧
bagsR[i]? = some Bi ∧ ∀ x ∈ undoAttach F D C, x ∈ Bi))
{C0 : List Nat} (hC0 : C0 ∈ comps) :
(∀ v ∈ C0, ConvL (bags0Of F D bagsR comps) v) ∧
(∀ v ∈ C0, ∃ B ∈ bags0Of F D bagsR comps, v ∈ B) ∧
(∀ u ∈ C0, ∀ y, F.Adj u y → y ∉ D → ∃ B ∈ bags0Of F D bagsR comps, u ∈ B ∧ y ∈ B) := by
obtain ⟨s, t, hst⟩ := List.append_of_mem hC0
have hdec := bags0Of_split F D bagsR hst
have hdisj' : (s ++ C0 :: t).flatten.Nodup := hst ▸ hdisj
have hdisjC := disj_of_nodup_split hdisj'
have hPlanC := plan_bags_in_comp hInd hF hP
-- the plans of the other components avoid the vertices of `C0`
have hpre : ∀ v ∈ C0, ∀ p ∈ s.map (planOf F D bagsR) ++ t.map (planOf F D bagsR),
∀ Y ∈ p.2.1, v ∉ Y := by
intro v hv p hp Y hY hvY
obtain ⟨C', hC', rfl⟩ : ∃ C' ∈ s ++ t, planOf F D bagsR C' = p := by
rcases List.mem_append.1 hp with hp | hp
· obtain ⟨C', hC', rfl⟩ := List.mem_map.1 hp
exact ⟨C', List.mem_append_left _ hC', rfl⟩
· obtain ⟨C', hC', rfl⟩ := List.mem_map.1 hp
exact ⟨C', List.mem_append_right _ hC', rfl⟩
have hC'comps : C' ∈ comps := by
rw [hst]
rcases List.mem_append.1 hC' with h | h
· exact List.mem_append_left _ h
· exact List.mem_append_right _ (List.mem_cons_of_mem _ h)
have hvC' := (hPlanC C' hC'comps Y hY v hvY).2
exact hdisjC C' hC' v hv hvC'
have hS0 : ((planOf F D bagsR C0).1 = [] → (planOf F D bagsR C0).2.2.2 = none) ∧
((planOf F D bagsR C0).1 ≠ [] → ∃ i Bi, (planOf F D bagsR C0).2.2.2 = some i ∧
bagsR[i]? = some Bi ∧ ∀ x ∈ (planOf F D bagsR C0).1, x ∈ Bi) := by
refine ⟨fun h => ?_, fun h => ?_⟩
· have h' : undoAttach F D C0 = [] := h
simp [planOf, h']
· exact (hok C0 hC0).2 h
have key : ∀ v ∈ C0, ConvL (bags0Of F D bagsR comps) v ∧
∀ B0 ∈ (planOf F D bagsR C0).2.1, ∃ B ∈ bags0Of F D bagsR comps,
(∀ x ∈ B0, x ∈ B) ∧ (∀ x ∈ undoAttach F D C0, x ∈ B) := by
intro v hv
have hvF : v ∈ (F.induced C0.contains).nodes :=
(induced_mem_iff hInd hF C0 v).2 ⟨(hcomp_mem C0 hC0 v hv).1, hv⟩
have hP0 : ConvL (planOf F D bagsR C0).2.1 v := (hP C0 hC0).1.2.1 v hvF
have hB : ∀ B ∈ bagsR, v ∉ B := fun B hB hvB =>
(hcomp_mem C0 hC0 v hv).2.2 (hBR B hB v hvB)
have hVC := vertex_C (pre := s.map (planOf F D bagsR))
(post := t.map (planOf F D bagsR)) (p0 := planOf F D bagsR C0) (hpre v hv) hP0 hB hS0
rw [hdec]
exact ⟨hVC.1, hVC.2⟩
refine ⟨fun v hv => (key v hv).1, fun v hv => ?_, fun u hu y hadj hyD => ?_⟩
· have hvF : v ∈ (F.induced C0.contains).nodes :=
(induced_mem_iff hInd hF C0 v).2 ⟨(hcomp_mem C0 hC0 v hv).1, hv⟩
obtain ⟨i, hi⟩ := (hP C0 hC0).1.1 v hvF
obtain ⟨B0, hB0, hvB0⟩ := inBag_mem hi
obtain ⟨B, hB, hsub, _⟩ := (key v hv).2 B0 hB0
exact ⟨B, hB, hsub v hvB0⟩
· have huF : u ∈ (F.induced C0.contains).nodes :=
(induced_mem_iff hInd hF C0 u).2 ⟨(hcomp_mem C0 hC0 u hu).1, hu⟩
rcases hclos C0 hC0 u hu y hadj with hyC | hyD' | hyR
· have hadjI : (F.induced C0.contains).Adj u y :=
(induced_adj_iff hInd hF C0 u y).2 ⟨hadj, hu, hyC⟩
obtain ⟨B0, hB0, huB0, hyB0⟩ := (hP C0 hC0).1.2.2 u y huF hadjI
obtain ⟨B, hB, hsub, _⟩ := (key u hu).2 B0 hB0
exact ⟨B, hB, hsub u huB0, hsub y hyB0⟩
· exact absurd hyD' hyD
· have hyC0 : y ∉ C0 := fun hyC => (hcomp_mem C0 hC0 y hyC).2.2 hyR
have hyS : y ∈ undoAttach F D C0 :=
(mem_undoAttach F D C0 y).2 ⟨⟨u, hu, hadj⟩, hyC0, hyD⟩
obtain ⟨i, hi⟩ := (hP C0 hC0).1.1 u huF
obtain ⟨B0, hB0, huB0⟩ := inBag_mem hi
obtain ⟨B, hB, hsub, hsubS⟩ := (key u hu).2 B0 hB0
exact ⟨B, hB, hsub u huB0, hsubS y hyS⟩
/-- Facts about the vertices of `R`. -/
theorem R_V {F R : Graph} {D : List Nat} {bagsR : List Bag} {comps : List (List Nat)}
(hInd : InducedSpec) (hF : F.WF)
(hVR : ValidPD R bagsR)
(hRadj : ∀ x y, x ∈ R.nodes → y ∈ R.nodes → F.Adj x y → R.Adj x y)
(hcomp_mem : ∀ C ∈ comps, ∀ x ∈ C, x ∈ F.nodes ∧ x ∉ D ∧ x ∉ R.nodes)
(hP : ∀ C ∈ comps, ValidPD (F.induced C.contains) (planOf F D bagsR C).2.1 ∧
BagsWithin (F.induced C.contains) (planOf F D bagsR C).2.1) :
(∀ v ∈ R.nodes, ConvL (bags0Of F D bagsR comps) v) ∧
(∀ v ∈ R.nodes, ∃ B ∈ bags0Of F D bagsR comps, v ∈ B) ∧
(∀ u v, u ∈ R.nodes → v ∈ R.nodes → F.Adj u v →
∃ B ∈ bags0Of F D bagsR comps, u ∈ B ∧ v ∈ B) := by
have hPlanC := plan_bags_in_comp hInd hF hP
have hPl : ∀ v ∈ R.nodes, ∀ p ∈ comps.map (planOf F D bagsR), ∀ Y ∈ p.2.1, v ∉ Y := by
intro v hv p hp Y hY hvY
obtain ⟨C, hC, rfl⟩ := List.mem_map.1 hp
exact (hcomp_mem C hC v (hPlanC C hC Y hY v hvY).2).2.2 hv
refine ⟨fun v hv => ?_, fun v hv => ?_, fun u v hu hv hadj => ?_⟩
· unfold bags0Of
exact vertex_R (hPl v hv) (hVR.2.1 v hv)
· obtain ⟨i, hi⟩ := hVR.1 v hv
obtain ⟨B, hB, hvB⟩ := inBag_mem hi
exact ⟨B, List.mem_append_left _ (mem_outFrom_of_mem _ bagsR 0 B hB), hvB⟩
· obtain ⟨B, hB, huB, hvB⟩ := hVR.2.2 u v hu (hRadj u v hu hv hadj)
exact ⟨B, List.mem_append_left _ (mem_outFrom_of_mem _ bagsR 0 B hB), huB, hvB⟩
/-! ## 8. The main branch of `undoF` -/
theorem core_valid {F R : Graph} {D : List Nat} {bagsR : List Bag} {comps : List (List Nat)}
(hInd : InducedSpec) (hF : F.WF)
(hVR : ValidPD R bagsR) (hBR : BagsWithin R bagsR)
(hRadj : ∀ x y, x ∈ R.nodes → y ∈ R.nodes → F.Adj x y → R.Adj x y)
(hRsub : ∀ x ∈ R.nodes, x ∈ F.nodes)
(hcomp_mem : ∀ C ∈ comps, ∀ x ∈ C, x ∈ F.nodes ∧ x ∉ D ∧ x ∉ R.nodes)
(hcov : ∀ x ∈ F.nodes, x ∈ D ∨ x ∈ R.nodes ∨ ∃ C ∈ comps, x ∈ C)
(hdisj : comps.flatten.Nodup)
(hclos : ∀ C ∈ comps, ∀ x ∈ C, ∀ y, F.Adj x y → y ∈ C ∨ y ∈ D ∨ y ∈ R.nodes)
(hP : ∀ C ∈ comps, ValidPD (F.induced C.contains) (planOf F D bagsR C).2.1 ∧
BagsWithin (F.induced C.contains) (planOf F D bagsR C).2.1)
(hok : ∀ C ∈ comps, (∀ x ∈ undoAttach F D C, x ∈ R.nodes) ∧
(undoAttach F D C ≠ [] → ∃ i Bi, (planOf F D bagsR C).2.2.2 = some i ∧
bagsR[i]? = some Bi ∧ ∀ x ∈ undoAttach F D C, x ∈ Bi)) :
ValidPD F (resOf D (bags0Of F D bagsR comps)) ∧
((∀ x ∈ D, x ∈ F.nodes) → BagsWithin F (resOf D (bags0Of F D bagsR comps))) := by
have hCV : ∀ C0 ∈ comps, (∀ v ∈ C0, ConvL (bags0Of F D bagsR comps) v) ∧
(∀ v ∈ C0, ∃ B ∈ bags0Of F D bagsR comps, v ∈ B) ∧
(∀ u ∈ C0, ∀ y, F.Adj u y → y ∉ D → ∃ B ∈ bags0Of F D bagsR comps, u ∈ B ∧ y ∈ B) :=
fun C0 hC0 => comp_V hInd hF hBR hcomp_mem hdisj hclos hP hok hC0
have hRV := R_V hInd hF hVR hRadj hcomp_mem hP
have hPF : ∀ p ∈ comps.map (planOf F D bagsR), ∀ Y ∈ p.2.1, ∀ x ∈ Y, x ∈ F.nodes := by
intro p hp Y hY x hx
obtain ⟨C, hC, rfl⟩ := List.mem_map.1 hp
exact (plan_bags_in_comp hInd hF hP C hC Y hY x hx).1
have hbagsF : ∀ B ∈ bags0Of F D bagsR comps, ∀ x ∈ B, x ∈ F.nodes := by
intro B hB x hx
unfold bags0Of at hB
rcases List.mem_append.1 hB with hB | hB
· exact outFrom_within (G := F) _ hPF bagsR 0
(fun B' hB' x' hx' => hRsub x' (hBR B' hB' x' hx')) B hB x hx
· exact tailOf_within (G := F) _ hPF B hB x hx
-- every vertex of `F` outside `D` is covered, convex, and each edge is covered
have hV1 : ∀ v ∈ F.nodes, v ∉ D → ∃ B ∈ bags0Of F D bagsR comps, v ∈ B := by
intro v hv hvD
rcases hcov v hv with h | h | ⟨C0, hC0, hvC0⟩
· exact absurd h hvD
· exact hRV.2.1 v h
· exact (hCV C0 hC0).2.1 v hvC0
have hV2 : ∀ v ∈ F.nodes, v ∉ D → ConvL (bags0Of F D bagsR comps) v := by
intro v hv hvD
rcases hcov v hv with h | h | ⟨C0, hC0, hvC0⟩
· exact absurd h hvD
· exact hRV.1 v h
· exact (hCV C0 hC0).1 v hvC0
have hV3 : ∀ u v, u ∈ F.nodes → v ∈ F.nodes → u ∉ D → v ∉ D → F.Adj u v →
∃ B ∈ bags0Of F D bagsR comps, u ∈ B ∧ v ∈ B := by
intro u v hu hv huD hvD hadj
rcases hcov u hu with h | h | ⟨C0, hC0, huC0⟩
· exact absurd h huD
· rcases hcov v hv with h' | h' | ⟨C1, hC1, hvC1⟩
· exact absurd h' hvD
· exact hRV.2.2 u v h h' hadj
· obtain ⟨B, hB, hvB, huB⟩ := (hCV C1 hC1).2.2 v hvC1 u (hF.symm u v hadj) huD
exact ⟨B, hB, huB, hvB⟩
· exact (hCV C0 hC0).2.2 u huC0 v hadj hvD
have hcovRes : ∀ v ∈ F.nodes, ∃ X ∈ resOf D (bags0Of F D bagsR comps), v ∈ X := by
intro v hv
by_cases hvD : v ∈ D
· obtain ⟨X, hX⟩ := List.exists_mem_of_ne_nil _ (resOf_ne_nil D (bags0Of F D bagsR comps))
exact ⟨X, hX, resOf_contains hX v hvD⟩
· obtain ⟨B, hB, hvB⟩ := hV1 v hv hvD
obtain ⟨X, hX, hBX⟩ := resOf_ne_nil_of_mem (D := D) hB
exact ⟨X, hX, hBX v hvB⟩
have hValid : ValidPD F (resOf D (bags0Of F D bagsR comps)) := by
refine ⟨fun v hv => ?_, fun v hv => ?_, fun u v hu hadj => ?_⟩
· obtain ⟨X, hX, hvX⟩ := hcovRes v hv
exact inBag_of_mem hX hvX
· by_cases hvD : v ∈ D
· exact convL_full (fun X hX => resOf_contains hX v hvD)
· obtain ⟨B, hB, _⟩ := hV1 v hv hvD
have hne : bags0Of F D bagsR comps ≠ [] := fun h => by simp [h] at hB
have hconvRes : ConvL (resOf D (bags0Of F D bagsR comps)) v := by
rw [resOf_eq_map D hne]
exact convL_map _ (fun B' _ => by
simp only [bagUnion, List.mem_append]
exact ⟨fun h => h.elim id (fun h' => absurd h' hvD), Or.inl⟩)
(hV2 v hv hvD)
exact hconvRes
· have hvF : v ∈ F.nodes := hF.nbrs_sub u v hadj
by_cases huD : u ∈ D
· obtain ⟨X, hX, hvX⟩ := hcovRes v hvF
exact ⟨X, hX, resOf_contains hX u huD, hvX⟩
by_cases hvD : v ∈ D
· obtain ⟨X, hX, huX⟩ := hcovRes u hu
exact ⟨X, hX, huX, resOf_contains hX v hvD⟩
· obtain ⟨B, hB, huB, hvB⟩ := hV3 u v hu hvF huD hvD hadj
obtain ⟨X, hX, hBX⟩ := resOf_ne_nil_of_mem (D := D) hB
exact ⟨X, hX, hBX u huB, hBX v hvB⟩
refine ⟨hValid, fun hDF => ?_⟩
exact fun X hX x hx => resOf_within hDF hbagsF X hX x hx
/-! ## 9. Fallback, plan extraction, and the main theorem -/
theorem fallback_valid {F : Graph} (hF : F.WF) :
ValidPD F [F.nodes] ∧ BagsWithin F [F.nodes] := by
refine ⟨⟨fun v hv => ⟨0, F.nodes, by simp, hv⟩,
fun v hv => convL_full (fun B hB => by rw [List.mem_singleton.1 hB]; exact hv),
fun u v hu hadj => ⟨F.nodes, List.mem_singleton.2 rfl, hu,
hF.nbrs_sub u v hadj⟩⟩, fun B hB x hx => ?_⟩
rw [List.mem_singleton.1 hB] at hx
exact hx
/-- The attachment data of a component that passes the check of `undoF`. -/
theorem ok_extract {F R : Graph} {D : List Nat} {bagsR : List Bag} {C : List Nat} (hR : R.WF)
(h1 : (undoAttach F D C).all R.mem = true)
(h2 : (undoAttach F D C).isEmpty = true ∨ (planOf F D bagsR C).2.2.2.isSome = true) :
(∀ x ∈ undoAttach F D C, x ∈ R.nodes) ∧
(undoAttach F D C ≠ [] → ∃ i Bi, (planOf F D bagsR C).2.2.2 = some i ∧
bagsR[i]? = some Bi ∧ ∀ x ∈ undoAttach F D C, x ∈ Bi) := by
refine ⟨fun x hx => (hR.mem_iff x).1 (List.all_eq_true.1 h1 x hx), fun hne => ?_⟩
have hfalse : (undoAttach F D C).isEmpty = false := by
simpa [List.isEmpty_iff] using hne
have hsome : (planOf F D bagsR C).2.2.2.isSome = true := h2.resolve_left (by rw [hfalse]; decide)
have hidx : (planOf F D bagsR C).2.2.2 = bagsR.findIdx? (subsetB (undoAttach F D C) ·) := by
simp only [planOf, hfalse]
simp
rw [hidx] at hsome ⊢
obtain ⟨i, hi⟩ := Option.isSome_iff_exists.1 hsome
rw [hi]
obtain ⟨hlt, hp, _⟩ := List.findIdx?_eq_some_iff_getElem.1 hi
refine ⟨i, bagsR[i], rfl, List.getElem?_eq_getElem hlt, fun x hx => ?_⟩
have hp' : subsetB (undoAttach F D C) bagsR[i] = true := hp
unfold subsetB at hp'
exact List.contains_iff_mem.1 (List.all_eq_true.1 hp' x hx)
end C7
open C7
theorem undoValid_of (hWF : WFBasics) (hInd : InducedSpec) (hComp : ComponentsSpec)
(hPd : PdTw2Valid) : UndoValid := by
intro F R ops bagsR hF hR hRsub hRadj hVR hBR
unfold undo
unfold undoF
dsimp only
split
· exact ⟨(fallback_valid hF).1, fun _ => (fallback_valid hF).2⟩
· rename_i hnot
generalize hD : deletedSet ops = D at hRsub hnot ⊢
simp only [Bool.not_eq_true', Bool.not_eq_false] at hnot
rw [zipIdx_outFrom]
obtain ⟨hcomp_mem, hcov, hdisj, hclos⟩ :=
restG_components_facts (D := D) hInd hComp hF hR
have hP : ∀ C ∈ (restG F R D).components,
ValidPD (F.induced C.contains) (planOf F D bagsR C).2.1 ∧
BagsWithin (F.induced C.contains) (planOf F D bagsR C).2.1 :=
fun C _ => hPd (F.induced C.contains) ((hInd F C.contains hF).1)
have hok : ∀ C ∈ (restG F R D).components, (∀ x ∈ undoAttach F D C, x ∈ R.nodes) ∧
(undoAttach F D C ≠ [] → ∃ i Bi, (planOf F D bagsR C).2.2.2 = some i ∧
bagsR[i]? = some Bi ∧ ∀ x ∈ undoAttach F D C, x ∈ Bi) := by
intro C hC
have h1 := List.all_eq_true.1 hnot (planOf F D bagsR C) (List.mem_map.2 ⟨C, hC, rfl⟩)
have h2 : (undoAttach F D C).all R.mem = true ∧
((undoAttach F D C).isEmpty = true ∨ (planOf F D bagsR C).2.2.2.isSome = true) := by
simp only [planOf, Bool.and_eq_true, Bool.or_eq_true] at h1
exact ⟨h1.1.1, h1.2⟩
exact ok_extract hR h2.1 h2.2
exact core_valid hInd hF hVR hBR hRadj (fun x hx => (hRsub x hx).1) hcomp_mem hcov hdisj
hclos hP hok
#print axioms CubicPathwidth.Alg.undoValid_of
end CubicPathwidth.Alg
Back to top