MaxLeafFormal.DSTGraph
Source file MaxLeafFormal/DSTGraph.lean of the Lean project (how it is built).
Statements of the paper formalised here: Lemma D.11.14, Theorem 12.8.
import MaxLeafFormal.DSTCert
import MaxLeafFormal.MLS
/-!
# Directed Steiner Tree: `W_S ≥ W_A` (`lem:fa-dst-point`, `eq:fa-dst-W`)
The setting is that of `thm:fa-dst`: a root `r`, terminals `K`, non-terminals `U`.
-/
namespace MaxLeafFormal.DSTGraph
open Finset
open Antinorm8 (RTree)
variable {V : Type*} [Fintype V] [DecidableEq V]
/-! ### Definitions with explicit graph data -/
/-- `v` is reachable from `u` in the induced subdigraph `G[T]` (`u ∈ T`; length 0 allowed). -/
def ReachIn (G : Digraph V) (T : Finset V) (u v : V) : Prop :=
u ∈ T ∧ Relation.ReflTransGen (fun a b => a ∈ T ∧ b ∈ T ∧ G.Adj a b) u v
/-- `\bar K_X = {r} ∪ K ∪ X` (the definition of `g` before `thm:fa-dst`). -/
def Kbar (r : V) (K X : Finset V) : Finset V := insert r (K ∪ X)
open Classical in
/-- `\bar K^r_X`: the vertices of `\bar K_X` reachable from `r` in `G[\bar K_X]`. -/
noncomputable def KbarR (G : Digraph V) (r : V) (K X : Finset V) : Finset V :=
(Kbar r K X).filter (fun v => ReachIn G (Kbar r K X) r v)
/-- `\bar K_X \ \bar K^r_X`. -/
noncomputable def Dset (G : Digraph V) (r : V) (K X : Finset V) : Finset V :=
Kbar r K X \ KbarR G r K X
open Classical in
/-- The strong component of `v` in `G[D]`. -/
noncomputable def scc (G : Digraph V) (D : Finset V) (v : V) : Finset V :=
D.filter (fun w => ReachIn G D v w ∧ ReachIn G D w v)
open Classical in
/-- Source components of `G[D]`: strong components that no arc of `G[D]` enters from outside. -/
noncomputable def sourceComps (G : Digraph V) (D : Finset V) : Finset (Finset V) :=
(D.image (scc G D)).filter (fun C => ∀ u ∈ D, ∀ v ∈ C, G.Adj u v → u ∈ C)
/-- The running-time exponent `g(X)` of a sample (defined before `thm:fa-dst`). -/
noncomputable def gDST (G : Digraph V) (r : V) (K X : Finset V) : ℕ :=
(sourceComps G (Dset G r K X)).card
/-- The non-terminals `U = V \ ({r} ∪ K)`. -/
def nonterm (r : V) (K : Finset V) : Finset V := univ \ insert r K
/-- `S` is a Steiner set: every terminal is reachable from `r` in `G[{r} ∪ K ∪ S]`. -/
def Steiner (G : Digraph V) (r : V) (K S : Finset V) : Prop :=
∀ v ∈ K, ReachIn G (Kbar r K S) r v
/-- `S` is rooted: every vertex of `K ∪ S` is reachable from `r` in `G[{r} ∪ K ∪ S]`. -/
def Rooted (G : Digraph V) (r : V) (K S : Finset V) : Prop :=
∀ v ∈ K ∪ S, ReachIn G (Kbar r K S) r v
open Classical in
/-- The vertices of `S` reachable from `r` in `G[{r} ∪ K ∪ S]`. -/
noncomputable def reachPart (G : Digraph V) (r : V) (K S : Finset V) : Finset V :=
S.filter (fun v => ReachIn G (Kbar r K S) r v)
/-- `W_S(y) = ∑_{X ⊆ S} y^{|X|} 2^{-g(X)}` (`def:fw-moments`, `eq:fa-dst-W`). -/
noncomputable def WS (G : Digraph V) (r : V) (K S : Finset V) (y : ℝ) : ℝ :=
∑ X ∈ S.powerset, y ^ X.card * (1 / 2 : ℝ) ^ gDST G r K X
/-- An out-arborescence of `G[N]` rooted at `r`: arcs `par u → u` for `u ∈ N \ {r}`. -/
structure OutArb (G : Digraph V) (r : V) (N : Finset V) where
par : V → V
height : V → ℕ
par_mem : ∀ u ∈ N, u ≠ r → par u ∈ N
par_adj : ∀ u ∈ N, u ≠ r → G.Adj (par u) u
height_lt : ∀ u ∈ N, u ≠ r → height (par u) < height u
/-! ### Definitions on an arborescence; theorems -/
variable {G : Digraph V} {r : V} {K S : Finset V}
open Classical in
/-- `Ψ_A(X) = |{u ∈ K ∪ X : par(u) ∉ \bar K_X}|` (`lem:fa-dst-point`). -/
noncomputable def PsiG (A : OutArb G r (Kbar r K S)) (X : Finset V) : ℕ :=
((K ∪ X).filter (fun u => A.par u ∉ Kbar r K X)).card
/-- `W_A(y) = ∑_{X ⊆ S} y^{|X|} 2^{-Ψ_A(X)}` (`eq:fa-dst-W`). -/
noncomputable def WAg (A : OutArb G r (Kbar r K S)) (y : ℝ) : ℝ :=
∑ X ∈ S.powerset, y ^ X.card * (1 / 2 : ℝ) ^ PsiG A X
/-- No vertex of `S` is a leaf of `A`. -/
def NoSteinerLeafG (A : OutArb G r (Kbar r K S)) : Prop :=
∀ v ∈ S, ∃ u ∈ K ∪ S, A.par u = v
/-! ### Helper lemmas: reachability -/
theorem ReachIn.of_mem {T : Finset V} {u : V} (hu : u ∈ T) : ReachIn G T u u :=
⟨hu, Relation.ReflTransGen.refl⟩
theorem ReachIn.mem_right {T : Finset V} {u v : V} (h : ReachIn G T u v) : v ∈ T := by
obtain ⟨hu, h⟩ := h
induction h with
| refl => exact hu
| tail _ hbc _ => exact hbc.2.1
theorem ReachIn.tail_adj {T : Finset V} {u a b : V} (h : ReachIn G T u a) (hb : b ∈ T)
(hab : G.Adj a b) : ReachIn G T u b :=
⟨h.1, h.2.tail ⟨h.mem_right, hb, hab⟩⟩
theorem ReachIn.trans {T : Finset V} {u v w : V} (h₁ : ReachIn G T u v)
(h₂ : ReachIn G T v w) : ReachIn G T u w :=
⟨h₁.1, h₁.2.trans h₂.2⟩
/-- A set containing `u` and closed under the arcs inside `T` contains every vertex that `u`
reaches inside `T`. -/
theorem ReachIn.mem_of_closed {T Z : Finset V} {u v : V} (hu : u ∈ Z)
(hZ : ∀ a ∈ Z, ∀ b ∈ T, G.Adj a b → b ∈ Z) (h : ReachIn G T u v) : v ∈ Z := by
obtain ⟨-, h⟩ := h
induction h with
| refl => exact hu
| tail _ hbc ih => exact hZ _ ih _ hbc.2.1 hbc.2.2
/-- The backward version of `ReachIn.mem_of_closed`. -/
theorem ReachIn.mem_of_back_closed {T Z : Finset V} {u v : V} (hv : v ∈ Z)
(hZ : ∀ a ∈ T, ∀ b ∈ Z, G.Adj a b → a ∈ Z) (h : ReachIn G T u v) : u ∈ Z := by
obtain ⟨-, h⟩ := h
induction h using Relation.ReflTransGen.head_induction_on with
| refl => exact hv
| head hac _ ih => exact hZ _ hac.1 _ ih hac.2.2
theorem mem_Kbar {X : Finset V} {v : V} : v ∈ Kbar r K X ↔ v = r ∨ v ∈ K ∨ v ∈ X := by
simp only [Kbar, Finset.mem_insert, Finset.mem_union]
theorem r_mem_Kbar {X : Finset V} : r ∈ Kbar r K X := Finset.mem_insert_self _ _
theorem mem_nonterm {v : V} : v ∈ nonterm r K ↔ v ≠ r ∧ v ∉ K := by
simp [nonterm]
theorem mem_KbarR {X : Finset V} {v : V} :
v ∈ KbarR G r K X ↔ v ∈ Kbar r K X ∧ ReachIn G (Kbar r K X) r v := by
simp only [KbarR, Finset.mem_filter]
theorem mem_Dset {X : Finset V} {v : V} :
v ∈ Dset G r K X ↔ v ∈ Kbar r K X ∧ ¬ ReachIn G (Kbar r K X) r v := by
simp only [Dset, Finset.mem_sdiff, mem_KbarR]
tauto
theorem mem_scc {D : Finset V} {v w : V} :
w ∈ scc G D v ↔ w ∈ D ∧ ReachIn G D v w ∧ ReachIn G D w v := by
simp only [scc, Finset.mem_filter]
theorem scc_self {D : Finset V} {v : V} (hv : v ∈ D) : v ∈ scc G D v :=
mem_scc.2 ⟨hv, ReachIn.of_mem hv, ReachIn.of_mem hv⟩
theorem scc_eq_of_mem {D : Finset V} {v w : V} (h : w ∈ scc G D v) :
scc G D w = scc G D v := by
rw [mem_scc] at h
ext x
rw [mem_scc, mem_scc]
constructor
· rintro ⟨hx, h1, h2⟩
exact ⟨hx, h.2.1.trans h1, h2.trans h.2.2⟩
· rintro ⟨hx, h1, h2⟩
exact ⟨hx, h.2.2.trans h1, h2.trans h.2.1⟩
theorem mem_sourceComps {D C : Finset V} :
C ∈ sourceComps G D ↔
(∃ v ∈ D, scc G D v = C) ∧ ∀ u ∈ D, ∀ v ∈ C, G.Adj u v → u ∈ C := by
simp only [sourceComps, Finset.mem_filter, Finset.mem_image]
/-- A source component is closed under backward reachability (the vertex form of the
source condition). -/
theorem mem_of_mem_sourceComps {D C : Finset V} {u w : V} (hC : C ∈ sourceComps G D)
(hw : w ∈ C) (h : ReachIn G D u w) : u ∈ C :=
ReachIn.mem_of_back_closed hw (mem_sourceComps.1 hC).2 h
/-- Every vertex of `D_X` has a "top": a vertex of `D_X` that reaches it inside `D_X` and whose
parent lies outside `\bar K_X` (proof of `lem:fa-dst-point`). -/
theorem exists_top (A : OutArb G r (Kbar r K S)) {X : Finset V} (hX : X ⊆ S) :
∀ (n : ℕ) (v : V), v ∈ Dset G r K X → A.height v < n →
∃ u ∈ Dset G r K X, ReachIn G (Dset G r K X) u v ∧ A.par u ∉ Kbar r K X := by
have hKS : Kbar r K X ⊆ Kbar r K S := by
intro w hw
rw [mem_Kbar] at hw ⊢
rcases hw with h | h | h
· exact Or.inl h
· exact Or.inr (Or.inl h)
· exact Or.inr (Or.inr (hX h))
intro n
induction n with
| zero => intro v _ h; exact absurd h (Nat.not_lt_zero _)
| succ n ih =>
intro v hv hlt
have hvK : v ∈ Kbar r K X := (mem_Dset.1 hv).1
have hvr : v ≠ r := by
rintro rfl
exact (mem_Dset.1 hv).2 (ReachIn.of_mem r_mem_Kbar)
by_cases hp : A.par v ∈ Kbar r K X
· have hadj := A.par_adj v (hKS hvK) hvr
have hpD : A.par v ∈ Dset G r K X := by
rw [mem_Dset]
exact ⟨hp, fun h => (mem_Dset.1 hv).2 (h.tail_adj hvK hadj)⟩
have h1 := A.height_lt v (hKS hvK) hvr
obtain ⟨u, hu, hreach, hpar⟩ := ih (A.par v) hpD (by omega)
exact ⟨u, hu, hreach.tail_adj hv hadj, hpar⟩
· exact ⟨v, hv, ReachIn.of_mem hv, hp⟩
/-! ### Helper lemmas for the examples -/
theorem gDST_eq_zero_of {X : Finset V} (h : ∀ v ∈ Kbar r K X, ReachIn G (Kbar r K X) r v) :
gDST G r K X = 0 := by
have hD : Dset G r K X = ∅ :=
Finset.eq_empty_iff_forall_notMem.2
(fun v hv => (mem_Dset.1 hv).2 (h v (mem_Dset.1 hv).1))
rw [gDST, hD]
simp [sourceComps]
theorem Dset_eq_of {X R : Finset V} (hr : r ∈ R) (hR : ∀ v ∈ R, ReachIn G (Kbar r K X) r v)
(hcl : ∀ a ∈ R, ∀ b ∈ Kbar r K X, G.Adj a b → b ∈ R) :
Dset G r K X = Kbar r K X \ R := by
ext v
rw [mem_Dset, Finset.mem_sdiff]
constructor
· rintro ⟨hv, hn⟩
exact ⟨hv, fun h => hn (hR v h)⟩
· rintro ⟨hv, hn⟩
exact ⟨hv, fun h => hn (h.mem_of_closed hr hcl)⟩
theorem sourceComps_eq_single {D : Finset V} (hne : D.Nonempty)
(h : ∀ v ∈ D, ∀ w ∈ D, ReachIn G D v w) : sourceComps G D = {D} := by
have hscc : ∀ v ∈ D, scc G D v = D := by
intro v hv
ext w
rw [mem_scc]
exact ⟨fun hw => hw.1, fun hw => ⟨hw, h v hv w hw, h w hw v hv⟩⟩
ext C
rw [mem_sourceComps, Finset.mem_singleton]
constructor
· rintro ⟨⟨v, hv, rfl⟩, -⟩
exact hscc v hv
· rintro rfl
obtain ⟨v, hv⟩ := hne
exact ⟨⟨v, hv, hscc v hv⟩, fun u hu _ _ _ => hu⟩
theorem strong_of_adj {D : Finset V} (h : ∀ v ∈ D, ∀ w ∈ D, v = w ∨ G.Adj v w) :
∀ v ∈ D, ∀ w ∈ D, ReachIn G D v w := by
intro v hv w hw
rcases h v hv w hw with rfl | hadj
· exact ReachIn.of_mem hv
· exact (ReachIn.of_mem hv).tail_adj hw hadj
/-! ### Helpers for `exists_outArb` and `exists_rtree` -/
namespace Aux
/-- `v` is reached from `r` by a walk of exactly `d` arcs inside `N`. -/
def RW (G : Digraph V) (N : Finset V) (r : V) : ℕ → V → Prop
| 0, v => v = r
| d + 1, v => ∃ a, RW G N r d a ∧ a ∈ N ∧ v ∈ N ∧ G.Adj a v
theorem exists_RW {N : Finset V} {v : V} (h : ReachIn G N r v) : ∃ d, RW G N r d v := by
obtain ⟨-, h⟩ := h
induction h with
| refl => exact ⟨0, by simp only [RW]⟩
| tail _ hbc ih =>
obtain ⟨d, hd⟩ := ih
exact ⟨d + 1, by simp only [RW]; exact ⟨_, hd, hbc.1, hbc.2.1, hbc.2.2⟩⟩
/-- The children of `v`: the vertices `u ∈ N \ {r}` with `par u = v`, in some order. -/
noncomputable def kids (par : V → V) (N : Finset V) (r v : V) : List V :=
(N.filter (fun u => u ≠ r ∧ par u = v)).toList
/-- Follow a list of child indices from `v`. -/
noncomputable def walk (par : V → V) (N : Finset V) (r : V) : V → List ℕ → Option V
| v, [] => some v
| v, i :: p => ((kids par N r v)[i]?).bind (fun c => walk par N r c p)
/-- The label of a vertex: `steiner` on `S`, `term` elsewhere. -/
def lab (S : Finset V) (v : V) : DSTCert.Kind := if v ∈ S then .steiner else .term
/-- The tree below `v`, cut at depth `n`. -/
noncomputable def tree (par : V → V) (N S : Finset V) (r : V) : ℕ → V → RTree DSTCert.Kind
| 0, v => .node (lab S v) []
| n + 1, v => .node (lab S v) ((kids par N r v).map (tree par N S r n))
/-- The vertex at a position (`r` off the tree). -/
noncomputable def phi (par : V → V) (N : Finset V) (r : V) (p : List ℕ) : V :=
(walk par N r r p).getD r
/-- The positions in `P` whose vertex lies in `X`. -/
noncomputable def pre (par : V → V) (N : Finset V) (r : V) (P : Finset (List ℕ))
(X : Finset V) : Finset (List ℕ) :=
P.filter (fun p => phi par N r p ∈ X)
theorem mem_of_getElem {l : List V} {i : ℕ} {a : V} (h : l[i]? = some a) : a ∈ l :=
List.mem_iff_getElem?.2 ⟨i, h⟩
theorem getElem_inj_of_nodup {l : List V} (hl : l.Nodup) {i j : ℕ} {a : V}
(hi : l[i]? = some a) (hj : l[j]? = some a) : i = j := by
rw [List.getElem?_eq_some_iff] at hi hj
obtain ⟨hi', rfl⟩ := hi
obtain ⟨hj', hj⟩ := hj
exact (List.Nodup.getElem_inj_iff hl).1 hj.symm
theorem mem_kids {par : V → V} {N : Finset V} {v c : V} :
c ∈ kids par N r v ↔ c ∈ N ∧ c ≠ r ∧ par c = v := by
simp only [kids, Finset.mem_toList, Finset.mem_filter]
theorem walk_nil (par : V → V) (N : Finset V) (v : V) : walk par N r v [] = some v := by
simp only [walk]
theorem walk_cons (par : V → V) (N : Finset V) (v : V) (i : ℕ) (p : List ℕ) :
walk par N r v (i :: p) = ((kids par N r v)[i]?).bind (fun c => walk par N r c p) := by
simp only [walk]
theorem walk_append (par : V → V) (N : Finset V) (p : List ℕ) :
∀ (v : V) (i : ℕ),
walk par N r v (p ++ [i]) = (walk par N r v p).bind (fun u => (kids par N r u)[i]?) := by
induction p with
| nil => intro v i; simp [walk]
| cons j p ih =>
intro v i
rw [List.cons_append, walk_cons, walk_cons, Option.bind_assoc]
congr 1
funext c
exact ih c i
theorem walk_spec {N : Finset V} (A : OutArb G r N) :
∀ (p : List ℕ) (v u : V), v ∈ N → walk A.par N r v p = some u →
u ∈ N ∧ A.height v + p.length ≤ A.height u := by
intro p
induction p with
| nil =>
intro v u hv h
rw [walk_nil] at h
cases h
exact ⟨hv, by simp⟩
| cons i q ih =>
intro v u hv h
rw [walk_cons] at h
cases hc : (kids A.par N r v)[i]? with
| none => rw [hc] at h; simp at h
| some c =>
rw [hc] at h
obtain ⟨hcN, hcr, hcp⟩ := mem_kids.1 (mem_of_getElem hc)
have h1 := A.height_lt c hcN hcr
rw [hcp] at h1
obtain ⟨huN, hu⟩ := ih c u hcN h
refine ⟨huN, ?_⟩
simp only [List.length_cons]
omega
theorem walk_last (par : V → V) (N : Finset V) {v u : V} {p : List ℕ} (hp : p ≠ [])
(h : walk par N r v p = some u) :
∃ w, walk par N r v p.dropLast = some w ∧ (kids par N r w)[p.getLast hp]? = some u := by
rw [← List.dropLast_append_getLast hp, walk_append] at h
cases hw : walk par N r v p.dropLast with
| none => rw [hw] at h; simp at h
| some w => rw [hw] at h; exact ⟨w, rfl, h⟩
theorem walk_inj {N : Finset V} (A : OutArb G r N) {v : V} (hv : v ∈ N) :
∀ (n : ℕ) (p q : List ℕ) (u : V), p.length < n → walk A.par N r v p = some u →
walk A.par N r v q = some u → p = q := by
-- a nonempty walk from `v` does not return to `v`
have hne : ∀ (s : List ℕ), s ≠ [] → walk A.par N r v s = some v → False := by
intro s hs h
obtain ⟨w, hw, hwv⟩ := walk_last A.par N hs h
obtain ⟨hvN, hvr, hvp⟩ := mem_kids.1 (mem_of_getElem hwv)
have h1 := A.height_lt v hvN hvr
rw [hvp] at h1
have h2 := (walk_spec A _ v w hv hw).2
omega
intro n
induction n with
| zero => intro p q u h; exact absurd h (Nat.not_lt_zero _)
| succ n ih =>
intro p q u hlen hp hq
by_cases hp0 : p = []
· subst hp0
rw [walk_nil] at hp
cases hp
by_cases hq0 : q = []
· exact hq0.symm
· exact (hne q hq0 hq).elim
· by_cases hq0 : q = []
· subst hq0
rw [walk_nil] at hq
cases hq
exact (hne p hp0 hp).elim
· obtain ⟨w, hw, hwu⟩ := walk_last A.par N hp0 hp
obtain ⟨w', hw', hwu'⟩ := walk_last A.par N hq0 hq
have e1 := (mem_kids.1 (mem_of_getElem hwu)).2.2
have e2 := (mem_kids.1 (mem_of_getElem hwu')).2.2
rw [e1] at e2
subst e2
have hpos : 0 < p.length := by
cases p with
| nil => exact absurd rfl hp0
| cons a l => simp
have hlt : p.dropLast.length < n := by
rw [List.length_dropLast]
omega
have hd := ih p.dropLast q.dropLast w hlt hw hw'
have hi := getElem_inj_of_nodup (Finset.nodup_toList _) hwu hwu'
rw [← List.dropLast_append_getLast hp0, ← List.dropLast_append_getLast hq0, hd, hi]
theorem walk_surj {N : Finset V} (A : OutArb G r N) :
∀ (n : ℕ) (u : V), u ∈ N → A.height u < n → ∃ p, walk A.par N r r p = some u := by
intro n
induction n with
| zero => intro u _ h; exact absurd h (Nat.not_lt_zero _)
| succ n ih =>
intro u hu hlt
by_cases hur : u = r
· exact ⟨[], by rw [walk_nil, hur]⟩
· have h1 := A.height_lt u hu hur
obtain ⟨p, hp⟩ := ih (A.par u) (A.par_mem u hu hur) (by omega)
have hmem : u ∈ kids A.par N r (A.par u) := mem_kids.2 ⟨hu, hur, rfl⟩
obtain ⟨i, hi⟩ := List.mem_iff_getElem?.1 hmem
exact ⟨p ++ [i], by rw [walk_append, hp]; exact hi⟩
theorem lab_eq_steiner {S : Finset V} {u : V} : lab S u = .steiner ↔ u ∈ S := by
unfold lab
split_ifs with h <;> simp [h]
theorem lab_eq_term {S : Finset V} {u : V} : lab S u = .term ↔ u ∉ S := by
unfold lab
split_ifs with h <;> simp [h]
theorem rootKind_tree (par : V → V) (N S : Finset V) (n : ℕ) (v : V) :
DSTCert.rootKind (tree par N S r n v) = lab S v := by
cases n <;> rfl
theorem labelAt_tree {N : Finset V} (A : OutArb G r N) (S : Finset V) :
∀ (n : ℕ) (v : V) (p : List ℕ), v ∈ N → N.sup A.height ≤ A.height v + n →
DSTCert.labelAt (tree A.par N S r n v) p = (walk A.par N r v p).map (lab S) := by
intro n
induction n with
| zero =>
intro v p hv hM
cases p with
| nil => simp [tree, walk_nil, DSTCert.labelAt_nil]
| cons i q =>
have hk : kids A.par N r v = [] := by
cases hk : kids A.par N r v with
| nil => rfl
| cons c l =>
exfalso
have hc : c ∈ kids A.par N r v := by rw [hk]; simp
obtain ⟨hcN, hcr, hcp⟩ := mem_kids.1 hc
have h1 := A.height_lt c hcN hcr
have h2 : A.height c ≤ N.sup A.height := Finset.le_sup hcN
rw [hcp] at h1
omega
simp [tree, walk_cons, DSTCert.labelAt_cons, hk]
| succ n ih =>
intro v p hv hM
cases p with
| nil => simp [tree, walk_nil, DSTCert.labelAt_nil]
| cons i q =>
simp only [tree]
rw [walk_cons, DSTCert.labelAt_cons, List.getElem?_map]
cases hc : (kids A.par N r v)[i]? with
| none => simp
| some c =>
obtain ⟨hcN, hcr, hcp⟩ := mem_kids.1 (mem_of_getElem hc)
have h1 := A.height_lt c hcN hcr
rw [hcp] at h1
have := ih c q hcN (by omega)
simpa using this
theorem noLeaf_tree (A : OutArb G r (Kbar r K S)) (hrK : r ∉ K) (hrS : r ∉ S)
(hNL : NoSteinerLeafG A) : ∀ (n : ℕ) (v : V), v ∈ Kbar r K S →
(Kbar r K S).sup A.height ≤ A.height v + n →
DSTCert.NoSteinerLeaf (tree A.par (Kbar r K S) S r n v) := by
have hchild : ∀ v ∈ S, ∃ c, c ∈ kids A.par (Kbar r K S) r v := by
intro v hv
obtain ⟨u, hu, hpu⟩ := hNL v hv
rw [Finset.mem_union] at hu
refine ⟨u, mem_kids.2 ⟨?_, ?_, hpu⟩⟩
· rw [mem_Kbar]
tauto
· rintro rfl
tauto
intro n
induction n with
| zero =>
intro v hv hM
simp only [tree]
rw [DSTCert.NoSteinerLeaf]
refine ⟨fun hs => ?_, by simp [DSTCert.NoSteinerLeafAll]⟩
exfalso
obtain ⟨c, hc⟩ := hchild v (lab_eq_steiner.1 hs)
obtain ⟨hcN, hcr, hcp⟩ := mem_kids.1 hc
have h1 := A.height_lt c hcN hcr
have h2 : A.height c ≤ (Kbar r K S).sup A.height := Finset.le_sup hcN
rw [hcp] at h1
omega
| succ n ih =>
intro v hv hM
simp only [tree]
rw [DSTCert.NoSteinerLeaf, DSTCert.rec_noLeafAll_iff]
refine ⟨fun hs => ?_, fun c hc => ?_⟩
· obtain ⟨c, hc⟩ := hchild v (lab_eq_steiner.1 hs)
cases hk : kids A.par (Kbar r K S) r v with
| nil => rw [hk] at hc; simp at hc
| cons a l => simp
· rw [List.mem_map] at hc
obtain ⟨c', hc', rfl⟩ := hc
obtain ⟨hcN, hcr, hcp⟩ := mem_kids.1 hc'
have h1 := A.height_lt c' hcN hcr
rw [hcp] at h1
exact ih c' hcN (by omega)
/-- `count k t` is the number of positions labelled `k` (any tree). -/
theorem count_eq_card (k : DSTCert.Kind) : ∀ t : RTree DSTCert.Kind,
DSTCert.count k t =
((DSTCert.positions t).filter (fun p => DSTCert.labelAt t p = some k)).card := by
refine Antinorm8.RTree.ind _ ?_
intro k' cs ih
have hall : ∀ (cs' pre : List (RTree DSTCert.Kind)),
(∀ c ∈ cs', DSTCert.count k c =
((DSTCert.positions c).filter (fun p => DSTCert.labelAt c p = some k)).card) →
((DSTCert.positionsAll pre.length cs').filter
(fun p => DSTCert.labelAt (.node k' (pre ++ cs')) p = some k)).card =
DSTCert.countAll k cs' := by
intro cs'
induction cs' with
| nil => intro pre _; simp [DSTCert.positionsAll_nil, DSTCert.countAll]
| cons c cs' ihc =>
intro pre h
have hdisj : Disjoint ((DSTCert.positions c).map (DSTCert.consEmb pre.length))
(DSTCert.positionsAll (pre.length + 1) cs') := by
rw [Finset.disjoint_left]
intro p hp1 hp2
obtain ⟨q, _, rfl⟩ := Finset.mem_map.1 hp1
obtain ⟨a, q', he, ha, -⟩ :=
(DSTCert.mem_positionsAll_aux cs' (fun c _ p => DSTCert.mem_positions_iff) _ _).1 hp2
rw [DSTCert.consEmb_apply] at he
have := (List.cons.inj he).1
omega
have hlc : ∀ q, DSTCert.labelAt (.node k' (pre ++ c :: cs')) (pre.length :: q) =
DSTCert.labelAt c q := by
intro q
rw [DSTCert.labelAt_cons, List.getElem?_append_right (le_refl _), Nat.sub_self]
rfl
have ih2 := ihc (pre ++ [c]) (fun c' hc' => h c' (List.mem_cons_of_mem _ hc'))
rw [List.length_append, List.length_singleton, List.append_assoc,
List.singleton_append] at ih2
rw [DSTCert.positionsAll_cons, Finset.filter_union,
Finset.card_union_of_disjoint (Finset.disjoint_filter_filter hdisj), Finset.filter_map,
Finset.card_map, ih2, DSTCert.countAll, h c (List.mem_cons_self ..)]
congr 2
ext q
simp only [Finset.mem_filter, Function.comp_apply, DSTCert.consEmb_apply, hlc]
have hnot : ([] : List ℕ) ∉ DSTCert.positionsAll 0 cs := by
intro hm
obtain ⟨a, q, he, -⟩ :=
(DSTCert.mem_positionsAll_aux cs (fun c _ p => DSTCert.mem_positions_iff) _ _).1 hm
simp at he
have h0 := hall cs [] ih
simp only [List.length_nil, List.nil_append] at h0
rw [Finset.card_filter, DSTCert.positions_node, Finset.sum_insert hnot, ← Finset.card_filter,
h0, DSTCert.labelAt_nil, DSTCert.count]
simp
theorem phi_of {par : V → V} {N : Finset V} {p : List ℕ} {u : V}
(h : walk par N r r p = some u) : phi par N r p = u := by
rw [phi, h]
rfl
theorem mem_pre {par : V → V} {N : Finset V} {P : Finset (List ℕ)} {X : Finset V}
{p : List ℕ} : p ∈ pre par N r P X ↔ p ∈ P ∧ phi par N r p ∈ X := by
simp only [pre, Finset.mem_filter]
theorem labelAt_T {N : Finset V} (A : OutArb G r N) (hrN : r ∈ N) (S : Finset V)
(p : List ℕ) :
DSTCert.labelAt (tree A.par N S r (N.sup A.height) r) p =
(walk A.par N r r p).map (lab S) :=
labelAt_tree A S _ r p hrN (Nat.le_add_left _ _)
theorem mem_positions_T {N : Finset V} (A : OutArb G r N) (hrN : r ∈ N) (S : Finset V)
(p : List ℕ) :
p ∈ DSTCert.positions (tree A.par N S r (N.sup A.height) r) ↔
∃ u, walk A.par N r r p = some u := by
rw [DSTCert.mem_positions_iff, labelAt_T A hrN S p]
cases walk A.par N r r p <;> simp
theorem mem_steinerPos_T {N : Finset V} (A : OutArb G r N) (hrN : r ∈ N) (S : Finset V)
(p : List ℕ) :
p ∈ DSTCert.steinerPos (tree A.par N S r (N.sup A.height) r) ↔
∃ u, walk A.par N r r p = some u ∧ u ∈ S := by
rw [DSTCert.steinerPos, Finset.mem_filter, mem_positions_T A hrN S p, labelAt_T A hrN S p]
cases walk A.par N r r p with
| none => simp
| some u => simp [lab_eq_steiner]
theorem card_transfer {N : Finset V} (A : OutArb G r N) (hrN : r ∈ N) (S : Finset V)
(P : V → Prop) [DecidablePred P] :
((DSTCert.positions (tree A.par N S r (N.sup A.height) r)).filter
(fun p => P (phi A.par N r p))).card = (N.filter P).card := by
refine Finset.card_nbij (phi A.par N r) ?_ ?_ ?_
· intro p hp
rw [Finset.mem_coe, Finset.mem_filter] at hp
rw [Finset.mem_coe, Finset.mem_filter]
obtain ⟨u, hu⟩ := (mem_positions_T A hrN S p).1 hp.1
have h2 := hp.2
rw [phi_of hu] at h2 ⊢
exact ⟨(walk_spec A p r u hrN hu).1, h2⟩
· intro p₁ h₁ p₂ h₂ he
have h₁' := (Finset.mem_filter.1 (Finset.mem_coe.1 h₁)).1
have h₂' := (Finset.mem_filter.1 (Finset.mem_coe.1 h₂)).1
obtain ⟨u₁, hu₁⟩ := (mem_positions_T A hrN S p₁).1 h₁'
obtain ⟨u₂, hu₂⟩ := (mem_positions_T A hrN S p₂).1 h₂'
rw [phi_of hu₁, phi_of hu₂] at he
subst he
exact walk_inj A hrN _ p₁ p₂ u₁ (Nat.lt_succ_self _) hu₁ hu₂
· intro u hu
obtain ⟨huN, hPu⟩ := Finset.mem_filter.1 (Finset.mem_coe.1 hu)
obtain ⟨p, hp⟩ := walk_surj A _ u huN (Nat.lt_succ_self _)
refine ⟨p, ?_, phi_of hp⟩
rw [Finset.mem_coe, Finset.mem_filter, mem_positions_T A hrN S p, phi_of hp]
exact ⟨⟨u, hp⟩, hPu⟩
theorem count_T {N : Finset V} (A : OutArb G r N) (hrN : r ∈ N) (S : Finset V)
(k : DSTCert.Kind) :
DSTCert.count k (tree A.par N S r (N.sup A.height) r) =
(N.filter (fun u => lab S u = k)).card := by
rw [count_eq_card, ← card_transfer A hrN S (fun u => lab S u = k)]
congr 1
refine Finset.filter_congr (fun p hp => ?_)
obtain ⟨u, hu⟩ := (mem_positions_T A hrN S p).1 hp
rw [labelAt_T A hrN S p, hu, phi_of hu]
simp
theorem phi_injOn {N : Finset V} (A : OutArb G r N) (hrN : r ∈ N) (S : Finset V)
{p q : List ℕ} (hp : p ∈ DSTCert.positions (tree A.par N S r (N.sup A.height) r))
(hq : q ∈ DSTCert.positions (tree A.par N S r (N.sup A.height) r))
(h : phi A.par N r p = phi A.par N r q) : p = q := by
obtain ⟨u, hu⟩ := (mem_positions_T A hrN S p).1 hp
obtain ⟨u', hu'⟩ := (mem_positions_T A hrN S q).1 hq
rw [phi_of hu, phi_of hu'] at h
subst h
exact walk_inj A hrN _ p q u (Nat.lt_succ_self _) hu hu'
theorem inKbar_T (A : OutArb G r (Kbar r K S)) (hrK : r ∉ K) (hSU : S ⊆ nonterm r K)
{X' : Finset (List ℕ)}
(hX' : X' ⊆ DSTCert.steinerPos
(tree A.par (Kbar r K S) S r ((Kbar r K S).sup A.height) r))
{p : List ℕ} {u : V} (hp : walk A.par (Kbar r K S) r r p = some u) :
DSTCert.inKbar (tree A.par (Kbar r K S) S r ((Kbar r K S).sup A.height) r) X' p ↔
u ∈ Kbar r K (X'.image (phi A.par (Kbar r K S) r)) := by
have hrS : r ∉ S := fun h => (mem_nonterm.1 (hSU h)).1 rfl
have hSK : ∀ w ∈ S, w ∉ K := fun w hw => (mem_nonterm.1 (hSU hw)).2
have huN := (walk_spec A p r u r_mem_Kbar hp).1
have hmem : p ∈ X' ↔ u ∈ X'.image (phi A.par (Kbar r K S) r) := by
rw [Finset.mem_image]
constructor
· intro h
exact ⟨p, h, phi_of hp⟩
· rintro ⟨q, hq, hqu⟩
obtain ⟨u', hu', -⟩ := (mem_steinerPos_T A r_mem_Kbar S q).1 (hX' hq)
rw [phi_of hu'] at hqu
subst hqu
rw [walk_inj A r_mem_Kbar _ p q u' (Nat.lt_succ_self _) hp hu']
exact hq
have hX'S : p ∈ X' → u ∈ S := by
intro h
obtain ⟨u', hu', hS⟩ := (mem_steinerPos_T A r_mem_Kbar S p).1 (hX' h)
rw [hp] at hu'
cases hu'
exact hS
rw [DSTCert.inKbar, labelAt_T A r_mem_Kbar S p, hp, mem_Kbar, ← hmem]
have hlab : Option.map (lab S) (some u) = some DSTCert.Kind.term ↔ u ∉ S := by
simp [lab_eq_term]
rw [hlab]
rw [mem_Kbar] at huN
constructor
· rintro (h | h)
· rcases huN with h' | h' | h'
· exact Or.inl h'
· exact Or.inr (Or.inl h')
· exact absurd h' h
· exact Or.inr (Or.inr h)
· rintro (h | h | h)
· left
rw [h]
exact hrS
· left
exact fun hs => hSK u hs h
· exact Or.inr h
theorem PsiA_T (A : OutArb G r (Kbar r K S)) (hrK : r ∉ K) (hSU : S ⊆ nonterm r K)
{X' : Finset (List ℕ)}
(hX' : X' ⊆ DSTCert.steinerPos
(tree A.par (Kbar r K S) S r ((Kbar r K S).sup A.height) r)) :
DSTCert.PsiA (tree A.par (Kbar r K S) S r ((Kbar r K S).sup A.height) r) X' =
PsiG A (X'.image (phi A.par (Kbar r K S) r)) := by
have hrS : r ∉ S := fun h => (mem_nonterm.1 (hSU h)).1 rfl
have hXS : X'.image (phi A.par (Kbar r K S) r) ⊆ S := by
intro u hu
obtain ⟨q, hq, rfl⟩ := Finset.mem_image.1 hu
obtain ⟨u', hu', hS⟩ := (mem_steinerPos_T A r_mem_Kbar S q).1 (hX' hq)
rw [phi_of hu']
exact hS
have e1 : PsiG A (X'.image (phi A.par (Kbar r K S) r)) =
((Kbar r K S).filter (fun u => u ∈ K ∪ X'.image (phi A.par (Kbar r K S) r) ∧
A.par u ∉ Kbar r K (X'.image (phi A.par (Kbar r K S) r)))).card := by
rw [PsiG]
congr 1
ext u
simp only [Finset.mem_filter]
constructor
· rintro ⟨h1, h2⟩
refine ⟨?_, h1, h2⟩
rw [mem_Kbar]
rw [Finset.mem_union] at h1
rcases h1 with h | h
· exact Or.inr (Or.inl h)
· exact Or.inr (Or.inr (hXS h))
· rintro ⟨-, h1, h2⟩
exact ⟨h1, h2⟩
rw [e1, ← card_transfer A r_mem_Kbar S (fun u => u ∈ K ∪ X'.image (phi A.par (Kbar r K S) r) ∧
A.par u ∉ Kbar r K (X'.image (phi A.par (Kbar r K S) r))), DSTCert.PsiA]
congr 1
refine Finset.filter_congr (fun p hp => ?_)
obtain ⟨u, hu⟩ := (mem_positions_T A r_mem_Kbar S p).1 hp
rw [phi_of hu, inKbar_T A hrK hSU hX' hu]
show _ ↔ (u ∈ K ∪ X'.image (phi A.par (Kbar r K S) r) ∧
A.par u ∉ Kbar r K (X'.image (phi A.par (Kbar r K S) r)))
constructor
· rintro ⟨hne, hin, hnot⟩
obtain ⟨w, hw, hwu⟩ := walk_last A.par _ hne hu
obtain ⟨-, hur, hpw⟩ := mem_kids.1 (mem_of_getElem hwu)
rw [inKbar_T A hrK hSU hX' hw, ← hpw] at hnot
refine ⟨?_, hnot⟩
rw [mem_Kbar] at hin
rw [Finset.mem_union]
rcases hin with h | h | h
· exact absurd h hur
· exact Or.inl h
· exact Or.inr h
· rintro ⟨hin, hnot⟩
have hur : u ≠ r := by
rintro rfl
rw [Finset.mem_union] at hin
rcases hin with h | h
· exact hrK h
· exact hrS (hXS h)
have hne : p ≠ [] := by
rintro rfl
rw [walk_nil] at hu
cases hu
exact hur rfl
obtain ⟨w, hw, hwu⟩ := walk_last A.par _ hne hu
obtain ⟨-, -, hpw⟩ := mem_kids.1 (mem_of_getElem hwu)
refine ⟨hne, ?_, ?_⟩
· rw [mem_Kbar]
rw [Finset.mem_union] at hin
tauto
· rw [inKbar_T A hrK hSU hX' hw, ← hpw]
exact hnot
theorem WA_T (A : OutArb G r (Kbar r K S)) (hrK : r ∉ K) (hSU : S ⊆ nonterm r K) (y : ℝ) :
DSTCert.WA y (tree A.par (Kbar r K S) S r ((Kbar r K S).sup A.height) r) = WAg A y := by
have hSN : S ⊆ Kbar r K S := fun u hu => by rw [mem_Kbar]; exact Or.inr (Or.inr hu)
have hsub : DSTCert.steinerPos (tree A.par (Kbar r K S) S r ((Kbar r K S).sup A.height) r) ⊆
DSTCert.positions (tree A.par (Kbar r K S) S r ((Kbar r K S).sup A.height) r) :=
DSTCert.steinerPos_subset _
rw [DSTCert.WA, WAg]
refine Finset.sum_nbij' (Finset.image (phi A.par (Kbar r K S) r))
(pre A.par (Kbar r K S) r
(DSTCert.steinerPos (tree A.par (Kbar r K S) S r ((Kbar r K S).sup A.height) r)))
?_ ?_ ?_ ?_ ?_
· intro X' hX'
have hX'' : X' ⊆ _ := Finset.mem_powerset.1 (by simpa using hX')
simp only [Finset.mem_powerset]
intro u hu
obtain ⟨q, hq, rfl⟩ := Finset.mem_image.1 hu
obtain ⟨u', hu', hS⟩ := (mem_steinerPos_T A r_mem_Kbar S q).1 (hX'' hq)
rw [phi_of hu']
exact hS
· intro X _
simp only [Finset.mem_powerset]
intro p hp
exact (mem_pre.1 hp).1
· intro X' hX'
have hX'' : X' ⊆ _ := Finset.mem_powerset.1 (by simpa using hX')
ext p
rw [mem_pre, Finset.mem_image]
constructor
· rintro ⟨hp, q, hq, hqp⟩
rw [phi_injOn A r_mem_Kbar S (hsub (hX'' hq)) (hsub hp) hqp] at hq
exact hq
· intro hp
exact ⟨hX'' hp, p, hp, rfl⟩
· intro X hX
have hX'' : X ⊆ S := Finset.mem_powerset.1 (by simpa using hX)
ext u
rw [Finset.mem_image]
constructor
· rintro ⟨p, hp, rfl⟩
exact (mem_pre.1 hp).2
· intro hu
obtain ⟨p, hp⟩ := walk_surj A _ u (hSN (hX'' hu)) (Nat.lt_succ_self _)
refine ⟨p, ?_, phi_of hp⟩
rw [mem_pre, phi_of hp, mem_steinerPos_T A r_mem_Kbar S p]
exact ⟨⟨u, hp, hX'' hu⟩, hu⟩
· intro X' hX'
have hX'' : X' ⊆ _ := Finset.mem_powerset.1 (by simpa using hX')
have hinj : Set.InjOn (phi A.par (Kbar r K S) r) X' := by
intro p hp q hq h
exact phi_injOn A r_mem_Kbar S (hsub (hX'' hp)) (hsub (hX'' hq)) h
rw [Finset.card_image_of_injOn hinj, PsiA_T A hrK hSU hX'']
end Aux
/-! ### Core -/
/-- lem:fa-dst-point, inequality. -/
theorem fa_dst_point (hrK : r ∉ K) (hSU : S ⊆ nonterm r K)
(A : OutArb G r (Kbar r K S)) {X : Finset V} (hX : X ⊆ S) :
gDST G r K X ≤ PsiG A X := by
have key : ∀ C ∈ sourceComps G (Dset G r K X),
∃ u, (u ∈ K ∪ X ∧ A.par u ∉ Kbar r K X) ∧ u ∈ C := by
intro C hC
obtain ⟨⟨v, hvD, hvC⟩, -⟩ := mem_sourceComps.1 hC
obtain ⟨u, huD, hreach, hpar⟩ := exists_top A hX _ v hvD (Nat.lt_succ_self _)
have hu := (mem_Dset.1 huD).1
have hur : u ≠ r := by
rintro rfl
exact (mem_Dset.1 huD).2 (ReachIn.of_mem r_mem_Kbar)
refine ⟨u, ⟨?_, hpar⟩, ?_⟩
· rw [mem_Kbar] at hu
rw [Finset.mem_union]
rcases hu with h | h | h
· exact absurd h hur
· exact Or.inl h
· exact Or.inr h
· have hvC' : v ∈ C := hvC ▸ scc_self hvD
exact mem_of_mem_sourceComps hC hvC' hreach
have : Nonempty V := ⟨r⟩
choose! f hf using key
have e : ∀ C ∈ sourceComps G (Dset G r K X), C = scc G (Dset G r K X) (f C) := by
intro C hC
obtain ⟨⟨v, _, rfl⟩, -⟩ := mem_sourceComps.1 hC
exact (scc_eq_of_mem (hf _ hC).2).symm
unfold gDST PsiG
refine Finset.card_le_card_of_injOn f ?_ ?_
· intro C hC
have hC' : C ∈ sourceComps G (Dset G r K X) := by simpa using hC
simp only [Finset.mem_coe, Finset.mem_filter]
exact (hf C hC').1
· intro C₁ h₁ C₂ h₂ he
rw [e C₁ (Finset.mem_coe.1 h₁), e C₂ (Finset.mem_coe.1 h₂), he]
/-- eq:fa-dst-W. -/
theorem fa_dst_W (hrK : r ∉ K) (hSU : S ⊆ nonterm r K)
(A : OutArb G r (Kbar r K S)) {y : ℝ} (hy : 0 ≤ y) :
WAg A y ≤ WS G r K S y := by
unfold WAg WS
refine Finset.sum_le_sum (fun X hX => ?_)
have hXS : X ⊆ S := Finset.mem_powerset.1 hX
exact mul_le_mul_of_nonneg_left
(pow_le_pow_of_le_one (by norm_num) (by norm_num) (fa_dst_point hrK hSU A hXS))
(pow_nonneg hy _)
/-! ### Optional -/
/-- lem:fa-dst-point, equality clause: if `G[\bar K_X] = A[\bar K_X]`, then `g(X) = Ψ_A(X)`. -/
theorem fa_dst_point_eq (hrK : r ∉ K) (hSU : S ⊆ nonterm r K)
(A : OutArb G r (Kbar r K S)) {X : Finset V} (hX : X ⊆ S)
(hGA : ∀ a ∈ Kbar r K X, ∀ b ∈ Kbar r K X, G.Adj a b ↔ (b ≠ r ∧ A.par b = a)) :
gDST G r K X = PsiG A X := by
refine le_antisymm (fa_dst_point hrK hSU A hX) ?_
-- under `hGA`, a vertex whose parent is outside `\bar K_X` is reached by nothing else
have only : ∀ (T : Finset V), T ⊆ Kbar r K X → ∀ u ∈ Kbar r K X, A.par u ∉ Kbar r K X →
∀ b, ReachIn G T b u → b = u := by
intro T hT u hu hpar b hb
obtain ⟨-, hb⟩ := hb
cases hb with
| refl => rfl
| tail _ hcu =>
have h1 := ((hGA _ (hT hcu.1) _ hu).1 hcu.2.2).2
exact absurd (h1 ▸ hT hcu.1) hpar
have hDK : Dset G r K X ⊆ Kbar r K X := fun w hw => (mem_Dset.1 hw).1
have props : ∀ u ∈ (K ∪ X).filter (fun u => A.par u ∉ Kbar r K X),
u ∈ Kbar r K X ∧ A.par u ∉ Kbar r K X ∧ u ∈ Dset G r K X := by
intro u hu
rw [Finset.mem_filter, Finset.mem_union] at hu
have hur : u ≠ r := by
rintro rfl
rcases hu.1 with h | h
· exact hrK h
· exact (mem_nonterm.1 (hSU (hX h))).1 rfl
have huK : u ∈ Kbar r K X := by
rw [mem_Kbar]
tauto
exact ⟨huK, hu.2, mem_Dset.2 ⟨huK, fun h =>
hur (only _ (Finset.Subset.refl _) u huK hu.2 r h).symm⟩⟩
unfold gDST PsiG
refine Finset.card_le_card_of_injOn (scc G (Dset G r K X)) ?_ ?_
· intro u hu
have hu' : u ∈ (K ∪ X).filter (fun u => A.par u ∉ Kbar r K X) := by simpa using hu
obtain ⟨huK, hpar, huD⟩ := props u hu'
simp only [Finset.mem_coe]
rw [mem_sourceComps]
refine ⟨⟨u, huD, rfl⟩, fun a ha b hb hab => ?_⟩
have hbu : b = u := only _ hDK u huK hpar b (mem_scc.1 hb).2.2
subst hbu
have h1 := ((hGA a (hDK ha) b huK).1 hab).2
exact (hpar (h1 ▸ hDK ha)).elim
· intro u₁ h₁ u₂ h₂ he
have h₁' : u₁ ∈ (K ∪ X).filter (fun u => A.par u ∉ Kbar r K X) := by simpa using h₁
have h₂' : u₂ ∈ (K ∪ X).filter (fun u => A.par u ∉ Kbar r K X) := by simpa using h₂
obtain ⟨-, -, hu₁D⟩ := props u₁ h₁'
obtain ⟨hu₂K, hpar₂, -⟩ := props u₂ h₂'
have hmem : u₁ ∈ scc G (Dset G r K X) u₂ := he ▸ scc_self hu₁D
exact only _ hDK u₂ hu₂K hpar₂ u₁ (mem_scc.1 hmem).2.2
/-- `WS` is `MLS.W` for the running-time exponent `g` (which ignores `k`). -/
theorem WS_eq_MLS_W (k : ℕ) (y : ℝ) :
WS G r K S y = MLS.W (fun X _ => (gDST G r K X : ℝ)) S k y := by
unfold WS MLS.W
refine Finset.sum_congr rfl (fun X _ => ?_)
rw [Real.rpow_neg (by norm_num : (0 : ℝ) ≤ 2), Real.rpow_natCast, one_div, inv_pow]
/-- An out-arborescence exists when `S` is rooted. -/
theorem exists_outArb (hroot : Rooted G r K S) : Nonempty (OutArb G r (Kbar r K S)) := by
classical
have hreach : ∀ v ∈ Kbar r K S, ∃ d, Aux.RW G (Kbar r K S) r d v := by
intro v hv
by_cases hvr : v = r
· exact ⟨0, by simp only [Aux.RW]; exact hvr⟩
· have hv' : v ∈ K ∪ S := by
rw [mem_Kbar] at hv
rw [Finset.mem_union]
tauto
exact Aux.exists_RW (hroot v hv')
let dist : V → ℕ := fun v =>
if h : ∃ d, Aux.RW G (Kbar r K S) r d v then Nat.find h else 0
have key : ∀ v ∈ Kbar r K S, v ≠ r →
∃ a, a ∈ Kbar r K S ∧ G.Adj a v ∧ dist a < dist v := by
intro v hv hvr
have h := hreach v hv
have hspec := Nat.find_spec h
have hdv : dist v = Nat.find h := dite_eq_left h
obtain ⟨d, hd⟩ : ∃ d, Nat.find h = d + 1 := by
rcases hk : Nat.find h with _ | d
· rw [hk] at hspec
simp only [Aux.RW] at hspec
exact absurd hspec hvr
· exact ⟨d, rfl⟩
rw [hd] at hspec
simp only [Aux.RW] at hspec
obtain ⟨a, ha, haN, -, hadj⟩ := hspec
refine ⟨a, haN, hadj, ?_⟩
have ha' : ∃ d, Aux.RW G (Kbar r K S) r d a := ⟨d, ha⟩
have hda : dist a = Nat.find ha' := dite_eq_left ha'
rw [hda, hdv, hd]
exact Nat.lt_succ_of_le (Nat.find_min' ha' ha)
have : Nonempty V := ⟨r⟩
choose! p hp using key
exact ⟨⟨p, dist, fun u hu hur => (hp u hu hur).1, fun u hu hur => (hp u hu hur).2.1,
fun u hu hur => (hp u hu hur).2.2⟩⟩
/-- Minimality: no vertex of `S` is a leaf. -/
theorem noSteinerLeaf_of_minimal (hrK : r ∉ K) (hSU : S ⊆ nonterm r K)
(hmin : ∀ T ⊆ S, Rooted G r K T → T = S) (A : OutArb G r (Kbar r K S)) :
NoSteinerLeafG A := by
intro v hv
by_contra hno
have hno' : ∀ u ∈ K ∪ S, A.par u ≠ v := fun u hu h => hno ⟨u, hu, h⟩
have key : ∀ (n : ℕ) (w : V), w ∈ Kbar r K (S.erase v) → A.height w < n →
ReachIn G (Kbar r K (S.erase v)) r w := by
intro n
induction n with
| zero => intro w _ h; exact absurd h (Nat.not_lt_zero _)
| succ n ih =>
intro w hw hlt
by_cases hwr : w = r
· rw [hwr]
exact ReachIn.of_mem r_mem_Kbar
· have hwKS : w ∈ K ∪ S := by
rw [mem_Kbar, Finset.mem_erase] at hw
rw [Finset.mem_union]
tauto
have hwN : w ∈ Kbar r K S := by
rw [mem_Kbar]
rw [Finset.mem_union] at hwKS
tauto
have hpN := A.par_mem w hwN hwr
have hpv : A.par w ≠ v := hno' w hwKS
have hp' : A.par w ∈ Kbar r K (S.erase v) := by
rw [mem_Kbar] at hpN ⊢
rw [Finset.mem_erase]
tauto
have h1 := A.height_lt w hwN hwr
exact (ih (A.par w) hp' (by omega)).tail_adj hw (A.par_adj w hwN hwr)
have hroot : Rooted G r K (S.erase v) := by
intro w hw
refine key _ w ?_ (Nat.lt_succ_self _)
rw [mem_Kbar]
rw [Finset.mem_union] at hw
tauto
have he := hmin (S.erase v) (Finset.erase_subset _ _) hroot
have h2 : v ∈ S.erase v := by
rw [he]
exact hv
exact (Finset.mem_erase.1 h2).1 rfl
/-- The bridge to `lem:fa-dst-rec` and `lem:fa-dst-cert`: a tree with the properties that `dst_tree_bound_WA` uses. -/
theorem exists_rtree (hrK : r ∉ K) (hSU : S ⊆ nonterm r K) (A : OutArb G r (Kbar r K S)) :
∃ t : RTree DSTCert.Kind, DSTCert.rootKind t = .term ∧
DSTCert.count .steiner t = S.card ∧ DSTCert.count .term t = K.card + 1 ∧
(NoSteinerLeafG A → DSTCert.NoSteinerLeaf t) ∧
∀ y : ℝ, DSTCert.WA y t = WAg A y := by
have hrS : r ∉ S := fun h => (mem_nonterm.1 (hSU h)).1 rfl
have hSK : ∀ w ∈ S, w ∉ K := fun w hw => (mem_nonterm.1 (hSU hw)).2
have hSN : S ⊆ Kbar r K S := fun u hu => by rw [mem_Kbar]; exact Or.inr (Or.inr hu)
refine ⟨Aux.tree A.par (Kbar r K S) S r ((Kbar r K S).sup A.height) r, ?_, ?_, ?_, ?_, ?_⟩
· rw [Aux.rootKind_tree]
exact Aux.lab_eq_term.2 hrS
· rw [Aux.count_T A r_mem_Kbar S]
congr 1
ext u
rw [Finset.mem_filter, Aux.lab_eq_steiner]
exact ⟨fun h => h.2, fun h => ⟨hSN h, h⟩⟩
· rw [Aux.count_T A r_mem_Kbar S]
have he : (Kbar r K S).filter (fun u => Aux.lab S u = .term) = insert r K := by
ext u
rw [Finset.mem_filter, Aux.lab_eq_term, Finset.mem_insert, mem_Kbar]
constructor
· rintro ⟨h | h | h, h'⟩
· exact Or.inl h
· exact Or.inr h
· exact absurd h h'
· rintro (h | h)
· exact ⟨Or.inl h, h ▸ hrS⟩
· exact ⟨Or.inr (Or.inl h), fun hs => hSK u hs h⟩
rw [he, Finset.card_insert_of_notMem hrK]
· intro hNL
exact Aux.noLeaf_tree A hrK hrS hNL _ r r_mem_Kbar (Nat.le_add_left _ _)
· intro y
exact Aux.WA_T A hrK hSU y
/-! ### Rooted and minimal sets -/
/-- Every rooted set is a Steiner set. -/
theorem steiner_of_rooted (h : Rooted G r K S) : Steiner G r K S :=
fun v hv => h v (Finset.mem_union_left _ hv)
/-- The reachable part of a Steiner set is a rooted subset of it. -/
theorem reachPart_rooted (hS : Steiner G r K S) :
reachPart G r K S ⊆ S ∧ Rooted G r K (reachPart G r K S) := by
classical
have key : ∀ v, ReachIn G (Kbar r K S) r v →
ReachIn G (Kbar r K (reachPart G r K S)) r v := by
intro v h
obtain ⟨-, h⟩ := h
induction h with
| refl => exact ReachIn.of_mem r_mem_Kbar
| tail hab hbc ih =>
refine ih.tail_adj ?_ hbc.2.2
have hc := hbc.2.1
rw [mem_Kbar] at hc ⊢
rcases hc with hc | hc | hc
· exact Or.inl hc
· exact Or.inr (Or.inl hc)
· refine Or.inr (Or.inr ?_)
simp only [reachPart, Finset.mem_filter]
exact ⟨hc, r_mem_Kbar, hab.tail hbc⟩
refine ⟨fun v hv => (Finset.mem_filter.1 hv).1, fun v hv => ?_⟩
rw [Finset.mem_union] at hv
rcases hv with hv | hv
· exact key v (hS v hv)
· simp only [reachPart, Finset.mem_filter] at hv
exact key v hv.2
/-- An inclusion-minimal Steiner set is rooted, and minimal among rooted sets. -/
theorem rooted_minimal_of_minimal_steiner (hS : Steiner G r K S)
(hmin : ∀ T ⊆ S, Steiner G r K T → T = S) :
Rooted G r K S ∧ ∀ T ⊆ S, Rooted G r K T → T = S := by
have hR := reachPart_rooted hS
have hRS : reachPart G r K S = S := hmin _ hR.1 (steiner_of_rooted hR.2)
exact ⟨hRS ▸ hR.2, fun T hT hTr => hmin T hT (steiner_of_rooted hTr)⟩
/-- A minimum Steiner set is rooted and inclusion-minimal among rooted sets. -/
theorem minimum_steiner_rooted_minimal (hSU : S ⊆ nonterm r K) (hS : Steiner G r K S)
(hleast : ∀ T ⊆ nonterm r K, Steiner G r K T → S.card ≤ T.card) :
Rooted G r K S ∧ ∀ T ⊆ S, Rooted G r K T → T = S := by
have hR := reachPart_rooted hS
have hRS : reachPart G r K S = S :=
Finset.eq_of_subset_of_card_le hR.1 (hleast _ (hR.1.trans hSU) (steiner_of_rooted hR.2))
exact ⟨hRS ▸ hR.2, fun T hT hTr =>
Finset.eq_of_subset_of_card_le hT (hleast T (hT.trans hSU) (steiner_of_rooted hTr))⟩
/-! ### Composites -/
/-- eq:fa-dst-W with lem:fa-dst-cert, for an inclusion-minimal rooted Steiner set. -/
theorem fa_dst_WS_cert (hrK : r ∉ K) (hSU : S ⊆ nonterm r K) (hroot : Rooted G r K S)
(hmin : ∀ T ⊆ S, Rooted G r K T → T = S)
{y e₁ e₂ : ℝ} {Z : Finset (ℝ × ℝ)} (hZ : Z.Nonempty) (h : DSTCert.CertHyp y e₁ e₂ Z) :
DSTCert.cZ Z hZ * e₁ ^ S.card * e₂ ^ (K.card + 1) ≤ WS G r K S y := by
obtain ⟨A⟩ := exists_outArb hroot
obtain ⟨t, ht1, ht2, ht3, ht4, ht5⟩ := exists_rtree hrK hSU A
have hl := ht4 (noSteinerLeaf_of_minimal hrK hSU hmin A)
have hb := DSTCert.dst_tree_bound_WA y e₁ e₂ Z hZ h t ht1 hl
rw [ht2, ht3, ht5 y] at hb
exact hb.trans (fa_dst_W hrK hSU A h.1)
/-- The middle inequality of the proof of `thm:fa-dst`, times `(1 + y_j)^{n_U}`:
for a minimum Steiner set and each certificate `j` of prop:fa-dst-certs. The factor cancels:
the paper's denominator is `(1 + y_j)^{s + r_0}` and `n_U = s + r_0`, so the statement is
`c_{Z_j} e_{2,j} e_{1,j}^s e_{2,j}^p ≤ W_S(y_j)` with `s = |S|` and `p = |K|`. -/
theorem fa_dst_WS_minimum (hrK : r ∉ K) (hSU : S ⊆ nonterm r K) (hS : Steiner G r K S)
(hleast : ∀ T ⊆ nonterm r K, Steiner G r K T → S.card ≤ T.card) (j : Fin 3) :
DSTCert.cZ (DSTCert.ZR j) (DSTCert.ZR_nonempty j) * (DSTCert.e₂ j : ℝ) *
(DSTCert.e₁ j : ℝ) ^ S.card * (DSTCert.e₂ j : ℝ) ^ K.card ≤
WS G r K S (DSTCert.y j : ℝ) := by
obtain ⟨hroot, hmin⟩ := minimum_steiner_rooted_minimal hSU hS hleast
have h := fa_dst_WS_cert hrK hSU hroot hmin (DSTCert.ZR_nonempty j)
((DSTCert.dst_certs_exact).1 j)
calc DSTCert.cZ (DSTCert.ZR j) (DSTCert.ZR_nonempty j) * (DSTCert.e₂ j : ℝ) *
(DSTCert.e₁ j : ℝ) ^ S.card * (DSTCert.e₂ j : ℝ) ^ K.card
= DSTCert.cZ (DSTCert.ZR j) (DSTCert.ZR_nonempty j) * (DSTCert.e₁ j : ℝ) ^ S.card *
(DSTCert.e₂ j : ℝ) ^ (K.card + 1) := by ring
_ ≤ _ := h
/-! ### Examples: seven small instances E1–E7, root `0` -/
namespace Examples
/-- The digraph on `Fin n` whose arcs are exactly the listed pairs `(a, b)`, read as `a → b`. -/
abbrev ofArcs {n : ℕ} (L : List (Fin n × Fin n)) : Digraph (Fin n) := ⟨fun a b => (a, b) ∈ L⟩
/-- E1: `r, v, k = 0, 1, 2`; arcs `r → v`, `v → k`. -/
abbrev G1 : Digraph (Fin 3) := ofArcs [(0, 1), (1, 2)]
/-- E2: E1 plus the arc `r → k`. -/
abbrev G2 : Digraph (Fin 3) := ofArcs [(0, 1), (1, 2), (0, 2)]
/-- E3: `r, v, k₁, k₂ = 0, 1, 2, 3`; arcs `r → v`, `v → k₁`, `v → k₂`, `k₁ → k₂`, `k₂ → k₁`. -/
abbrev G3 : Digraph (Fin 4) := ofArcs [(0, 1), (1, 2), (1, 3), (2, 3), (3, 2)]
/-- E4: `r, v, a, k₁, k₂ = 0, 1, 2, 3, 4`; arcs `r → v`, `v → a`, `a → k₁`, `a → k₂`, `k₁ → k₂`,
`k₂ → k₁`. -/
abbrev G4 : Digraph (Fin 5) := ofArcs [(0, 1), (1, 2), (2, 3), (2, 4), (3, 4), (4, 3)]
/-- E5: `r, v, k₁, k₂ = 0, 1, 2, 3`; arcs `r → v`, `v → k₁`, `k₁ → k₂`. -/
abbrev G5 : Digraph (Fin 4) := ofArcs [(0, 1), (1, 2), (2, 3)]
/-- E6: `r, v, k₁, k₂, k₃ = 0, 1, 2, 3, 4`; arcs `r → v`, `v → k₁`, `k₁ → k₂`, `k₁ → k₃`. -/
abbrev G6 : Digraph (Fin 5) := ofArcs [(0, 1), (1, 2), (2, 3), (2, 4)]
/-- E7: `r, v, k, u = 0, 1, 2, 3`; arcs `r → v`, `v → k`; `u` has no arcs. -/
abbrev G7 : Digraph (Fin 4) := ofArcs [(0, 1), (1, 2)]
/-- E1's arborescence: `par v = r`, `par k = v` (`par r = r` is unused). -/
def A1 : OutArb G1 0 (Kbar 0 {2} {1}) where
par := ![0, 0, 1]
height := ![0, 1, 2]
par_mem := by decide
par_adj := by decide
height_lt := by decide
/-- An arborescence of E2 with a Steiner leaf: `par v = par k = r` (it uses the arc `r → k`). -/
def A2 : OutArb G2 0 (Kbar 0 {2} {1}) where
par := ![0, 0, 0]
height := ![0, 1, 1]
par_mem := by decide
par_adj := by decide
height_lt := by decide
/-- E3's arborescence: `par v = r`, `par k₁ = par k₂ = v`. -/
def A3 : OutArb G3 0 (Kbar 0 {2, 3} {1}) where
par := ![0, 0, 1, 1]
height := ![0, 1, 2, 2]
par_mem := by decide
par_adj := by decide
height_lt := by decide
/-- E4's arborescence: `par v = r`, `par a = v`, `par k₁ = par k₂ = a`. -/
def A4 : OutArb G4 0 (Kbar 0 {3, 4} {1, 2}) where
par := ![0, 0, 1, 2, 2]
height := ![0, 1, 2, 3, 3]
par_mem := by decide
par_adj := by decide
height_lt := by decide
theorem ex1_psi : PsiG A1 ∅ = 1 ∧ PsiG A1 {1} = 0 := ⟨by decide, by decide⟩
/-- The hypothesis `hGA` of `fa_dst_point_eq` for E1, at `X = ∅` and at `X = {1}`. -/
theorem ex1_hGA :
(∀ a ∈ Kbar (0 : Fin 3) {2} ∅, ∀ b ∈ Kbar (0 : Fin 3) {2} ∅,
G1.Adj a b ↔ (b ≠ 0 ∧ A1.par b = a)) ∧
(∀ a ∈ Kbar (0 : Fin 3) {2} {1}, ∀ b ∈ Kbar (0 : Fin 3) {2} {1},
G1.Adj a b ↔ (b ≠ 0 ∧ A1.par b = a)) := by
exact ⟨by simp only [G1, ofArcs]; decide, by simp only [G1, ofArcs]; decide⟩
theorem ex1_g : gDST G1 0 {2} ∅ = 1 ∧ gDST G1 0 {2} {1} = 0 := by
have h0 : (0 : Fin 3) ∉ ({2} : Finset (Fin 3)) := by decide
have hS : ({1} : Finset (Fin 3)) ⊆ nonterm (0 : Fin 3) {2} := by decide
refine ⟨?_, ?_⟩
· rw [fa_dst_point_eq h0 hS A1 (Finset.empty_subset _) ex1_hGA.1]
exact ex1_psi.1
· rw [fa_dst_point_eq h0 hS A1 (Finset.Subset.refl _) ex1_hGA.2]
exact ex1_psi.2
/-- In E1, `k` is not reachable from `r` inside `{r, k}`. -/
theorem ex1_not_steiner_empty : ¬ Steiner G1 0 {2} ∅ := by
intro h
have h2 := (h 2 (by decide)).mem_of_closed (Z := {0}) (by decide) (by decide)
exact absurd h2 (by decide)
theorem ex1_minimum : Steiner G1 0 {2} {1} ∧
∀ T ⊆ nonterm (0 : Fin 3) {2}, Steiner G1 0 {2} T → ({1} : Finset (Fin 3)).card ≤ T.card := by
refine ⟨?_, ?_⟩
· intro v hv
rw [Finset.mem_singleton] at hv
subst hv
have h1 : ReachIn G1 (Kbar 0 {2} {1}) 0 1 :=
(ReachIn.of_mem (by decide)).tail_adj (by decide) (by decide)
exact h1.tail_adj (by decide) (by decide)
· intro T _ hT
rw [Finset.card_singleton]
rcases Nat.eq_zero_or_pos T.card with h | h
· rw [Finset.card_eq_zero] at h
subst h
exact absurd hT ex1_not_steiner_empty
· exact h
/-- For E1: `hrK`, `hSU`, `hroot` and `hmin`, the hypotheses of `fa_dst_WS_cert` other than the
certificate (which `DSTCert.ZR_nonempty 0` and `(DSTCert.dst_certs_exact).1 0` supply). -/
theorem ex1_hyps : (0 : Fin 3) ∉ ({2} : Finset (Fin 3)) ∧
({1} : Finset (Fin 3)) ⊆ nonterm (0 : Fin 3) {2} ∧ Rooted G1 0 {2} {1} ∧
∀ T ⊆ ({1} : Finset (Fin 3)), Rooted G1 0 {2} T → T = {1} := by
refine ⟨by decide, by decide, ?_, ?_⟩
· intro v hv
have h1 : ReachIn G1 (Kbar 0 {2} {1}) 0 1 :=
(ReachIn.of_mem (by decide)).tail_adj (by decide) (by decide)
have hv' : v = 2 ∨ v = 1 := by simpa using hv
rcases hv' with rfl | rfl
· exact h1.tail_adj (by decide) (by decide)
· exact h1
· intro T hT hroot
rcases Finset.subset_singleton_iff.1 hT with rfl | rfl
· exact absurd (steiner_of_rooted hroot) ex1_not_steiner_empty
· rfl
theorem ex1_WS : ∀ y : ℝ, WS G1 0 {2} {1} y = y + 1 / 2 ∧ WAg A1 y = y + 1 / 2 := by
intro y
have hP : ({1} : Finset (Fin 3)).powerset = {∅, {1}} := by decide
have hne : (∅ : Finset (Fin 3)) ≠ {1} := by decide
constructor
· rw [WS, hP, Finset.sum_pair hne, ex1_g.1, ex1_g.2]
simp only [Finset.card_empty, Finset.card_singleton, pow_zero, pow_one, one_mul, mul_one]
ring
· rw [WAg, hP, Finset.sum_pair hne, ex1_psi.1, ex1_psi.2]
simp only [Finset.card_empty, Finset.card_singleton, pow_zero, pow_one, one_mul, mul_one]
ring
/-- The conclusion of `fa_dst_WS_cert` for E1 and certificate `0`. -/
theorem ex1_WS_cert :
DSTCert.cZ (DSTCert.ZR 0) (DSTCert.ZR_nonempty 0) *
(DSTCert.e₁ 0 : ℝ) ^ ({1} : Finset (Fin 3)).card *
(DSTCert.e₂ 0 : ℝ) ^ (({2} : Finset (Fin 3)).card + 1) ≤
WS G1 0 {2} {1} (DSTCert.y 0 : ℝ) :=
fa_dst_WS_cert ex1_hyps.1 ex1_hyps.2.1 ex1_hyps.2.2.1 ex1_hyps.2.2.2
(DSTCert.ZR_nonempty 0) ((DSTCert.dst_certs_exact).1 0)
/-- The conclusion of `fa_dst_WS_minimum` for E1 and `j = 0`. -/
theorem ex1_WS_minimum :
DSTCert.cZ (DSTCert.ZR 0) (DSTCert.ZR_nonempty 0) * (DSTCert.e₂ 0 : ℝ) *
(DSTCert.e₁ 0 : ℝ) ^ ({1} : Finset (Fin 3)).card *
(DSTCert.e₂ 0 : ℝ) ^ ({2} : Finset (Fin 3)).card ≤
WS G1 0 {2} {1} (DSTCert.y 0 : ℝ) :=
fa_dst_WS_minimum ex1_hyps.1 ex1_hyps.2.1 ex1_minimum.1 ex1_minimum.2 0
theorem ex2_g : gDST G2 0 {2} ∅ = 0 := by
apply gDST_eq_zero_of
intro v hv
have hv' : v = 0 ∨ v = 2 := by revert v; decide
rcases hv' with rfl | rfl
· exact ReachIn.of_mem (by decide)
· exact (ReachIn.of_mem (by decide)).tail_adj (by decide) (by decide)
/-- E2: `∅` is rooted, so `{1}` is not minimal among rooted sets, and `A2` has a Steiner leaf. -/
theorem ex2_leaf : Rooted G2 0 {2} ∅ ∧ ¬ NoSteinerLeafG A2 := by
refine ⟨?_, ?_⟩
· intro v hv
have hv' : v = 2 := by simpa using hv
subst hv'
exact (ReachIn.of_mem (by decide)).tail_adj (by decide) (by decide)
· unfold NoSteinerLeafG
decide
theorem ex3_g : gDST G3 0 {2, 3} ∅ = 1 := by
have hD : Dset G3 0 {2, 3} ∅ = {2, 3} := by
refine (Dset_eq_of (R := {0}) (by decide) ?_ (by decide)).trans (by decide)
intro v hv
rw [Finset.mem_singleton.1 hv]
exact ReachIn.of_mem (by decide)
rw [gDST, hD, sourceComps_eq_single (G := G3) (D := {2, 3}) ⟨2, by decide⟩
(strong_of_adj (by decide)), Finset.card_singleton]
theorem ex3_psi : PsiG A3 ∅ = 2 := by decide
/-- E4 meets `hrK` and `hSU` (and `A4` is an arborescence), but `W_S(-2) < W_A(-2)`. -/
theorem ex4_strict : (0 : Fin 5) ∉ ({3, 4} : Finset (Fin 5)) ∧
({1, 2} : Finset (Fin 5)) ⊆ nonterm (0 : Fin 5) {3, 4} ∧
WS G4 0 {3, 4} {1, 2} (-2) < WAg A4 (-2) := by
refine ⟨by decide, by decide, ?_⟩
have g0 : gDST G4 0 {3, 4} ∅ = 1 := by
have hD : Dset G4 0 {3, 4} ∅ = {3, 4} := by
refine (Dset_eq_of (R := {0}) (by decide) ?_ (by decide)).trans (by decide)
intro v hv
rw [Finset.mem_singleton.1 hv]
exact ReachIn.of_mem (by decide)
rw [gDST, hD, sourceComps_eq_single (G := G4) (D := {3, 4}) ⟨3, by decide⟩
(strong_of_adj (by decide)), Finset.card_singleton]
have g1 : gDST G4 0 {3, 4} {1} = 1 := by
have hD : Dset G4 0 {3, 4} {1} = {3, 4} := by
refine (Dset_eq_of (R := {0, 1}) (by decide) ?_ (by decide)).trans (by decide)
intro v hv
have hv' : v = 0 ∨ v = 1 := by simpa using hv
rcases hv' with rfl | rfl
· exact ReachIn.of_mem (by decide)
· exact (ReachIn.of_mem (by decide)).tail_adj (by decide) (by decide)
rw [gDST, hD, sourceComps_eq_single (G := G4) (D := {3, 4}) ⟨3, by decide⟩
(strong_of_adj (by decide)), Finset.card_singleton]
have g2 : gDST G4 0 {3, 4} {2} ≤ 1 := by
have h := fa_dst_point (X := {2}) (by decide) (by decide) A4 (by decide)
have hp : PsiG A4 {2} = 1 := by decide
omega
have g3 : gDST G4 0 {3, 4} {1, 2} = 0 := by
apply gDST_eq_zero_of
intro v hv
have h1 : ReachIn G4 (Kbar 0 {3, 4} {1, 2}) 0 1 :=
(ReachIn.of_mem (by decide)).tail_adj (by decide) (by decide)
have h2 : ReachIn G4 (Kbar 0 {3, 4} {1, 2}) 0 2 := h1.tail_adj (by decide) (by decide)
have hv' : v = 0 ∨ v = 1 ∨ v = 2 ∨ v = 3 ∨ v = 4 := by revert v; decide
rcases hv' with rfl | rfl | rfl | rfl | rfl
· exact ReachIn.of_mem (by decide)
· exact h1
· exact h2
· exact h2.tail_adj (by decide) (by decide)
· exact h2.tail_adj (by decide) (by decide)
have p0 : PsiG A4 ∅ = 2 := by decide
have p1 : PsiG A4 {1} = 2 := by decide
have p2 : PsiG A4 {2} = 1 := by decide
have p3 : PsiG A4 {1, 2} = 0 := by decide
have c12 : ({1, 2} : Finset (Fin 5)).card = 2 := by decide
have hP : ({1, 2} : Finset (Fin 5)).powerset = {∅, {1}, {2}, {1, 2}} := by decide
have s1 : ∀ f : Finset (Fin 5) → ℝ,
∑ X ∈ ({1, 2} : Finset (Fin 5)).powerset, f X = f ∅ + f {1} + f {2} + f {1, 2} := by
intro f
rw [hP, Finset.sum_insert, Finset.sum_insert, Finset.sum_insert, Finset.sum_singleton]
· ring
all_goals decide
have hg2 : (1 / 2 : ℝ) ^ 1 ≤ (1 / 2 : ℝ) ^ gDST G4 0 {3, 4} {2} :=
pow_le_pow_of_le_one (by norm_num) (by norm_num) g2
rw [WS, WAg, s1, s1]
simp only [Finset.card_empty, Finset.card_singleton, c12, g0, g1, g3, p0, p1, p2, p3]
generalize (1 / 2 : ℝ) ^ gDST G4 0 {3, 4} {2} = a at hg2 ⊢
norm_num at hg2 ⊢
linarith
theorem ex5_g : gDST G5 0 {2, 3} ∅ = 1 := by
rw [fa_dst_point_eq (G := G5) (r := 0) (K := {2, 3}) (S := {1}) (X := ∅) (by decide)
(by decide) ⟨![0, 0, 1, 2], ![0, 1, 2, 3], by decide, by decide, by decide⟩
(Finset.empty_subset _) (by decide)]
decide
theorem ex6_g : gDST G6 0 {2, 3, 4} ∅ = 1 := by
rw [fa_dst_point_eq (G := G6) (r := 0) (K := {2, 3, 4}) (S := {1}) (X := ∅) (by decide)
(by decide) ⟨![0, 0, 1, 2, 2], ![0, 1, 2, 3, 3], by decide, by decide, by decide⟩
(Finset.empty_subset _) (by decide)]
decide
theorem ex7_reachPart :
reachPart G7 0 {2} {1, 3} = {1} ∧ Steiner G7 0 {2} {1, 3} ∧ ¬ Rooted G7 0 {2} {1, 3} ∧
Rooted G7 0 {2} {1} := by
have h1 : ReachIn G7 (Kbar 0 {2} {1, 3}) 0 1 :=
(ReachIn.of_mem (by decide)).tail_adj (by decide) (by decide)
have h3 : ¬ ReachIn G7 (Kbar 0 {2} {1, 3}) 0 3 := fun h =>
absurd (h.mem_of_closed (Z := {0, 1, 2}) (by decide) (by decide)) (by decide)
refine ⟨?_, ?_, ?_, ?_⟩
· ext v
simp only [reachPart, Finset.mem_filter]
constructor
· rintro ⟨hv, hr⟩
have hv' : v = 1 ∨ v = 3 := by simpa using hv
rcases hv' with rfl | rfl
· decide
· exact absurd hr h3
· intro hv
rw [Finset.mem_singleton.1 hv]
exact ⟨by decide, h1⟩
· intro v hv
rw [Finset.mem_singleton.1 hv]
exact h1.tail_adj (by decide) (by decide)
· intro h
exact h3 (h 3 (by decide))
· intro v hv
have k1 : ReachIn G7 (Kbar 0 {2} {1}) 0 1 :=
(ReachIn.of_mem (by decide)).tail_adj (by decide) (by decide)
have hv' : v = 2 ∨ v = 1 := by simpa using hv
rcases hv' with rfl | rfl
· exact k1.tail_adj (by decide) (by decide)
· exact k1
/-- `NoSteinerLeafG` on data: it holds for `A1` and `A4` (and fails for `A2`, `ex2_leaf`). -/
theorem ex_noLeaf : NoSteinerLeafG A1 ∧ NoSteinerLeafG A4 := by
unfold NoSteinerLeafG
decide
end Examples
end MaxLeafFormal.DSTGraph
Back to top