CubicPathwidth.Alg.Plan2Deletion

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

import CubicPathwidth.Alg.Plan2

/-!
# Plan interfaces for Tier 3 of Stage 2: the deletion process (task D0)

NOT part of the approval surface (`Spec2.lean`); like `Plan2.lean`, these statements
may be revised during proof work. Nothing is proved here and nothing is assumed.

## Task signatures (Tier 3)

Every task writes ONE file `CubicPathwidth/Alg/Proofs2/<File>.lean` importing
`CubicPathwidth.Alg.Plan2Deletion` (plus Stage 1 proofs and `T4.*` modules as needed),
and proves EXACTLY the theorem(s) below in namespace `CubicPathwidth.Alg`. Stage 1
results (`wfBasics`, `removeNodeSpec`, `inducedSpec`, `componentsSpec`, `unionAllSpec`,
`concatValid`, `plainLayoutValid`, `reduceRecordSpec`, `undoValid`, `t4InitInv`,
`t4LoopPreserves`, `ofSimpleGraphSpec`, `algoT4Exported`, the helpers of
`Proofs/T3LoopPreserves.lean`, ...) and the T4 / T3 theorems (`T4.seqClaim_h`,
`T4.torsoDynamics`, `T4.psiClaim`, `T4.coeff_le`, `T3.goodLabelsCount5_step`, ...) are
imported, never assumed. Stage 2 results are hypotheses with exactly these names.

```
-- D2d  Proofs2/OpsRecordFrame.lean                                  (M, Sonnet)
theorem opsRecordFrame : OpsRecordFrame

-- D6   Proofs2/TorsoLocal.lean                                      (S/M, Sonnet)
theorem torsoLocal : TorsoLocal

-- D3   Proofs2/TorsoBridge.lean                                     (M, Sonnet)
theorem torsoPotentialBridge : TorsoPotentialBridge
theorem psiPortFacts : PsiPortFacts

-- D2a1 Proofs2/T4LoopInit.lean                                      (M, Sonnet)
theorem t4LoopInvInit_of (hMax : ReduceRecordMaximal) (hConn : ComponentsConnected)
    (hCongr : OpsRecordCongr) : T4LoopInvInit

-- D2a2 Proofs2/T4LoopStep.lean                                      (L, Opus)
theorem t4LoopInvStep_of (hMax : ReduceRecordMaximal) (hConn : ComponentsConnected)
    (hCongr : OpsRecordCongr) (hApp : OpsRecordAppend) (hFrame : OpsRecordFrame) :
    T4LoopInvStep

-- D2b  Proofs2/CommitBound.lean                                     (L, Opus)
theorem commitBound_of (hKey : KeyStepAt) (hSim : TorsoSim) (hLoc : TorsoLocal)
    (hBr : TorsoPotentialBridge) (hMax : ReduceRecordMaximal)
    (hConn : ComponentsConnected) (hCongr : OpsRecordCongr) : CommitBound

-- D2c  Proofs2/T4LoopRun.lean                                       (M, Sonnet)
theorem t4LoopRun_of (hStep : T4LoopInvStep) (hCommit : CommitBound) : T4LoopRun

-- D5   Proofs2/DeletionBound.lean                                   (M, Sonnet)
theorem deletionProcessBound_of (hRun : T4LoopRun) (hInit : T4LoopInvInit)
    (hMax : ReduceRecordMaximal) : DeletionProcessBound
theorem t4FinalFacts_of (hRun : T4LoopRun) (hInit : T4LoopInvInit) : T4FinalFacts

-- N4   Proofs2/AlgoT4NoFallback.lean                                (M, Sonnet)
theorem algoT4NoFallback_of (hR1 : ReduceRecordNoFallback) (hD4 : T4LoopNoFallback)
    (hU3 : UndoNoFallback) (hRun : T4LoopRun) (hInit : T4LoopInvInit) : AlgoT4NoFallback

-- U5   Proofs2/ThinComponentWidth.lean   (revised: needs the thin-entry facts)  (S/M)
theorem thinComponentWidth_of (hU4 : UndoWidth) (hRun : T4LoopRun)
    (hInit : T4LoopInvInit) : ThinComponentWidth

-- K4a  Proofs2/SweepBound.lean                                      (M, Sonnet)
theorem sweepComponentBound_of (hL2 : PlainLayoutWidth) (hX2 : RelabelExists)
    (hX3 : DegreeTransfer) (hX4 : LabelTransfer) : SweepComponentBound

-- K4b  Proofs2/AlgoT4Internal.lean                                  (M/L, Opus)
theorem algoT4InternalBound_of (hSw : SweepComponentBound) (hA3 : AlgoT4Width)
    (hU5 : ThinComponentWidth) (hD5 : DeletionProcessBound) (hN4 : AlgoT4NoFallback)
    (hFin : T4FinalFacts) (hPsi : PsiPortFacts) (hX1 : RelabelOfSimpleGraph)
    (hX3 : DegreeTransfer) : AlgoT4InternalBound

-- K4c  Proofs2/AlgoT4Thm4.lean                                      (S, Haiku)
theorem algoT4RealizesTheorem4_of (h : AlgoT4InternalBound) : AlgoT4RealizesTheorem4

-- K5   Proofs2/AlgoT4Cor5.lean                                      (M, Sonnet)
theorem algoT4RealizesCorollary5_of (h : AlgoT4InternalBound) : AlgoT4RealizesCorollary5
```

