CubicPathwidth.Alg.Proofs2.R4TorsoSim
Source file CubicPathwidth/Alg/Proofs2/R4TorsoSim.lean of the Lean project (how it is built).
import CubicPathwidth.Alg.Plan2
import CubicPathwidth.Alg.Proofs.Targets
import CubicPathwidth.T4.TorsoDyn
/-!
# R4: the record of reductions and deletions is a torso simulation
Proves `TorsoSim` (`Plan2.lean` §6.2) from the torso dynamics `T4.torsoDynamics`
(`T4/TorsoDyn.lean`). The invariant `Inv` says that the current graph of the record is
the torso of the state `(F, B)`: `B` is the node set and the torso adjacency is the
adjacency of the current graph.
-/
noncomputable section
namespace CubicPathwidth.Alg.R4
/-! ## Graph facts about `redStep` -/
theorem mem_of_len_le_one {L : List Nat} (h : L.length ≤ 1) {x y : Nat}
(hx : x ∈ L) (hy : y ∈ L) : x = y := by
rcases L with _ | ⟨a, _ | ⟨b, t⟩⟩
· simp at hx
· simp at hx hy
omega
· simp at h
theorem redStep_cases (G : Graph) (v : Nat) :
(∃ a b, G.nbrs v = [a, b] ∧ redStep G v = (G.removeNode v).addEdge a b) ∨
((G.nbrs v).length ≤ 1 ∧ redStep G v = G.removeNode v) ∨
(3 ≤ (G.nbrs v).length ∧ redStep G v = G.removeNode v) := by
unfold redStep
rcases h : G.nbrs v with _ | ⟨a, _ | ⟨b, _ | ⟨c, t⟩⟩⟩
· right; left; simp
· right; left; simp
· left; exact ⟨a, b, rfl, rfl⟩
· right; right; simp
theorem nbrs_len_eq (G : Graph) (hG : G.WF) (v : Nat) (nb : List Nat) (hnb : nb.Nodup)
(hmem : ∀ x, x ∈ nb ↔ G.Adj v x) : (G.nbrs v).length = nb.length := by
have hperm : (G.nbrs v).Perm nb :=
(List.perm_ext_iff_of_nodup (hG.nbrs_nodup v) hnb).2 (fun x => (hmem x).symm)
exact hperm.length_eq
/-- The graph after one reduction at `v` (with neighbour list `nb`, as in `OpsRecord`):
nodes are the old nodes except `v`, and the adjacency is the torso adjacency of
`(F, B.erase v)` (joining the two neighbours of `v`). -/
theorem redStep_facts (G : Graph) (hG : G.WF) (v : Nat) (nb : List Nat)
(hnb : nb.Nodup) (hlen : nb.length ≤ 2)
(hmem : ∀ x, x ∈ nb ↔ G.Adj v x) :
(redStep G v).WF ∧
(∀ x, x ∈ (redStep G v).nodes ↔ x ∈ G.nodes ∧ x ≠ v) ∧
(∀ x y, (redStep G v).Adj x y ↔
x ≠ v ∧ y ≠ v ∧ (G.Adj x y ∨ (x ≠ y ∧ G.Adj x v ∧ G.Adj y v))) := by
have hL : (G.nbrs v).length ≤ 2 := by
rw [nbrs_len_eq G hG v nb hnb hmem]; exact hlen
have hRem := removeNodeSpec G v hG
have hsymm : ∀ x, G.Adj x v ↔ G.Adj v x :=
fun x => ⟨fun h => hG.symm x v h, fun h => hG.symm v x h⟩
rcases redStep_cases G v with ⟨a, b, hab, hred⟩ | ⟨hlen1, hred⟩ | ⟨hlen3, _⟩
· -- two neighbours `a ≠ b`
have hnodup := hG.nbrs_nodup v
rw [hab] at hnodup
have hab' : a ≠ b := by simpa using hnodup
have haN : a ∈ G.nbrs v := by rw [hab]; simp
have hbN : b ∈ G.nbrs v := by rw [hab]; simp
have hav : a ≠ v := fun h => hG.loopless v (h ▸ haN)
have hbv : b ≠ v := fun h => hG.loopless v (h ▸ hbN)
have haV : a ∈ G.nodes := hG.nbrs_sub v a haN
have hbV : b ∈ G.nodes := hG.nbrs_sub v b hbN
have hxa : ∀ x, G.Adj x v ↔ (x = a ∨ x = b) := by
intro x
rw [hsymm x]
show x ∈ G.nbrs v ↔ _
rw [hab]; simp
have hA := addEdgeSpec (G.removeNode v) a b hRem.1 hab'
rw [hred]
refine ⟨hA.1, fun x => ?_, fun x y => ?_⟩
· rw [hA.2.1 x, hRem.2.1 x]
constructor
· rintro (h | rfl | rfl)
· exact h
· exact ⟨haV, hav⟩
· exact ⟨hbV, hbv⟩
· intro h
exact Or.inl h
· rw [hA.2.2 x y, hRem.2.2 x y, hxa x, hxa y]
constructor
· rintro ((⟨h, h1, h2⟩) | ⟨rfl, rfl⟩ | ⟨rfl, rfl⟩)
· exact ⟨h1, h2, Or.inl h⟩
· exact ⟨hav, hbv, Or.inr ⟨hab', Or.inl rfl, Or.inr rfl⟩⟩
· exact ⟨hbv, hav, Or.inr ⟨fun e => hab' e.symm, Or.inr rfl, Or.inl rfl⟩⟩
· rintro ⟨h1, h2, h | ⟨hne, hx, hy⟩⟩
· exact Or.inl ⟨h, h1, h2⟩
· rcases hx with rfl | rfl <;> rcases hy with rfl | rfl
· exact absurd rfl hne
· exact Or.inr (Or.inl ⟨rfl, rfl⟩)
· exact Or.inr (Or.inr ⟨rfl, rfl⟩)
· exact absurd rfl hne
· -- at most one neighbour
rw [hred]
refine ⟨hRem.1, fun x => hRem.2.1 x, fun x y => ?_⟩
rw [hRem.2.2 x y]
constructor
· rintro ⟨h, h1, h2⟩
exact ⟨h1, h2, Or.inl h⟩
· rintro ⟨h1, h2, h | ⟨hne, hx, hy⟩⟩
· exact ⟨h, h1, h2⟩
· exact absurd (mem_of_len_le_one hlen1 ((hsymm x).mp hx) ((hsymm y).mp hy)) hne
· omega
/-! ## The invariant relating the torso of a state to the current graph -/
/-- The current graph `G` of the record is the torso of `(F, B)` over `S`: the node set of
`G` is `B` and the torso adjacency is the adjacency of `G`. -/
def Inv {n : ℕ} (S : SimpleGraph (Fin n)) (G : Graph) (F B : Finset (Fin n)) : Prop :=
(∀ x : Fin n, x ∈ B ↔ x.val ∈ G.nodes) ∧
∀ x y : Fin n, (T4.tgraph S F B).Adj x y ↔ G.Adj x.val y.val
/-- Torso degree at most `2` when the torso neighbours of `v` are listed in `L`. -/
theorem tdeg_le_two {n : ℕ} (S : SimpleGraph (Fin n)) (F B : Finset (Fin n)) (v : Fin n)
(L : List Nat) (hlen : L.length ≤ 2)
(hadj : ∀ x : Fin n, (T4.tgraph S F B).Adj v x ↔ x.val ∈ L) :
T4.tdeg S F B v ≤ 2 := by
classical
rw [T4.tdeg_eq_card]
have hle := Finset.card_le_card_of_injOn (fun u : Fin n => u.val)
(s := Finset.univ.filter fun u => (T4.tgraph S F B).Adj v u) (t := L.toFinset)
(by
intro u hu
rw [Finset.mem_coe, Finset.mem_filter] at hu
exact Finset.mem_coe.mpr (List.mem_toFinset.mpr ((hadj u).1 hu.2)))
(by
intro a _ b _ hab
exact Fin.ext hab)
have h2 := List.toFinset_card_le L
omega
/-- The initial state: the torso of `(V0, V0)` is the graph `F` on its nodes. -/
theorem init_inv {n : ℕ} (F : Graph) (hF : F.WF) (S : SimpleGraph (Fin n))
(hS : ∀ x y : Fin n, S.Adj x y ↔ F.Adj x.val y.val) :
Inv S F (Finset.univ.filter fun x : Fin n => x.val ∈ F.nodes)
(Finset.univ.filter fun x : Fin n => x.val ∈ F.nodes) := by
refine ⟨fun x => by simp, fun x y => ?_⟩
have hc : CubicPathwidth.components S (∅ : Finset (Fin n)) = ∅ := by
unfold CubicPathwidth.components
simp
rw [T4.tgraph_adj_iff, Finset.sdiff_self, hc, hS]
simp only [Finset.mem_filter, Finset.mem_univ, true_and, Finset.notMem_empty, false_and,
exists_false, or_false]
constructor
· rintro ⟨_, h1, h2, h⟩
exact h
· intro h
obtain ⟨h1, h2, _, h4⟩ := wfBasics F hF x.val y.val h
exact ⟨fun e => h4 (congrArg Fin.val e), h1, h2, h⟩
/-- Filtering by the deleted set after erasing a core vertex. -/
theorem filter_erase_del {n : ℕ} (F : Finset (Fin n)) (wF : Fin n) (w : Nat)
(hwF : wF.val = w) (D : List Nat) :
(F.erase wF).filter (fun x => x.val ∉ D) =
F.filter (fun x => x.val ∉ w :: D) := by
ext x
simp only [Finset.mem_filter, Finset.mem_erase, List.mem_cons, not_or, ne_eq, Fin.ext_iff,
hwF]
tauto
/-- Main induction: running the record from a state simulating `F` reaches the state of the
final graph, and the final torso is the final graph. -/
theorem aux {n : ℕ} (S : SimpleGraph (Fin n)) (ops : List Op) :
∀ (G R : Graph) (F B : Finset (Fin n)),
G.WF → (∀ v ∈ G.nodes, v < n) → OpsRecord G ops R →
T4.Good S F B → Inv S G F B →
T4.Reach S (F, B)
(F.filter (fun x => x.val ∉ deletedSet ops),
Finset.univ.filter (fun x => x.val ∈ R.nodes)) ∧
Inv S R (F.filter (fun x => x.val ∉ deletedSet ops))
(Finset.univ.filter (fun x => x.val ∈ R.nodes)) := by
induction ops with
| nil =>
intro G R F B hG hn hops hgood hinv
simp only [OpsRecord] at hops
obtain ⟨hnodes, hadj⟩ := hops
have hD : deletedSet ([] : List Op) = [] := by simp [deletedSet]
have hF : F.filter (fun x => x.val ∉ deletedSet ([] : List Op)) = F := by
rw [hD]; ext x; simp
have hB : B = Finset.univ.filter (fun x => x.val ∈ R.nodes) := by
ext x
rw [hinv.1 x, Finset.mem_filter]
simp [hnodes x.val]
rw [hF, ← hB]
refine ⟨T4.Reach.refl S _, ?_⟩
refine ⟨fun x => ?_, fun x y => ?_⟩
· exact (hinv.1 x).trans (hnodes x.val)
· exact (hinv.2 x y).trans (hadj x.val y.val)
| cons op rest ih =>
intro G R F B hG hn hops hgood hinv
cases op with
| red v nb =>
simp only [OpsRecord] at hops
obtain ⟨hvN, hnb, hlen, hmem, hrest⟩ := hops
have hvn : v < n := hn v hvN
obtain ⟨vF, hvF⟩ : ∃ vF : Fin n, vF.val = v := ⟨⟨v, hvn⟩, rfl⟩
have hvB : vF ∈ B := (hinv.1 vF).2 (by rw [hvF]; exact hvN)
have hdeg : T4.tdeg S F B vF ≤ 2 := by
apply tdeg_le_two S F B vF nb hlen
intro x
rw [hinv.2 vF x, hvF]
exact (hmem x.val).symm
have hgood' : T4.Good S F (B.erase vF) :=
hgood.reach (T4.Reach.single (T4.Step.reduce hvB hdeg))
obtain ⟨hWF, hNodes, hAdj⟩ := redStep_facts G hG v nb hnb hlen hmem
have hdyn := T4.torsoDynamics n S F B hgood
have hinv' : Inv S (redStep G v) F (B.erase vF) := by
refine ⟨fun x => ?_, fun x y => ?_⟩
· rw [Finset.mem_erase, hinv.1 x, hNodes]
simp only [ne_eq, Fin.ext_iff, hvF]
tauto
· rw [hdyn.2.1 vF hvB hdeg x y, hinv.2 x y, hinv.2 x vF, hinv.2 y vF, hAdj x.val y.val]
simp only [ne_eq, Fin.ext_iff, hvF]
have ih' := ih (redStep G v) R F (B.erase vF) hWF
(fun u hu => hn u ((hNodes u).1 hu).1) hrest hgood' hinv'
have hD : deletedSet (Op.red v nb :: rest) = deletedSet rest := by simp [deletedSet]
rw [hD]
exact ⟨(T4.Reach.single (T4.Step.reduce hvB hdeg)).trans ih'.1, ih'.2⟩
| del w =>
simp only [OpsRecord] at hops
obtain ⟨hwN, hrest⟩ := hops
have hwn : w < n := hn w hwN
obtain ⟨wF, hwF⟩ : ∃ wF : Fin n, wF.val = w := ⟨⟨w, hwn⟩, rfl⟩
have hwB : wF ∈ B := (hinv.1 wF).2 (by rw [hwF]; exact hwN)
have hgood' : T4.Good S (F.erase wF) (B.erase wF) :=
hgood.reach (T4.Reach.single (T4.Step.delete hwB))
have hRem := removeNodeSpec G w hG
have hdyn := T4.torsoDynamics n S F B hgood
have hinv' : Inv S (G.removeNode w) (F.erase wF) (B.erase wF) := by
refine ⟨fun x => ?_, fun x y => ?_⟩
· rw [Finset.mem_erase, hinv.1 x, hRem.2.1 x.val]
simp only [ne_eq, Fin.ext_iff, hwF]
tauto
· rw [hdyn.1 wF hwB x y, hinv.2 x y, hRem.2.2 x.val y.val]
simp only [ne_eq, Fin.ext_iff, hwF]
have ih' := ih (G.removeNode w) R (F.erase wF) (B.erase wF) hRem.1
(fun u hu => hn u ((hRem.2.1 u).1 hu).1) hrest hgood' hinv'
have hD : deletedSet (Op.del w :: rest) = w :: deletedSet rest := by simp [deletedSet]
rw [hD, ← filter_erase_del F wF w hwF (deletedSet rest)]
exact ⟨(T4.Reach.single (T4.Step.delete hwB)).trans ih'.1, ih'.2⟩
end CubicPathwidth.Alg.R4
namespace CubicPathwidth.Alg
/-- Simulation of the record by the torso (`TorsoSim`). -/
theorem torsoSim : TorsoSim := by
intro n F R ops hF hn hops S V0 F1 B1
have hS : ∀ x y : Fin n, S.Adj x y ↔ F.Adj x.val y.val := by
intro x y
simp only [S, Graph.toSimpleGraph, SimpleGraph.fromRel_adj]
constructor
· rintro ⟨_, h | h⟩
· exact h
· exact hF.symm y.val x.val h
· intro h
obtain ⟨_, _, _, h4⟩ := wfBasics F hF x.val y.val h
exact ⟨fun e => h4 (congrArg Fin.val e), Or.inl h⟩
have hGood : T4.Good S V0 V0 := by
have := T4.reach_delete_set S Finset.univ Finset.univ (Finset.univ \ V0)
(Finset.subset_univ _)
rw [Finset.sdiff_sdiff_eq_self (Finset.subset_univ V0)] at this
exact this
have hinv0 : R4.Inv S F V0 V0 := R4.init_inv F hF S hS
obtain ⟨hreach, hfin⟩ := R4.aux S ops F R V0 V0 hF hn hops hGood hinv0
exact ⟨hGood, hreach, hfin.2⟩
end CubicPathwidth.Alg
#print axioms CubicPathwidth.Alg.torsoSim
Back to top