CubicPathwidth.Alg.Proofs.B2OfSimpleGraph
Source file CubicPathwidth/Alg/Proofs/B2OfSimpleGraph.lean of the Lean project (how it is built).
import CubicPathwidth.Alg.Spec
/-!
# B2: `ofSimpleGraph` of a simple graph on `Fin n`
Proves `OfSimpleGraphSpec` (see `Spec.lean`, section 2): the graph `Graph.ofSimpleGraph S`
is well formed, has vertex set `{0, …, n-1}`, gives back `S` under `toSimpleGraph n`, and
has maximum degree at most `3` when `S` is subcubic.
Strategy. `Graph.ofSimpleGraph S` is `Graph.ofAdjLists (List.range n) (…)`, that is the
fold `insert` over the association list `adjPairs S` whose keys are `List.range n` (no
repeats) and whose values are the neighbour lists `nbList S u` (increasing, duplicate free).
Folding `insert` over a list with distinct keys gives `getD k = l` for the value `l` of
the pair with key `k`, and `contains k` iff `k` is a key.
-/
namespace CubicPathwidth.Alg.B2
open CubicPathwidth.Alg
variable {n : ℕ}
/-- The increasing neighbour list of `u` in `S`, as in `Graph.ofSimpleGraph`. -/
def nbList (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] (u : Fin n) : List Nat :=
((List.finRange n).filter fun v => decide (S.Adj u v)).map Fin.val
/-- The association list folded by `Graph.ofAdjLists (List.range n) …`. -/
def adjPairs (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] : List (Nat × List Nat) :=
(List.range n).zip ((List.finRange n).map (nbList S))
theorem ofSimpleGraph_eq (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] :
Graph.ofSimpleGraph S =
⟨List.range n, (adjPairs S).foldl (fun (a : Std.HashMap Nat (List Nat)) (p : Nat × List Nat) => a.insert p.1 p.2) ∅⟩ :=
rfl
/-! ### Folding `insert` over an association list -/
theorem fold_getD_none (ps : List (Nat × List Nat)) :
∀ (m : Std.HashMap Nat (List Nat)) (k : Nat), k ∉ ps.map Prod.fst →
(ps.foldl (fun (a : Std.HashMap Nat (List Nat)) (p : Nat × List Nat) => a.insert p.1 p.2) m).getD k [] = m.getD k [] := by
induction ps with
| nil => intro m k _; rfl
| cons p ps ih =>
intro m k hk
rcases p with ⟨a, b⟩
simp only [List.map_cons, List.mem_cons, not_or] at hk
rw [List.foldl_cons, ih _ k hk.2, Std.HashMap.getD_insert]
have hne : (a == k) = false := by
simpa [beq_iff_eq] using (Ne.symm hk.1)
simp [hne]
theorem fold_getD (ps : List (Nat × List Nat)) :
∀ (m : Std.HashMap Nat (List Nat)) (k : Nat) (l : List Nat),
(ps.map Prod.fst).Nodup → (k, l) ∈ ps →
(ps.foldl (fun (a : Std.HashMap Nat (List Nat)) (p : Nat × List Nat) => a.insert p.1 p.2) m).getD k [] = l := by
induction ps with
| nil => intro m k l _ h; simp at h
| cons p ps ih =>
intro m k l hnd hmem
rcases p with ⟨a, b⟩
simp only [List.map_cons, List.nodup_cons] at hnd
rw [List.foldl_cons]
rcases List.mem_cons.1 hmem with h | h
· simp only [Prod.mk.injEq] at h
obtain ⟨rfl, rfl⟩ := h
rw [fold_getD_none ps _ _ hnd.1]
simp
· exact ih _ k l hnd.2 h
theorem fold_contains (ps : List (Nat × List Nat)) :
∀ (m : Std.HashMap Nat (List Nat)) (k : Nat),
(ps.foldl (fun (a : Std.HashMap Nat (List Nat)) (p : Nat × List Nat) => a.insert p.1 p.2) m).contains k = true ↔
k ∈ ps.map Prod.fst ∨ m.contains k = true := by
induction ps with
| nil => intro m k; simp
| cons p ps ih =>
intro m k
rcases p with ⟨a, b⟩
rw [List.foldl_cons, ih, Std.HashMap.contains_insert]
simp only [List.map_cons, List.mem_cons, Bool.or_eq_true, beq_iff_eq]
tauto
/-! ### The association list of `ofSimpleGraph` -/
theorem adjPairs_fst (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] :
(adjPairs S).map Prod.fst = List.range n := by
unfold adjPairs
rw [List.map_fst_zip]
simp
theorem mem_adjPairs (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] (u : Fin n) :
(u.val, nbList S u) ∈ adjPairs S := by
unfold adjPairs
rw [List.mem_iff_getElem]
refine ⟨u.val, by simp [u.isLt], ?_⟩
simp
/-! ### Neighbour lists -/
theorem mem_nbList {w : Nat} (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] (u : Fin n) :
w ∈ nbList S u ↔ ∃ x : Fin n, x.val = w ∧ S.Adj u x := by
unfold nbList
simp only [List.mem_map, List.mem_filter, List.mem_finRange, decide_eq_true_eq, true_and]
constructor
· rintro ⟨x, hx, rfl⟩
exact ⟨x, rfl, hx⟩
· rintro ⟨x, rfl, hx⟩
exact ⟨x, hx, rfl⟩
theorem nbList_lt {w : Nat} (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] (u : Fin n)
(h : w ∈ nbList S u) : w < n := by
obtain ⟨x, rfl, -⟩ := (mem_nbList S u).1 h
exact x.isLt
theorem nbrs_eq (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] (u : Fin n) :
(Graph.ofSimpleGraph S).nbrs u.val = nbList S u := by
rw [ofSimpleGraph_eq]
unfold Graph.nbrs
exact fold_getD _ _ _ _ (by rw [adjPairs_fst]; exact List.nodup_range) (mem_adjPairs S u)
theorem nbrs_ge (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] (k : Nat) (hk : n ≤ k) :
(Graph.ofSimpleGraph S).nbrs k = [] := by
rw [ofSimpleGraph_eq]
unfold Graph.nbrs
show ((adjPairs S).foldl (fun (a : Std.HashMap Nat (List Nat)) (p : Nat × List Nat) => a.insert p.1 p.2) ∅).getD k [] = []
rw [fold_getD_none _ _ _ (by rw [adjPairs_fst, List.mem_range]; omega), Std.HashMap.getD_empty]
theorem mem_nbrs_iff (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] (u v : Fin n) :
v.val ∈ (Graph.ofSimpleGraph S).nbrs u.val ↔ S.Adj u v := by
rw [nbrs_eq, mem_nbList]
constructor
· rintro ⟨x, hx, hadj⟩
have : x = v := Fin.ext hx
subst this
exact hadj
· intro h
exact ⟨v, rfl, h⟩
theorem subU (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] (u v : Nat)
(hv : v ∈ (Graph.ofSimpleGraph S).nbrs u) : u < n ∧ v < n := by
by_cases hu : u < n
· refine ⟨hu, ?_⟩
have e : (Graph.ofSimpleGraph S).nbrs u = nbList S ⟨u, hu⟩ := nbrs_eq S ⟨u, hu⟩
rw [e] at hv
exact nbList_lt S _ hv
· rw [nbrs_ge S u (by omega)] at hv
simp at hv
theorem nodes_eq (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] :
(Graph.ofSimpleGraph S).nodes = List.range n :=
rfl
theorem mem_iff (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] (k : Nat) :
(Graph.ofSimpleGraph S).mem k = true ↔ k < n := by
rw [ofSimpleGraph_eq]
unfold Graph.mem
show ((adjPairs S).foldl (fun (a : Std.HashMap Nat (List Nat)) (p : Nat × List Nat) => a.insert p.1 p.2) ∅).contains k = true ↔ k < n
rw [fold_contains, adjPairs_fst]
simp
/-! ### Well-formedness -/
theorem wf (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] : (Graph.ofSimpleGraph S).WF := by
have nd : ∀ u, ((Graph.ofSimpleGraph S).nbrs u).Nodup := by
intro u
by_cases hu : u < n
· have e : (Graph.ofSimpleGraph S).nbrs u = nbList S ⟨u, hu⟩ := nbrs_eq S ⟨u, hu⟩
rw [e]
unfold nbList
exact ((List.nodup_finRange n).filter _).map Fin.val_injective
· rw [nbrs_ge S u (by omega)]
exact List.nodup_nil
refine ⟨List.nodup_range, fun v => ?_, nd, fun u v hv => ?_, fun u v hv => ?_, fun v hv => ?_⟩
· rw [mem_iff S v]
show v < n ↔ v ∈ List.range n
simp
· exact List.mem_range.2 (subU S u v hv).2
· obtain ⟨hu, hv'⟩ := subU S u v hv
have h := (mem_nbrs_iff S ⟨u, hu⟩ ⟨v, hv'⟩).1 hv
exact (mem_nbrs_iff S ⟨v, hv'⟩ ⟨u, hu⟩).2 (S.adj_symm h)
· obtain ⟨hv', -⟩ := subU S v v hv
exact S.irrefl ((mem_nbrs_iff S ⟨v, hv'⟩ ⟨v, hv'⟩).1 hv)
/-! ### Bridge to `SimpleGraph` and degrees -/
theorem toSimpleGraph_eq (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] :
(Graph.ofSimpleGraph S).toSimpleGraph n = S := by
ext u v
unfold Graph.toSimpleGraph
rw [SimpleGraph.fromRel_adj]
constructor
· rintro ⟨-, h | h⟩
· exact (mem_nbrs_iff S u v).1 h
· exact S.adj_symm ((mem_nbrs_iff S v u).1 h)
· intro h
exact ⟨S.ne_of_adj h, Or.inl ((mem_nbrs_iff S u v).2 h)⟩
theorem card_filter_eq_length (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] (u : Fin n) :
(Finset.univ.filter (S.Adj u)).card = (nbList S u).length := by
unfold nbList
rw [List.length_map, Finset.card_def, Finset.filter_val, Fin.univ_def]
simp [Multiset.filter_coe, Multiset.coe_card]
theorem degree_eq_length (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] (u : Fin n) :
S.degree u = (nbList S u).length := by
rw [← SimpleGraph.card_neighborFinset_eq_degree, ← card_filter_eq_length]
congr 1
ext x
simp [SimpleGraph.mem_neighborFinset]
theorem maxDegLE (S : SimpleGraph (Fin n)) [DecidableRel S.Adj] (hS : CubicPathwidth.IsSubcubic S) :
(Graph.ofSimpleGraph S).MaxDegLE 3 := by
unfold CubicPathwidth.IsSubcubic at hS
intro v hv
have hvn : v < n := by
have : v ∈ List.range n := hv
exact List.mem_range.1 this
have e : (Graph.ofSimpleGraph S).nbrs v = nbList S ⟨v, hvn⟩ := nbrs_eq S ⟨v, hvn⟩
have h3 := hS ⟨v, hvn⟩
unfold Graph.degree
rw [e]
rw [← degree_eq_length]
convert h3
end CubicPathwidth.Alg.B2
namespace CubicPathwidth.Alg
open B2
/-- `ofSimpleGraph` is well formed, has vertex set `{0, …, n-1}`, gives back `S`, and keeps
the degree bound of `IsSubcubic`. -/
theorem ofSimpleGraphSpec : OfSimpleGraphSpec := by
intro n S _inst
refine ⟨B2.wf S, fun v => ?_, B2.toSimpleGraph_eq S, fun hS => B2.maxDegLE S hS⟩
rw [B2.nodes_eq]
exact List.mem_range
end CubicPathwidth.Alg
#print axioms CubicPathwidth.Alg.ofSimpleGraphSpec
Back to top