CubicPathwidth.Alg.Proofs.A3T4

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

import CubicPathwidth.Alg.Spec

/-!
# Task A3: validity of `algo_T4` from its hypotheses (task A3)

`algoT4Valid_of` takes the statements T1, T2, G6, G7, C2, C7 and T3 as hypotheses (each is
proved in another file) and proves `AlgoT4Valid`.

Route: `G0 := nonIsolated G`; the work loop of `algo_T4` keeps the invariant `T4Inv`
(`T4InitInv` and `T4LoopPreserves`). Every final entry decomposes validly inside its own
graph (`PlainLayoutValid` for `.sweep`; `UndoValid` with `R = Graph.empty` for `.thin`).
`ConcatValid` decomposes `R = unionAll` of the final graphs; `UndoValid` on `G0` inserts
the deletions; `AppendIsolatedValid` appends the isolated vertices.
-/

namespace CubicPathwidth.Alg

open Graph

namespace A3

/-- `T4Inv` depends only on the membership of the graphs in the work list, and the
disjointness clause is symmetric, so a permutation of the list preserves it. -/
theorem t4Inv_perm {G0 : Graph} {gs gs' : List Graph} {ops : List Op}
    (hp : gs.Perm gs') (h : T4Inv G0 gs ops) : T4Inv G0 gs' ops := by
  obtain ⟨h1, h2, h3, h4, h5⟩ := h
  refine ⟨fun J hJ => h1 J (hp.mem_iff.2 hJ), ?_, fun J hJ => h3 J (hp.mem_iff.2 hJ), h4, ?_⟩
  · exact (List.Perm.pairwise_iff (R := fun A B : Graph => ∀ x, x ∈ A.nodes → x ∉ B.nodes)
      (fun {A B} h x hB hA => h x hA hB) hp).1 h2
  · intro x y hxy hx hy
    have hx' : ∃ J ∈ gs, x ∈ J.nodes := by
      obtain ⟨J, hJ, hxJ⟩ := hx
      exact ⟨J, hp.mem_iff.2 hJ, hxJ⟩
    have hy' : ∃ J ∈ gs, y ∈ J.nodes := by
      obtain ⟨J, hJ, hyJ⟩ := hy
      exact ⟨J, hp.mem_iff.2 hJ, hyJ⟩
    obtain ⟨J, hJ, hadj⟩ := h5 x y hxy hx' hy'
    exact ⟨J, hp.mem_iff.1 hJ, hadj⟩

/-- The empty graph is well formed. -/
theorem empty_wf : Graph.empty.WF where
  nodup := List.nodup_nil
  mem_iff := by intro v; simp [Graph.mem, Graph.empty]
  nbrs_nodup := by intro v; simp [Graph.nbrs, Graph.empty]
  nbrs_sub := by intro u v h; simp [Graph.nbrs, Graph.empty] at h
  symm := by intro u v h; simp [Graph.nbrs, Graph.empty] at h
  loopless := by intro v h; simp [Graph.nbrs, Graph.empty] at h

/-- The empty decomposition is valid for the empty graph. -/
theorem validPD_empty : ValidPD Graph.empty [] := by
  unfold ValidPD
  refine ⟨?_, ?_, ?_⟩
  · intro v hv; simp [Graph.empty] at hv
  · intro v hv; simp [Graph.empty] at hv
  · intro u v hu; simp [Graph.empty] at hu

/-- No bags, so no bag leaves the graph. -/
theorem bagsWithin_nil (G : Graph) : BagsWithin G [] := by
  unfold BagsWithin
  intro B hB
  simp at hB

/-- Flattening the parts of the concatenation gives the bags of the thin/sweep entries. -/
theorem flatMap_parts (lab : Labeler) (l : List FinalEntry) :
    (l.map (fun e => (e.graph, (t4Decompose lab e).1))).flatMap (·.2) =
      (l.map (t4Decompose lab)).flatMap (·.1) := by
  simp only [List.flatMap_map]

/-- Each final entry decomposes validly inside its own graph. -/
theorem finalPart (hPL : PlainLayoutValid) (hUndo : UndoValid) (lab : Labeler)
    (final : List FinalEntry) (hWF : ∀ J ∈ final.map (·.graph), J.WF)
    (hTh : ThinOK final) :
    ∀ e ∈ final, ValidPD e.graph (t4Decompose lab e).1 ∧
      BagsWithin e.graph (t4Decompose lab e).1 := by
  intro e he
  rcases e with ⟨g, k, tops⟩
  have hw : g.WF := hWF g (List.mem_map_of_mem (f := fun e : FinalEntry => e.graph) he)
  cases k with
  | sweep => exact hPL g hw (lab g)
  | thin =>
    have h := hUndo g Graph.empty tops [] hw empty_wf
      (by intro x hx; simp [Graph.empty] at hx)
      (by intro x y hx; simp [Graph.empty] at hx)
      validPD_empty (bagsWithin_nil _)
    exact ⟨h.1, h.2 (hTh ⟨g, FinalKind.thin, tops⟩ he)⟩

/-- The decomposition of the final graphs and the deletions, from the invariant. -/
theorem finalStep (hU : UnionAllSpec) (hCat : ConcatValid)
    (hPL : PlainLayoutValid) (hUndo : UndoValid) (hIso : AppendIsolatedValid)
    (G : Graph) (lab : Labeler) (hG : G.WF) (final : List FinalEntry) (ops : List Op)
    (hG0 : (nonIsolated G).WF)
    (hT : T4Inv (nonIsolated G) (final.map (·.graph)) ops) (hTh : ThinOK final) :
    ValidPD G ((undoF (nonIsolated G) ops (unionAll (final.map (·.graph)))
      ((final.map (t4Decompose lab)).flatMap (·.1))).1 ++ isolatedBags G) := by
  obtain ⟨hWF, hPw, hNd, hDel, hEdge⟩ := hT
  have hPart := finalPart hPL hUndo lab final hWF hTh
  -- the parts of `ConcatValid`
  have hparts : ∀ p ∈ final.map (fun e => (e.graph, (t4Decompose lab e).1)),
      p.1.WF ∧ ValidPD p.1 p.2 ∧ BagsWithin p.1 p.2 := by
    intro p hp
    obtain ⟨e, he, rfl⟩ := List.mem_map.1 hp
    exact ⟨hWF _ (List.mem_map_of_mem (f := fun e : FinalEntry => e.graph) he),
      (hPart e he).1, (hPart e he).2⟩
  have hdis : (final.map (fun e => (e.graph, (t4Decompose lab e).1))).Pairwise
      (fun A B => ∀ x, x ∈ A.1.nodes → x ∉ B.1.nodes) :=
    List.pairwise_map.2 (List.pairwise_map.1 hPw)
  obtain ⟨hV, hB⟩ := hCat (final.map (fun e => (e.graph, (t4Decompose lab e).1))) hparts hdis
  have e1 : (final.map (fun e => (e.graph, (t4Decompose lab e).1))).map (·.1) =
      final.map (·.graph) := by
    simp only [List.map_map]
    rfl
  have e2 : (final.map (fun e => (e.graph, (t4Decompose lab e).1))).flatMap (·.2) =
      (final.map (t4Decompose lab)).flatMap (·.1) := flatMap_parts lab final
  rw [e1, e2] at hV hB
  -- the union of the final graphs
  have hRU := hU (final.map (·.graph)) (fun J hJ => hWF J hJ)
  have hRsub : ∀ x ∈ (unionAll (final.map (·.graph))).nodes,
      x ∈ (nonIsolated G).nodes ∧ x ∉ deletedSet ops := by
    intro x hx
    obtain ⟨J, hJ, hxJ⟩ := (hRU.2.1 x).1 hx
    exact hNd J hJ x hxJ
  have hRadj : ∀ x y, x ∈ (unionAll (final.map (·.graph))).nodes →
      y ∈ (unionAll (final.map (·.graph))).nodes →
      (nonIsolated G).Adj x y → (unionAll (final.map (·.graph))).Adj x y := by
    intro x y hx hy hxy
    obtain ⟨J1, hJ1, hx1⟩ := (hRU.2.1 x).1 hx
    obtain ⟨J2, hJ2, hy2⟩ := (hRU.2.1 y).1 hy
    obtain ⟨J, hJ, hadj⟩ := hEdge x y hxy ⟨J1, hJ1, hx1⟩ ⟨J2, hJ2, hy2⟩
    exact (hRU.2.2 x y).2 ⟨J, hJ, hadj⟩
  -- undo the reductions and deletions, then the isolated vertices
  obtain ⟨hV0, hB0⟩ := hUndo (nonIsolated G) (unionAll (final.map (·.graph))) ops
    ((final.map (t4Decompose lab)).flatMap (·.1)) hG0 hRU.1 hRsub hRadj hV hB
  exact hIso G hG _ hV0 (hB0 hDel)

end A3

/-- Validity of `algo_T4` (task A3), from the hypotheses proved in other files. -/
theorem algoT4Valid_of (hWF : WFBasics) (hInd : InducedSpec) (hU : UnionAllSpec)
    (hCat : ConcatValid) (hPL : PlainLayoutValid) (hUndo : UndoValid) (hInit : T4InitInv)
    (hLoop : T4LoopPreserves) (hIso : AppendIsolatedValid) : AlgoT4Valid := by
  intro G hG lab
  have hG0 : (nonIsolated G).WF := (hInd G (fun v => G.degree v != 0) hG).1
  have hT0 : T4Inv (nonIsolated G) (componentGraphs (reduceRecordF (nonIsolated G).copy).1)
      (reduceRecordF (nonIsolated G).copy).2.1 := hInit G hG
  have hStart : T4Inv (nonIsolated G)
      ((componentGraphs (reduceRecordF (nonIsolated G).copy).1).reverse ++
        ([] : List FinalEntry).map (·.graph))
      (reduceRecordF (nonIsolated G).copy).2.1 := by
    rw [List.map_nil, List.append_nil]
    exact A3.t4Inv_perm (List.reverse_perm _).symm hT0
  have hL := hLoop (nonIsolated G) (2 * (reduceRecordF (nonIsolated G).copy).1.numNodes + 1)
    _ [] _ hG0 hStart (by unfold ThinOK; intro e he; simp at he)
  obtain ⟨hT, hTh⟩ := hL
  have key := A3.finalStep hU hCat hPL hUndo hIso G lab hG _ _ hG0 hT hTh
  exact key

#print axioms CubicPathwidth.Alg.algoT4Valid_of

end CubicPathwidth.Alg
Back to top