DAG (leaves first; no cycles):
`D2d, D6, D3` (no Stage 2 hypotheses) → `D2a1, D2a2` (with R2, L3, R3, D2d) and
`D2b` (with D1, R4, D6, D3, R2, L3, R3) → `D2c` → `D5`, `N4` (with R1, D4, U3), `U5`
(with U4) → `K4b` (with K4a, A3, D3, X1, X3) → `K4c`, `K5`.

Routes.
* D2d: induction on `ops`, generalizing `K` and `M`; `redStep` of `M` and of `K` have
  the same nodes/adjacency up to `L` (`M.nbrs v` and `K.nbrs v` have the same elements,
  so the same length; `[a, b]` vs `[b, a]` gives the same `addEdge`).
* D6: `components G U` and `attachment G B T` only read `G` on `U`, `B ∪ T ⊆ F`.
  `Reach` by induction (steps keep `B ⊆ F` and shrink `F`).
* D3: `tcomps` are the node sets (closed, connected via `ReflTransGen`); `tdeg` =
  `J.degree` (the torso neighbours of `x ∈ J` are its `J`-neighbours, `nbrs` nodup);
  then `T4.psiMinus_eq_sum`. `PsiPortFacts`: `T4.runMin_le_self`,
  `T4.runMin_le_incr_three`, `T4.incr_three`.
* D2a1: Stage 1 `t4InitInv`; `OpsRecord G0.copy ops0 H` from R2, moved to `G0` by R3;
  `SameGraph H (unionAll (componentGraphs H).reverse)`; pieces by R2, L3.
* D2a2: four cases. Dump, finalize and thin: the graph list is permuted (Stage 1
  `T4Inv_perm`; `OpsRecord` only sees `R` up to `SameGraph`). Thin record: R2 on
  `J.copy.removeNode w`, R3 to `J.removeNode w`, final graph has no nodes. Commit:
  Stage 1 `commit_inv`; `OpsRecord M tops M'` by D2d with `K = J`,
  `L = unionAll (rest ++ finals)`, then R3-append; new pieces by R2, L3.
* D2b: `n` above every node of `J`, `S := J.toSimpleGraph n`, `V0` its node set.
  R4 with `ops = []` gives `Good S V0 V0` and the torso `J`; R4 on
  `J.removeNode w` (graph `S'`) with ops `red`, moved to `S` by D6 (`S`, `S'` agree on
  `V0.erase w`), gives the `Reach` and the torso `red.1`. D3 turns degrees, `tcomps`
  and `psiMinus` into port quantities; D1 at `C = V0` (regularity disjunction: a
  connected non-regular `J` has a maximum-degree vertex with a smaller neighbour, so
  `good ≠ []`); `T4.seqClaim_h.1` for `BootProps sigma`.
* D2c: induction on `fuel`; commit: `deletedSet` grows by one (`reduceRecordSpec`:
  only reductions), `List.Perm.sum_eq`, `CommitBound`.
* D5: `DeletionProcessBound` from D2c at the initial state, start value
  `∑ ψ⁻(components of H) ≤ ψ(H) ≤ ψ(G0) = ψ(G)` (`runMin ≥ 0`, R2 degrees,
  `σ 0 = 0` for isolated vertices, `σ` monotone and `≥ 0`).
