CubicPathwidth.Alg.Proofs.C6PdTw2

Source file CubicPathwidth/Alg/Proofs/C6PdTw2.lean of the Lean project (how it is built).

import CubicPathwidth.Alg.Spec

/-!
# C6: validity of `pd_tw2` (`PdTw2Valid`)

Induction on the fuel. Base cases and fallbacks give a single bag `H.nodes` (or `[]` when
`H` has no nodes). The main case glues, at the separator `X = v :: nb` of a reduction
recorded by `reduceRecordF H.copy` (`SeparatorGlueValid`), the recursive decompositions of
the induced graphs `H[c]` for the components `c` of `H[V \ X]`.
Hypotheses are taken from `Spec.lean`: `WFBasics`, `InducedSpec`, `ComponentsSpec`,
`SeparatorGlueValid`, `ReduceRecordSpec`.
-/

namespace CubicPathwidth.Alg

open Graph

namespace C6

/-- The single bag `[H.nodes]` is a valid decomposition of a well-formed graph. -/
theorem single_valid (H : Graph) (hH : H.WF) :
    ValidPD H [H.nodes] ∧ BagsWithin H [H.nodes] := by
  refine ⟨⟨?_, ?_, ?_⟩, ?_⟩
  · intro v hv
    exact ⟨0, H.nodes, rfl, hv⟩
  · intro v hv i j k hij hjk hi hk
    obtain ⟨B, hB, hvB⟩ := hk
    have hk0 : k = 0 := by
      rcases k with _ | k
      · rfl
      · simp at hB
    subst hk0
    have hj0 : j = 0 := by omega
    subst hj0
    exact ⟨H.nodes, rfl, hv⟩
  · intro u v hu huv
    exact ⟨H.nodes, List.mem_singleton.2 rfl, hu, hH.nbrs_sub u v huv⟩
  · intro B hB v hv
    rw [List.mem_singleton] at hB
    subst hB
    exact hv

/-- The empty decomposition is valid for a graph with no nodes. -/
theorem empty_valid (H : Graph) (h0 : H.numNodes = 0) :
    ValidPD H [] ∧ BagsWithin H [] := by
  have hlen : H.nodes.length = 0 := h0
  have hn : H.nodes = [] := List.length_eq_zero_iff.1 hlen
  refine ⟨⟨?_, ?_, ?_⟩, ?_⟩
  · intro v hv
    rw [hn] at hv
    simp at hv
  · intro v hv
    rw [hn] at hv
    simp at hv
  · intro u v hu _
    rw [hn] at hu
    simp at hu
  · intro B hB
    simp at hB

/-- Membership in the elimination bags: `X = v :: nb` for a recorded reduction. -/
theorem mem_elimBags_iff (ops : List Op) (X : Bag) (h : X ∈ elimBags ops) :
    ∃ v nb, Op.red v nb ∈ ops ∧ X = v :: nb := by
  unfold elimBags at h
  rw [List.mem_filterMap] at h
  obtain ⟨o, ho, hX⟩ := h
  cases o with
  | red v nb =>
    simp only at hX
    exact ⟨v, nb, ho, (Option.some.inj hX).symm⟩
  | del w =>
    simp at hX

/-- The node list of an induced graph is a permutation of the filtered node list. -/
theorem induced_nodes_perm (H : Graph) (keep : Nat → Bool) (hH : H.WF)
    (hInd : InducedSpec) :
    (H.induced keep).nodes.Perm (H.nodes.filter keep) := by
  have hI := hInd H keep hH
  rw [List.perm_ext_iff_of_nodup hI.1.nodup (List.Nodup.filter keep hH.nodup)]
  intro a
  rw [hI.2.1 a, List.mem_filter]

/-- The components of `H[V \ X]`. -/
def compsOf (H : Graph) (X : List Nat) : List (List Nat) :=
  (H.induced fun v => !X.contains v).components

/-- The output of the gluing step of `pd_tw2`, written as in `pdTw2Fuel`. -/
def glueOut (H : Graph) (X : List Nat) (f : Nat) : List Bag :=
  let parts := (compsOf H X).map fun c => pdTw2Fuel f (H.induced c.contains)
  let out := parts.flatMap fun p => p.1.map fun B => bagUnion B X
  if out.isEmpty then [X] else out

