CubicPathwidth.Alg.Proofs.G4Induced
Source file CubicPathwidth/Alg/Proofs/G4Induced.lean of the Lean project (how it is built).
import CubicPathwidth.Alg.Spec
/-!
# G4: `InducedSpec` (Python `subgraph(S).copy()` under model M)
`Graph.induced` starts from the edgeless graph on `ns = G.nodes.filter keep` and folds
`addEdge u v` over the pairs `u ∈ ns`, `v ∈ G.nbrs u` with `keep v`. The helpers below
state the fold for an arbitrary initial graph (induction on the lists), using the
hypothesis `AddEdgeSpec` for one `addEdge` step, and then specialise.
-/
namespace CubicPathwidth.Alg
open Graph
namespace G4
/-- The edgeless graph on the list `ns` (the start graph of `Graph.induced`). -/
def startGraph (ns : List Nat) : Graph :=
⟨ns, ns.foldl (fun (a : Std.HashMap Nat (List Nat)) (v : Nat) => a.insert v []) ∅⟩
theorem startGraph_nodes (ns : List Nat) : (startGraph ns).nodes = ns := rfl
/-- Membership in the keys of a fold of `insert _ []`. -/
theorem foldInsert_contains (l : List Nat) :
∀ (m : Std.HashMap Nat (List Nat)) (x : Nat),
(l.foldl (fun (a : Std.HashMap Nat (List Nat)) (v : Nat) => a.insert v []) m).contains x = true ↔ x ∈ l ∨ m.contains x = true := by
induction l with
| nil => intro m x; simp
| cons a l ih =>
intro m x
rw [List.foldl_cons, ih, Std.HashMap.contains_insert]
simp only [beq_iff_eq, Bool.or_eq_true, List.mem_cons]
constructor
· rintro (h | h | h)
· exact Or.inl (Or.inr h)
· exact Or.inl (Or.inl h.symm)
· exact Or.inr h
· rintro ((h | h) | h)
· exact Or.inr (Or.inl h.symm)
· exact Or.inl h
· exact Or.inr (Or.inr h)
/-- Values of a fold of `insert _ []` over a map whose values are all `[]`. -/
theorem foldInsert_getD (l : List Nat) :
∀ (m : Std.HashMap Nat (List Nat)), (∀ x, m.getD x [] = []) →
∀ x, (l.foldl (fun (a : Std.HashMap Nat (List Nat)) (v : Nat) => a.insert v []) m).getD x [] = [] := by
induction l with
| nil => intro m hm x; exact hm x
| cons a l ih =>
intro m hm x
rw [List.foldl_cons]
apply ih
intro y
rw [Std.HashMap.getD_insert]
split
· rfl
· exact hm y
theorem startGraph_nbrs (ns : List Nat) (u : Nat) : (startGraph ns).nbrs u = [] :=
foldInsert_getD ns ∅ (fun _ => Std.HashMap.getD_empty) u
theorem startGraph_not_adj (ns : List Nat) (x y : Nat) : ¬ (startGraph ns).Adj x y := by
intro h
rw [Graph.Adj, startGraph_nbrs] at h
exact List.not_mem_nil h
theorem startGraph_wf (ns : List Nat) (hnd : ns.Nodup) : (startGraph ns).WF := by
refine ⟨hnd, ?_, ?_, ?_, ?_, ?_⟩
· intro v
unfold Graph.mem
show (ns.foldl (fun (a : Std.HashMap Nat (List Nat)) (v : Nat) => a.insert v []) ∅).contains v = true ↔ v ∈ ns
rw [foldInsert_contains]
simp
· intro v
rw [startGraph_nbrs]
exact List.nodup_nil
· intro u v h
rw [startGraph_nbrs] at h
exact absurd h (List.not_mem_nil)
· intro u v h
rw [startGraph_nbrs] at h
exact absurd h (List.not_mem_nil)
· intro v h
rw [startGraph_nbrs] at h
exact absurd h (List.not_mem_nil)
/-- The inner fold: `addEdge u v` for the neighbours `v ∈ l` with `keep v`. -/
theorem inner_fold (hAdd : AddEdgeSpec) (keep : Nat → Bool) (S : Nat → Prop) (u : Nat) :
∀ (l : List Nat) (H : Graph), H.WF → (∀ x, x ∈ H.nodes ↔ S x) → S u →
(∀ v ∈ l, keep v = true → S v) → (∀ v ∈ l, v ≠ u) →
(l.foldl (fun H v => if keep v then H.addEdge u v else H) H).WF ∧
(∀ x, x ∈ (l.foldl (fun H v => if keep v then H.addEdge u v else H) H).nodes ↔
x ∈ H.nodes) ∧
(∀ x y, (l.foldl (fun H v => if keep v then H.addEdge u v else H) H).Adj x y ↔
(H.Adj x y ∨ ∃ v ∈ l, keep v = true ∧ ((x = u ∧ y = v) ∨ (x = v ∧ y = u)))) := by
intro l
induction l with
| nil =>
intro H hH _ _ _ _
refine ⟨hH, fun x => Iff.rfl, fun x y => ?_⟩
simp
| cons v l ih =>
intro H hH hS hSu hSl hne
have hv : v ≠ u := hne v (by simp)
have hSl' : ∀ w ∈ l, keep w = true → S w := fun w hw => hSl w (by simp [hw])
have hne' : ∀ w ∈ l, w ≠ u := fun w hw => hne w (by simp [hw])
rw [List.foldl_cons]
by_cases hk : keep v = true
· simp only [hk, ↓reduceIte]
have hvS : S v := hSl v (by simp) hk
have huN : u ∈ H.nodes := (hS u).mpr hSu
have hvN : v ∈ H.nodes := (hS v).mpr hvS
obtain ⟨hW1, hN1, hA1⟩ := hAdd H u v hH (Ne.symm hv)
have hN1'' : ∀ x, x ∈ (H.addEdge u v).nodes ↔ x ∈ H.nodes := by
intro x
rw [hN1 x]
constructor
· rintro (h | rfl | rfl)
· exact h
· exact huN
· exact hvN
· intro h
exact Or.inl h
obtain ⟨hWR, hNR, hAR⟩ :=
ih (H.addEdge u v) hW1 (fun x => (hN1'' x).trans (hS x)) hSu hSl' hne'
refine ⟨hWR, fun x => (hNR x).trans (hN1'' x), fun x y => ?_⟩
rw [hAR x y, hA1 x y]
constructor
· rintro ((h | h | h) | ⟨w, hw, hk2, hxy⟩)
· exact Or.inl h
· exact Or.inr ⟨v, by simp, hk, Or.inl h⟩
· exact Or.inr ⟨v, by simp, hk, Or.inr h⟩
· exact Or.inr ⟨w, by simp [hw], hk2, hxy⟩
· rintro (h | ⟨w, hw, hk2, hxy⟩)
· exact Or.inl (Or.inl h)
· rcases List.mem_cons.1 hw with hwv | hw'
· subst hwv
exact Or.inl (Or.inr hxy)
· exact Or.inr ⟨w, hw', hk2, hxy⟩
· have hk' : keep v = false := by simpa using hk
simp only [hk', Bool.false_eq_true, ↓reduceIte]
obtain ⟨hWR, hNR, hAR⟩ := ih H hH hS hSu hSl' hne'
refine ⟨hWR, hNR, fun x y => ?_⟩
rw [hAR x y]
constructor
· rintro (h | ⟨w, hw, hk2, hxy⟩)
· exact Or.inl h
· exact Or.inr ⟨w, by simp [hw], hk2, hxy⟩
· rintro (h | ⟨w, hw, hk2, hxy⟩)
· exact Or.inl h
· rcases List.mem_cons.1 hw with hwv | hw'
· subst hwv
exact absurd hk2 hk
· exact Or.inr ⟨w, hw', hk2, hxy⟩
/-- The outer fold over the list `us` of vertices. -/
theorem outer_fold (hAdd : AddEdgeSpec) (G : Graph) (keep : Nat → Bool) (hG : G.WF)
(S : Nat → Prop)
(hcl : ∀ u, S u → ∀ v ∈ G.nbrs u, keep v = true → S v) :
∀ (us : List Nat) (H : Graph), H.WF → (∀ x, x ∈ H.nodes ↔ S x) → (∀ u ∈ us, S u) →
(us.foldl (fun H u => (G.nbrs u).foldl (fun H v => if keep v then H.addEdge u v else H) H)
H).WF ∧
(∀ x, x ∈ (us.foldl (fun H u => (G.nbrs u).foldl
(fun H v => if keep v then H.addEdge u v else H) H) H).nodes ↔ x ∈ H.nodes) ∧
(∀ x y, (us.foldl (fun H u => (G.nbrs u).foldl
(fun H v => if keep v then H.addEdge u v else H) H) H).Adj x y ↔
(H.Adj x y ∨ ∃ u ∈ us, ∃ v ∈ G.nbrs u,
keep v = true ∧ ((x = u ∧ y = v) ∨ (x = v ∧ y = u)))) := by
intro us
induction us with
| nil =>
intro H hH _ _
refine ⟨hH, fun x => Iff.rfl, fun x y => ?_⟩
simp
| cons u us ih =>
intro H hH hS hus
have hSu : S u := hus u (by simp)
have hus' : ∀ u' ∈ us, S u' := fun u' hu' => hus u' (by simp [hu'])
simp only [List.foldl_cons]
obtain ⟨hW1, hN1, hA1⟩ :=
inner_fold hAdd keep S u (G.nbrs u) H hH hS hSu
(fun v hv hk => hcl u hSu v hv hk)
(fun v hv heq => by
subst heq
exact hG.loopless _ hv)
obtain ⟨hW2, hN2, hA2⟩ :=
ih _ hW1 (fun x => (hN1 x).trans (hS x)) hus'
refine ⟨hW2, fun x => (hN2 x).trans (hN1 x), fun x y => ?_⟩
rw [hA2 x y, hA1 x y]
simp only [List.mem_cons, exists_eq_or_imp, or_assoc]
end G4
open G4
/-- `induced` (Python `subgraph(S).copy()` under model M) is well formed, has the nodes
`G.nodes` with `keep`, and the edges of `G` between kept vertices. -/
theorem inducedSpec_of (hWF : WFBasics) (hAdd : AddEdgeSpec) : InducedSpec := by
intro G keep hG
have hnd : (G.nodes.filter keep).Nodup := hG.nodup.filter _
have hS0 := startGraph_wf (G.nodes.filter keep) hnd
have hcl : ∀ u, (u ∈ G.nodes ∧ keep u = true) → ∀ v ∈ G.nbrs u, keep v = true →
(v ∈ G.nodes ∧ keep v = true) :=
fun u _ v hv hk => ⟨hG.nbrs_sub u v hv, hk⟩
have hInd : G.induced keep = (G.nodes.filter keep).foldl
(fun H u => (G.nbrs u).foldl (fun H v => if keep v then H.addEdge u v else H) H)
(startGraph (G.nodes.filter keep)) := rfl
have hNodes : ∀ x, x ∈ (startGraph (G.nodes.filter keep)).nodes ↔
(x ∈ G.nodes ∧ keep x = true) := by
intro x
rw [startGraph_nodes]
exact List.mem_filter
obtain ⟨h1, h2, h3⟩ := outer_fold hAdd G keep hG (fun x => x ∈ G.nodes ∧ keep x = true) hcl
(G.nodes.filter keep) (startGraph (G.nodes.filter keep)) hS0 hNodes
(fun u hu => List.mem_filter.1 hu)
rw [hInd]
refine ⟨h1, fun x => (h2 x).trans (hNodes x), fun x y => ?_⟩
rw [h3 x y]
constructor
· rintro (h | ⟨u, hu, v, hv, hk, hxy⟩)
· exact absurd h (startGraph_not_adj _ x y)
· obtain ⟨hu1, hku⟩ := List.mem_filter.1 hu
rcases hxy with ⟨rfl, rfl⟩ | ⟨rfl, rfl⟩
· exact ⟨hv, hku, hk⟩
· exact ⟨hG.symm _ _ hv, hk, hku⟩
· rintro ⟨hadj, hkx, hky⟩
have hx : x ∈ G.nodes := hG.nbrs_sub y x (hG.symm x y hadj)
exact Or.inr ⟨x, List.mem_filter.2 ⟨hx, hkx⟩, y, hadj, hky, Or.inl ⟨rfl, rfl⟩⟩
end CubicPathwidth.Alg
#print axioms CubicPathwidth.Alg.inducedSpec_of
Back to top