* K4b: width `≤ D + max_e w_e + 3 log₂ n₀ + 1` (A3); sweep `w_e ≤ ψ(J) + ε n₀ + N ≤
  ψ⁻(J) + σ₃ + ε n₀ + N ≤ ∑ψ⁻ + σ₃ + ε n₀ + N` (K4a, D3, `T4FinalFacts`), thin
  `w_e ≤ 3 log₂ n₀ + 1` (U5); D5; `ψ(G) = degreeWeight S σ ≤ degreeWeight S thm4Coeff`;
  `6 log₂ n₀ + 2 ≤ ε n₀ + C`. The labeler is chosen per graph (`final` does not depend
  on `lab`, definitionally).
* K4c: `nonIsolatedCount S ≤ n`; `algoT4Exported`. K5: `nonIsolatedCount S ≤ 2m`,
  `T4.coeff_le`, `∑ deg = 2m`, `T4.hasPathwidth_mono`.
-/

noncomputable section

namespace CubicPathwidth.Alg

open Graph

/-! ## 6.5 Records in disjoint unions, locality of torsos -/

/-- Frame rule: a record on `K` is a record on any graph `M` that is the disjoint union
of `K` and `L`, ending in the disjoint union of the final graph `K'` and `L`. -/
def OpsRecordFrame : Prop :=
  ∀ (K K' L M M' : Graph) (ops : List Op), K.WF → L.WF → M.WF →
    (∀ x, x ∈ K.nodes → x ∉ L.nodes) →
    (∀ v, v ∈ M.nodes ↔ v ∈ K.nodes ∨ v ∈ L.nodes) →
    (∀ u v, M.Adj u v ↔ K.Adj u v ∨ L.Adj u v) →
    (∀ v, v ∈ M'.nodes ↔ v ∈ K'.nodes ∨ v ∈ L.nodes) →
    (∀ u v, M'.Adj u v ↔ K'.Adj u v ∨ L.Adj u v) →
    OpsRecord K ops K' → OpsRecord M ops M'