/-- The gluing step is valid, given the induction hypothesis for fuel `f`. -/
theorem glue_valid (hInd : InducedSpec) (hComp : ComponentsSpec)
    (hGlue : SeparatorGlueValid) (f : Nat)
    (ih : ∀ K : Graph, K.WF → ValidPD K (pdTw2Fuel f K).1 ∧ BagsWithin K (pdTw2Fuel f K).1)
    (H : Graph) (X : List Nat) (hH : H.WF) (hX : ∀ x ∈ X, x ∈ H.nodes) :
    ValidPD H (glueOut H X f) ∧ BagsWithin H (glueOut H X f) := by
  have hI := hInd H (fun v => !X.contains v) hH
  have hH' : (H.induced fun v => !X.contains v).WF := hI.1
  have hcp := hComp _ hH'
  -- the parts, paired with their recursive decompositions
  have hpm : ((compsOf H X).map fun c => (c, (pdTw2Fuel f (H.induced c.contains)).1)).map
      (fun p => p.1) = compsOf H X := by
    rw [List.map_map]
    exact List.map_id _
  have hperm : (((compsOf H X).map fun c =>
      (c, (pdTw2Fuel f (H.induced c.contains)).1)).map (fun p => p.1)).flatten.Perm
      (H.nodes.filter fun v => !X.contains v) := by
    rw [hpm]
    exact hcp.1.trans (induced_nodes_perm H (fun v => !X.contains v) hH hInd)
  have hclos : ∀ p ∈ (compsOf H X).map (fun c => (c, (pdTw2Fuel f (H.induced c.contains)).1)),
      ∀ x ∈ p.1, ∀ y, H.Adj x y → y ∈ p.1 ∨ y ∈ X := by
    intro p hp x hx y hxy
    obtain ⟨c, hc, rfl⟩ := List.mem_map.1 hp
    change x ∈ c at hx
    change y ∈ c ∨ y ∈ X
    by_cases hyX : y ∈ X
    · exact Or.inr hyX
    · left
      have hxN : x ∈ (H.induced fun v => !X.contains v).nodes :=
        hcp.1.mem_iff.1 (List.mem_flatten.2 ⟨c, hc, hx⟩)
      have hxk : (!X.contains x) = true := ((hI.2.1 x).1 hxN).2
      have hyk : (!X.contains y) = true := by simp [hyX]
      have hadj : (H.induced fun v => !X.contains v).Adj x y :=
        (hI.2.2 x y).2 ⟨hxy, hxk, hyk⟩
      exact hcp.2.2 c hc x hx y hadj
  have hrec : ∀ p ∈ (compsOf H X).map (fun c => (c, (pdTw2Fuel f (H.induced c.contains)).1)),
      ValidPD (H.induced p.1.contains) p.2 ∧ BagsWithin (H.induced p.1.contains) p.2 := by
    intro p hp
    obtain ⟨c, _, rfl⟩ := List.mem_map.1 hp
    exact ih (H.induced c.contains) (hInd H _ hH).1
  have hglue := hGlue H X _ hH hX hperm hclos hrec
  dsimp only at hglue
  simp only [List.flatMap_map] at hglue
  unfold glueOut
  simp only [List.flatMap_map]
  exact hglue

/-- Main induction: `pd_tw2` with fuel `fuel` is valid on every well-formed graph. -/
theorem main_fuel (hWF : WFBasics) (hInd : InducedSpec) (hComp : ComponentsSpec)
    (hGlue : SeparatorGlueValid) (hRed : ReduceRecordSpec) :
    ∀ (fuel : Nat) (H : Graph), H.WF →
      ValidPD H (pdTw2Fuel fuel H).1 ∧ BagsWithin H (pdTw2Fuel fuel H).1 := by
  intro fuel
  induction fuel with
  | zero =>
    intro H hH
    by_cases h0 : H.numNodes = 0
    · have e : (pdTw2Fuel 0 H).1 = [] := by
        unfold pdTw2Fuel
        rw [if_pos h0]
      rw [e]
      exact empty_valid H h0
    · have e : (pdTw2Fuel 0 H).1 = [H.nodes] := by
        unfold pdTw2Fuel
        rw [if_neg h0]
        split <;> rfl
      rw [e]
      exact single_valid H hH
  | succ f ih =>
    intro H hH
    by_cases h0 : H.numNodes = 0
    · have e : (pdTw2Fuel (f + 1) H).1 = [] := by
        unfold pdTw2Fuel
        rw [if_pos h0]
      rw [e]
      exact empty_valid H h0
    by_cases h3 : H.numNodes ≤ 3
    · have e : (pdTw2Fuel (f + 1) H).1 = [H.nodes] := by
        unfold pdTw2Fuel
        rw [if_neg h0, if_pos h3]
      rw [e]
      exact single_valid H hH
    have hcopy : H.copy.WF := (hInd H (fun _ => true) hH).1
    have hops := (hRed H.copy hcopy).2.2.2.1
    unfold pdTw2Fuel
    rw [if_neg h0, if_neg h3]
    dsimp only
    split
    · exact single_valid H hH
    · split
      · exact single_valid H hH
      · rename_i X heq
        have hXm := List.mem_of_find?_eq_some heq
        obtain ⟨v, nb, hop, rfl⟩ := mem_elimBags_iff _ _ hXm
        have hX : ∀ x ∈ v :: nb, x ∈ H.nodes := by
          obtain ⟨v', nb', he, hv', -, hnb'⟩ := hops (Op.red v nb) hop
          obtain ⟨rfl, rfl⟩ := Op.red.inj he
          intro x hx
          rcases List.mem_cons.1 hx with rfl | hx
          · exact ((hInd H (fun _ => true) hH).2.1 x).1 hv' |>.1
          · exact ((hInd H (fun _ => true) hH).2.1 x).1 (hnb' x hx) |>.1
        exact glue_valid hInd hComp hGlue f ih H (v :: nb) hH hX

end C6

/-- Theorem `pd_tw2` (`PdTw2Valid`): valid for every well-formed graph. -/
theorem pdTw2Valid_of (hWF : WFBasics) (hInd : InducedSpec) (hComp : ComponentsSpec)
    (hGlue : SeparatorGlueValid) (hRed : ReduceRecordSpec) : PdTw2Valid := by
  intro H hH
  exact C6.main_fuel hWF hInd hComp hGlue hRed H.numNodes H hH

#print axioms CubicPathwidth.Alg.pdTw2Valid_of

end CubicPathwidth.Alg
Back to top