/-- The torso of a state, and reachability from it, only depend on the graph inside
the undeleted vertices. -/
def TorsoLocal : Prop :=
  ∀ (n : ℕ) (S S' : SimpleGraph (Fin n)) (F₀ : Finset (Fin n)),
    (∀ u ∈ F₀, ∀ v ∈ F₀, S.Adj u v ↔ S'.Adj u v) →
    (∀ F B : Finset (Fin n), B ⊆ F → F ⊆ F₀ → T4.tgraph S F B = T4.tgraph S' F B) ∧
    ∀ F B F' B' : Finset (Fin n), B ⊆ F → F ⊆ F₀ →
      T4.Reach S' (F, B) (F', B') → T4.Reach S (F, B) (F', B')

/-! ## 6.6 Pieces and the potential bridge (D3) -/

/-- A graph on the work list or in `final` of `algo_T4`: well formed, nonempty,
connected, minimum degree at least `3`. -/
def T4Piece (J : Graph) : Prop :=
  J.WF ∧ J.nodes ≠ [] ∧
    (∀ x ∈ J.nodes, ∀ y ∈ J.nodes, Relation.ReflTransGen J.Adj x y) ∧
    ∀ v ∈ J.nodes, 3 ≤ J.degree v

/-- The node set of a graph as a `Finset (Fin n)`. -/
def finNodes (n : ℕ) (J : Graph) : Finset (Fin n) :=
  Finset.univ.filter fun x : Fin n => x.val ∈ J.nodes

/-- (D3) A torso state whose torso is the disjoint union of a list of connected,
nonempty graphs (on vertices below `n`): torso degrees are degrees, torso components
are the node sets, and `ψ`, `ψ⁻` are the sums of `psiPort`, `psiMinusPort`. -/
def TorsoPotentialBridge : Prop :=
  ∀ (n : ℕ) (S : SimpleGraph (Fin n)) (F B : Finset (Fin n)) (gs : List Graph),
    (∀ J ∈ gs, J.WF ∧ J.nodes ≠ [] ∧
      ∀ x ∈ J.nodes, ∀ y ∈ J.nodes, Relation.ReflTransGen J.Adj x y) →
    gs.Pairwise (fun A C => ∀ x, x ∈ A.nodes → x ∉ C.nodes) →
    (∀ J ∈ gs, ∀ v ∈ J.nodes, v < n) →
    (∀ x : Fin n, x ∈ B ↔ ∃ J ∈ gs, x.val ∈ J.nodes) →
    (∀ x y : Fin n, (T4.tgraph S F B).Adj x y ↔ ∃ J ∈ gs, J.Adj x.val y.val) →
    (∀ J ∈ gs, ∀ x : Fin n, x.val ∈ J.nodes → T4.tdeg S F B x = J.degree x.val) ∧
    (∀ J ∈ gs, finNodes n J ∈ T4.tcomps S F B) ∧
    (∀ C ∈ T4.tcomps S F B, ∃ J ∈ gs, C = finNodes n J) ∧
    ∀ b : ℕ → ℝ, T4.psi b S F B = (gs.map (psiPort b)).sum ∧
      T4.psiMinus b S F B = (gs.map (psiMinusPort b)).sum

/-- (D3) `0 ≤ ψ⁻(J)` and `ψ(J) ≤ ψ⁻(J) + b₃` for a nonempty graph of minimum degree at
least `3` (port form of `T4.PsiClaim` and `runMin ≤ b₃`). -/
def PsiPortFacts : Prop :=
  ∀ b : ℕ → ℝ, T4.BootProps b → ∀ J : Graph, J.WF → J.nodes ≠ [] →
    (∀ v ∈ J.nodes, 3 ≤ J.degree v) →
    0 ≤ psiMinusPort b J ∧ psiPort b J ≤ psiMinusPort b J + b 3

/-! ## 6.7 The loop invariant of `t4Loop` (D2) -/

/-- (D2, part (a)) Structural invariant of the work loop of `algo_T4` relative to
`G0 = nonIsolated G`, for the work stack, the final list and the global ops: Stage 1's
`T4Inv` and `ThinOK`, the global ops are a legal record from `G0` to the union of all
current graphs, every current graph is a `T4Piece`, and every thin entry carries a
legal record emptying its graph with exactly one deletion. -/
def T4LoopInv (G0 : Graph) (stack : List Graph) (final : List FinalEntry) (ops : List Op) :
    Prop :=
  T4Inv G0 (stack ++ final.map (·.graph)) ops ∧ ThinOK final ∧
    OpsRecord G0 ops (unionAll (stack ++ final.map (·.graph))) ∧
    (∀ J ∈ stack ++ final.map (·.graph), T4Piece J) ∧
    ∀ e ∈ final, e.kind = FinalKind.thin →
      OpsRecord e.graph e.tops Graph.empty ∧ (deletedSet e.tops).length = 1

/-- (D2, part (b)) The potential `|D| + ∑_{J ∈ stack ++ final} ψ⁻_b(J)`, with `|D|`
the number of deletions recorded in the global ops. -/
def T4Pot (b : ℕ → ℝ) (stack : List Graph) (final : List FinalEntry) (ops : List Op) : ℝ :=
  ((deletedSet ops).length : ℝ) + ((stack ++ final.map (·.graph)).map (psiMinusPort b)).sum

/-- (D2a1) The invariant holds at the start of the loop in `algoT4Full`. -/
def T4LoopInvInit : Prop :=
  ∀ G : Graph, G.WF →
    let r := reduceRecordF (nonIsolated G).copy
    T4LoopInv (nonIsolated G) (componentGraphs r.1).reverse [] r.2.1

/-- (D2a2) One round of `t4Loop` preserves the structural invariant: fuel exhaustion
(the stack is dumped into `final`), finalizing a graph of maximum degree `≤ 5`, a thin
round, and a commit. -/
def T4LoopInvStep : Prop :=
  (∀ (G0 : Graph) (stack : List Graph) (final : List FinalEntry) (ops : List Op),
    G0.WF → T4LoopInv G0 stack final ops →
    T4LoopInv G0 [] (final ++ stack.map fun J => FinalEntry.mk J FinalKind.sweep []) ops) ∧
  ∀ (G0 J : Graph) (rest : List Graph) (final : List FinalEntry) (ops : List Op),
    G0.WF → T4LoopInv G0 (J :: rest) final ops →
    (J.maxDegree ≤ 5 →
      T4LoopInv G0 rest (final ++ [FinalEntry.mk J FinalKind.sweep []]) ops) ∧
    (¬ J.maxDegree ≤ 5 →
      let w := t4ChooseW J
      let red := reduceRecordF (J.copy.removeNode w)
      (red.1.numNodes = 0 →
        T4LoopInv G0 rest (final ++ [FinalEntry.mk J FinalKind.thin (Op.del w :: red.2.1)]) ops) ∧
      (red.1.numNodes ≠ 0 →
        T4LoopInv G0 ((componentGraphs red.1).reverse ++ rest) final
          (ops ++ (Op.del w :: red.2.1))))

/-- (D2b) Lemma A.34 (`lem:alg-deletion`) for one commit of the algorithm (via
`KeyStepAt`): deleting the chosen vertex `w` of a piece of maximum degree `≥ 6` and
reducing, when something survives, lowers `ψ⁻_σ` by at least `1`. -/
def CommitBound : Prop :=
  ∀ J : Graph, T4Piece J → ¬ J.maxDegree ≤ 5 →
    let red := reduceRecordF (J.copy.removeNode (t4ChooseW J))
    red.1.numNodes ≠ 0 →
    1 + ((componentGraphs red.1).map (psiMinusPort T4.sigma)).sum ≤ psiMinusPort T4.sigma J

/-- (D2c) The whole run of `t4Loop` (any fuel) from a state satisfying the invariant:
the invariant holds at the end, the potential `T4Pot σ` does not increase, and without
fallback every `.sweep` entry has maximum degree at most `5`. -/
def T4LoopRun : Prop :=
  ∀ (G0 : Graph) (fuel : Nat) (stack : List Graph) (final : List FinalEntry) (ops : List Op),
    G0.WF → T4LoopInv G0 stack final ops →
    (∀ e ∈ final, e.kind = FinalKind.sweep → e.graph.maxDegree ≤ 5) →
    let r := t4Loop fuel stack final ops
    T4LoopInv G0 [] r.1 r.2.1 ∧
      T4Pot T4.sigma [] r.1 r.2.1 ≤ T4Pot T4.sigma stack final ops ∧
      (r.2.2 = false → ∀ e ∈ r.1, e.kind = FinalKind.sweep → e.graph.maxDegree ≤ 5)

/-- (D5, second theorem) What the corollaries use about the final components of a run
without fallback. -/
def T4FinalFacts : Prop :=
  ∀ G : Graph, G.WF → ∀ lab : Labeler, (algoT4Full G lab).fallback = false →
    ∀ e ∈ (algoT4Full G lab).final,
      T4Piece e.graph ∧ e.graph.numNodes ≤ (nonIsolated G).numNodes ∧
        (e.kind = FinalKind.sweep → e.graph.MaxDegLE 5)

/-! ## 6.8 Internal form of Theorem 4 for `algo_T4` (K4, K5) -/

/-- (K4a) Plain sweep of one `.sweep` component with good labels: width at most
`ψ_σ(J) + ε |J| + N` (Theorem 3 with the triple `S` at minimum degree `3`,
`T3.GoodLabelsCount5`; small components by the trivial bound). -/
def SweepComponentBound : Prop :=
  T3.AdmissibleTriple (5 / 32) (1 / 4) (11 / 32) →
    ∀ ε : ℝ, 0 < ε → ∃ N : ℕ, ∀ J : Graph, J.WF → J.MaxDegLE 5 →
      (∀ v ∈ J.nodes, 3 ≤ J.degree v) →
      ∃ Y : Labels, pdWidth (plainLayout J Y) ≤ psiPort T4.sigma J + ε * (J.numNodes : ℝ) + N

/-- The number `n₀` of non-isolated vertices. -/
def nonIsolatedCount {n : ℕ} (S : SimpleGraph (Fin n)) : ℕ := by
  classical
  exact (Finset.univ.filter fun v : Fin n => S.degree v ≠ 0).card

/-- (K4b) Internal form of Theorem 4 for `algo_T4`: `ε n₀ + C(ε)` with `n₀` the number of
non-isolated vertices, for EVERY `n` (no threshold). Both `AlgoT4RealizesTheorem4`
(`n₀ ≤ n`) and `AlgoT4RealizesCorollary5` (`n₀ ≤ 2m`, `thm4Coeff d ≤ 7d/96`) follow. -/
def AlgoT4InternalBound : Prop :=
  T3.AdmissibleTriple (5 / 32) (1 / 4) (11 / 32) →
    ∀ ε : ℝ, 0 < ε → ∃ C : ℝ, ∀ (n : ℕ) (S : SimpleGraph (Fin n)) [DecidableRel S.Adj],
      ∃ lab : Labeler,
        (algoT4Full (Graph.ofSimpleGraph S) lab).fallback = false ∧
        pdWidth (algoT4 (Graph.ofSimpleGraph S) lab) ≤
          T4.degreeWeight S T4.thm4Coeff + ε * (nonIsolatedCount S : ℝ) + C

end CubicPathwidth.Alg
Back to top