MaxLeafFormal.PDGraph
Source file MaxLeafFormal/PDGraph.lean of the Lean project (how it is built).
Statements of the paper formalised here: Lemma D.11.18, Lemma D.11.19, Theorem 12.10, Proposition 12.11.
import MaxLeafFormal.PDRate
import MaxLeafFormal.MLSNec
import MaxLeafFormal.CDS
/-!
# Paired Domination: the graph argument and tightness
`lem:fa-pd-point`, the second claim of `lem:fa-pd-rate` and `prop:fa-pd-tight`.
-/
namespace MaxLeafFormal.PDGraph
open Finset SimpleGraph MaxLeafFormal.MLS MaxLeafFormal.PDRate
namespace Aux
theorem sqrt3_sq : Real.sqrt 3 ^ 2 = 3 := Real.sq_sqrt (by norm_num)
theorem sqrt3_gt_one : 1 < Real.sqrt 3 := by
nlinarith [Real.sqrt_nonneg 3, sqrt3_sq]
theorem ystar_pos : 0 < ystar := by
unfold ystar
linarith [sqrt3_gt_one]
theorem N_factor (y : ℝ) :
4 * y ^ 2 + y / 2 - 13 / 32 = 4 * (y - ystar) * (y - (-1 - 3 * Real.sqrt 3) / 16) := by
unfold ystar
linear_combination (9 / 64 : ℝ) * sqrt3_sq
end Aux
section General
variable {V : Type*} [Fintype V] [DecidableEq V]
/-- `und(X) = V \ N[X]`. -/
def und (G : SimpleGraph V) [DecidableRel G.Adj] (X : Finset V) : Finset V :=
univ \ CDS.closedNbhd G X
/-- The running-time exponent `g(X) = |und(X)|`; it ignores the size argument. -/
def pdG (G : SimpleGraph V) [DecidableRel G.Adj] : Finset V → ℕ → ℝ :=
fun X _ => ((und G X).card : ℝ)
/-- `W_S(y)` for the exponent `|und(X)|`. -/
noncomputable def pdW (G : SimpleGraph V) [DecidableRel G.Adj] (S : Finset V) (y : ℝ) : ℝ :=
W (pdG G) S S.card y
def IsDominating (G : SimpleGraph V) (S : Finset V) : Prop :=
∀ v, v ∈ S ∨ ∃ u ∈ S, G.Adj v u
/-- A paired dominating set: dominating, and `G[S]` has a perfect matching. -/
def IsPairedDom (G : SimpleGraph V) (S : Finset V) : Prop :=
IsDominating G S ∧ ∃ M : G.Subgraph, M.verts = (S : Set V) ∧ M.IsMatching
/-- An oriented perfect matching of `G[S]`, as a finite set of ordered pairs. -/
def IsPairing (G : SimpleGraph V) (S : Finset V) (P : Finset (V × V)) : Prop :=
(∀ q ∈ P, q.1 ∈ S ∧ q.2 ∈ S ∧ G.Adj q.1 q.2) ∧
∀ w ∈ S, ∃! q : V × V, q ∈ P ∧ (q.1 = w ∨ q.2 = w)
/-- Anchors: every vertex outside `S` gets a neighbour in `S`. -/
def IsAnchor (G : SimpleGraph V) (S : Finset V) (anc : V → V) : Prop :=
∀ v, v ∉ S → anc v ∈ S ∧ G.Adj v (anc v)
/-- `d_u`, the number of vertices anchored at `u`. -/
def ancDeg (S : Finset V) (anc : V → V) (u : V) : ℕ :=
(univ.filter (fun v => v ∉ S ∧ anc v = u)).card
/-- The right-hand side of the first inequality of `lem:fa-pd-point`. -/
def pdRhs (S : Finset V) (P : Finset (V × V)) (anc : V → V) (X : Finset V) : ℕ :=
(univ.filter (fun v => v ∉ S ∧ anc v ∉ X)).card +
2 * (P.filter (fun q => q.1 ∉ X ∧ q.2 ∉ X)).card
/-- `Ω_{uv}(y) = y² + y(2^{-d_u} + 2^{-d_v}) + 2^{-n_{uv}}`, `n_{uv} = 2 + d_u + d_v`. -/
noncomputable def Ωpair (y : ℝ) (du dv : ℕ) : ℝ :=
y ^ 2 + y * ((2:ℝ) ^ (-(du : ℝ)) + (2:ℝ) ^ (-(dv : ℝ))) + (2:ℝ) ^ (-((2 + du + dv : ℕ) : ℝ))
theorem pdW_eq (G : SimpleGraph V) [DecidableRel G.Adj] (S : Finset V) (y : ℝ) :
pdW G S y = ∑ X ∈ S.powerset, y ^ X.card * (2:ℝ) ^ (-((und G X).card : ℝ)) := by
rfl
namespace Aux
theorem two_rpow_neg_nat (m : ℕ) : (2:ℝ) ^ (-(m:ℝ)) = (1 / 2 : ℝ) ^ m := by
rw [Real.rpow_neg (by norm_num), Real.rpow_natCast, one_div, inv_pow]
/-- Subsets of a disjoint union are pairs of subsets. -/
theorem sum_powerset_union {W β : Type*} [DecidableEq W] [AddCommMonoid β] (A C : Finset W)
(hAC : Disjoint A C) (f : Finset W → Finset W → β) :
∑ X ∈ (A ∪ C).powerset, f (X ∩ A) (X ∩ C) = ∑ Z ∈ A.powerset, ∑ Y ∈ C.powerset, f Z Y := by
rw [← sum_product' (f := f)]
refine sum_nbij' (fun X => (X ∩ A, X ∩ C)) (fun p => p.1 ∪ p.2) ?_ ?_ ?_ ?_ ?_
· intro X _
simp only [mem_coe, mem_product, mem_powerset]
exact ⟨inter_subset_right, inter_subset_right⟩
· intro p hp
simp only [mem_coe, mem_product, mem_powerset] at hp ⊢
exact union_subset_union hp.1 hp.2
· intro X hX
simp only [mem_coe, mem_powerset] at hX
simp only
rw [← inter_union_distrib_left, inter_eq_left.2 hX]
· intro p hp
simp only [mem_coe, mem_product, mem_powerset] at hp
obtain ⟨h1, h2⟩ := hp
refine Prod.ext ?_ ?_
· ext x
simp only [mem_inter, mem_union]
constructor
· rintro ⟨hx | hx, hxA⟩
· exact hx
· exact absurd (h2 hx) (disjoint_left.1 hAC hxA)
· intro hx; exact ⟨Or.inl hx, h1 hx⟩
· ext x
simp only [mem_inter, mem_union]
constructor
· rintro ⟨hx | hx, hxC⟩
· exact absurd hxC (disjoint_left.1 hAC (h1 hx))
· exact hx
· intro hx; exact ⟨Or.inr hx, h2 hx⟩
· intro X _
rfl
/-- Sums over subsets of a disjoint union of blocks factor over the blocks. -/
theorem sum_powerset_blocks {W ι β : Type*} [DecidableEq W] [DecidableEq ι] [CommSemiring β]
(s : Finset ι) (B : ι → Finset W) (hdisj : ∀ i ∈ s, ∀ j ∈ s, i ≠ j → Disjoint (B i) (B j))
(F : ι → Finset W → β) :
∑ X ∈ (s.biUnion B).powerset, ∏ i ∈ s, F i (X ∩ B i)
= ∏ i ∈ s, ∑ Z ∈ (B i).powerset, F i Z := by
induction s using Finset.induction_on with
| empty => simp
| @insert a s ha ih =>
have hdisj' : ∀ i ∈ s, ∀ j ∈ s, i ≠ j → Disjoint (B i) (B j) := fun i hi j hj =>
hdisj i (mem_insert_of_mem hi) j (mem_insert_of_mem hj)
have hAC : Disjoint (B a) (s.biUnion B) := by
rw [disjoint_biUnion_right]
intro i hi
exact hdisj a (mem_insert_self a s) i (mem_insert_of_mem hi) (fun h => ha (h ▸ hi))
calc ∑ X ∈ ((insert a s).biUnion B).powerset, ∏ i ∈ insert a s, F i (X ∩ B i)
= ∑ X ∈ (B a ∪ s.biUnion B).powerset,
F a (X ∩ B a) * ∏ i ∈ s, F i ((X ∩ s.biUnion B) ∩ B i) := by
rw [biUnion_insert]
refine sum_congr rfl fun X _ => ?_
rw [prod_insert ha]
congr 1
refine prod_congr rfl fun i hi => ?_
rw [inter_assoc, inter_eq_right.2 (subset_biUnion_of_mem B hi)]
_ = ∑ Z ∈ (B a).powerset, ∑ Y ∈ (s.biUnion B).powerset,
F a Z * ∏ i ∈ s, F i (Y ∩ B i) :=
sum_powerset_union (B a) (s.biUnion B) hAC
(fun Z Y => F a Z * ∏ i ∈ s, F i (Y ∩ B i))
_ = ∏ i ∈ insert a s, ∑ Z ∈ (B i).powerset, F i Z := by
rw [prod_insert ha, ← ih hdisj', sum_mul_sum]
end Aux
/-- The unique pair of a pairing that contains a vertex is determined by that vertex. -/
theorem IsPairing.eq_of_mem {G : SimpleGraph V} {S : Finset V} {P : Finset (V × V)}
(hP : IsPairing G S P) {q q' : V × V} (hq : q ∈ P) (hq' : q' ∈ P) {w : V}
(hw : q.1 = w ∨ q.2 = w) (hw' : q'.1 = w ∨ q'.2 = w) : q = q' := by
have hwS : w ∈ S := by
rcases hw with h | h
· exact h ▸ (hP.1 q hq).1
· exact h ▸ (hP.1 q hq).2.1
exact (hP.2 w hwS).unique ⟨hq, hw⟩ ⟨hq', hw'⟩
theorem IsPairing.fst_ne_snd {G : SimpleGraph V} {S : Finset V} {P : Finset (V × V)}
(hP : IsPairing G S P) {q : V × V} (hq : q ∈ P) : q.1 ≠ q.2 :=
G.ne_of_adj (hP.1 q hq).2.2
/-- The pairs of a pairing partition `S`: sums over `S` split into sums over pairs. -/
theorem IsPairing.sum_ends {G : SimpleGraph V} {S : Finset V} {P : Finset (V × V)}
(hP : IsPairing G S P) {β : Type*} [AddCommMonoid β] (f : V → β) :
∑ q ∈ P, (f q.1 + f q.2) = ∑ w ∈ S, f w := by
have hS : S = P.biUnion (fun q => ({q.1, q.2} : Finset V)) := by
ext w
simp only [mem_biUnion, mem_insert, mem_singleton]
constructor
· intro hw
obtain ⟨q, ⟨hq, hqw⟩, -⟩ := hP.2 w hw
exact ⟨q, hq, by rcases hqw with h | h <;> [left; right] <;> exact h.symm⟩
· rintro ⟨q, hq, h | h⟩
· exact h ▸ (hP.1 q hq).1
· exact h ▸ (hP.1 q hq).2.1
rw [hS, sum_biUnion]
· refine sum_congr rfl fun q hq => ?_
rw [sum_pair (hP.fst_ne_snd hq)]
· intro q hq q' hq' hne
simp only [Function.onFun]
rw [Finset.disjoint_left]
intro w hw hw'
simp only [mem_insert, mem_singleton] at hw hw'
exact hne (hP.eq_of_mem hq hq' (by rcases hw with h | h <;> [left; right] <;> exact h.symm)
(by rcases hw' with h | h <;> [left; right] <;> exact h.symm))
/-- Every perfect matching `M` of `G[S]` (Mathlib form) is listed by a pairing `P`
with exactly the same edges. -/
theorem pairing_of_matching (G : SimpleGraph V) (S : Finset V) (M : G.Subgraph)
(hMv : M.verts = (S : Set V)) (hM : M.IsMatching) :
∃ P : Finset (V × V), IsPairing G S P ∧ ∀ a b, M.Adj a b ↔ ((a, b) ∈ P ∨ (b, a) ∈ P) := by
classical
let e := Fintype.equivFin V
let P : Finset (V × V) := (univ ×ˢ univ).filter (fun q => M.Adj q.1 q.2 ∧ e q.1 < e q.2)
have hmemP : ∀ a b, (a, b) ∈ P ↔ M.Adj a b ∧ e a < e b := by
intro a b; simp [P]
have hvS : ∀ v, v ∈ M.verts ↔ v ∈ S := by
intro v; rw [hMv]; rfl
refine ⟨P, ⟨?_, ?_⟩, ?_⟩
· rintro ⟨a, b⟩ hq
rw [hmemP] at hq
exact ⟨(hvS a).1 (M.edge_vert hq.1), (hvS b).1 (M.edge_vert hq.1.symm), M.adj_sub hq.1⟩
· intro w hw
obtain ⟨w', hww', huniq⟩ := hM ((hvS w).2 hw)
have hne : w ≠ w' := G.ne_of_adj (M.adj_sub hww')
have hene : e w ≠ e w' := fun h => hne (e.injective h)
rcases lt_or_gt_of_ne hene with hlt | hlt
· refine ⟨(w, w'), ⟨(hmemP w w').2 ⟨hww', hlt⟩, Or.inl rfl⟩, ?_⟩
rintro ⟨a, b⟩ ⟨hq, h | h⟩
· simp only at h; subst h
rw [hmemP] at hq
rw [huniq b hq.1]
· simp only at h; subst h
rw [hmemP] at hq
have := huniq a hq.1.symm
subst this
exact absurd (hq.2.trans hlt) (lt_irrefl _)
· refine ⟨(w', w), ⟨(hmemP w' w).2 ⟨hww'.symm, hlt⟩, Or.inr rfl⟩, ?_⟩
rintro ⟨a, b⟩ ⟨hq, h | h⟩
· simp only at h; subst h
rw [hmemP] at hq
have := huniq b hq.1
subst this
exact absurd (hq.2.trans hlt) (lt_irrefl _)
· simp only at h; subst h
rw [hmemP] at hq
rw [huniq a hq.1.symm]
· intro a b
rw [hmemP, hmemP]
constructor
· intro h
have hne : e a ≠ e b := fun h' => G.ne_of_adj (M.adj_sub h) (e.injective h')
rcases lt_or_gt_of_ne hne with hlt | hlt
· exact Or.inl ⟨h, hlt⟩
· exact Or.inr ⟨h.symm, hlt⟩
· rintro (h | h)
· exact h.1
· exact h.1.symm
/-- Every pairing `P` lists the edges of a perfect matching `M` of `G[S]` (Mathlib form). -/
theorem matching_of_pairing (G : SimpleGraph V) (S : Finset V) (P : Finset (V × V))
(hP : IsPairing G S P) :
∃ M : G.Subgraph, M.verts = (S : Set V) ∧ M.IsMatching ∧
∀ a b, M.Adj a b ↔ ((a, b) ∈ P ∨ (b, a) ∈ P) := by
let M : G.Subgraph :=
{ verts := (S : Set V)
Adj := fun a b => (a, b) ∈ P ∨ (b, a) ∈ P
adj_sub := by
rintro a b (h | h)
· exact (hP.1 _ h).2.2
· exact (hP.1 _ h).2.2.symm
edge_vert := by
rintro a b (h | h)
· exact (hP.1 _ h).1
· exact (hP.1 _ h).2.1
symm := ⟨fun a b h => h.symm⟩ }
refine ⟨M, rfl, ?_, fun a b => Iff.rfl⟩
intro v hv
have hvS : v ∈ S := hv
obtain ⟨⟨a, b⟩, ⟨hq, hqv⟩, -⟩ := hP.2 v hvS
have hab : a ≠ b := hP.fst_ne_snd hq
rcases hqv with h | h
· simp only at h; subst h
refine ⟨b, Or.inl hq, ?_⟩
rintro w (hw | hw)
· exact congrArg Prod.snd (hP.eq_of_mem hw hq (Or.inl rfl) (Or.inl rfl))
· have := hP.eq_of_mem hw hq (Or.inr rfl) (Or.inl rfl)
simp only [Prod.mk.injEq] at this
exact absurd this.2 hab
· simp only at h; subst h
refine ⟨a, Or.inr hq, ?_⟩
rintro w (hw | hw)
· have := hP.eq_of_mem hw hq (Or.inl rfl) (Or.inr rfl)
simp only [Prod.mk.injEq] at this
exact absurd this.1.symm hab
· exact congrArg Prod.fst (hP.eq_of_mem hw hq (Or.inr rfl) (Or.inr rfl))
theorem exists_anchor (G : SimpleGraph V) (S : Finset V) (hS : IsDominating G S) :
∃ anc : V → V, IsAnchor G S anc := by
classical
refine ⟨fun v => if h : v ∈ S then v else Classical.choose ((hS v).resolve_left h), ?_⟩
intro v hv
simp only [dif_neg hv]
exact Classical.choose_spec ((hS v).resolve_left hv)
/-- `∑_{u ∈ S} (number of outside vertices anchored at u satisfying p)`. -/
theorem ancDeg.sum_eq {G : SimpleGraph V} {S : Finset V} {anc : V → V} (ha : IsAnchor G S anc)
(T : Finset V) (hT : T ⊆ S) :
∑ u ∈ T, ancDeg S anc u = (univ.filter (fun v => v ∉ S ∧ anc v ∈ T)).card := by
rw [card_eq_sum_card_fiberwise (f := anc) (t := T)]
· refine sum_congr rfl fun u hu => ?_
unfold ancDeg
congr 1
ext v
simp only [mem_filter, mem_univ, true_and]
constructor
· rintro ⟨hv, rfl⟩; exact ⟨⟨hv, hu⟩, rfl⟩
· rintro ⟨⟨hv, -⟩, rfl⟩; exact ⟨hv, rfl⟩
· intro v hv
simp at hv
exact hv.2
/-- `∑_{uv ∈ M} n_{uv} = n`. -/
theorem card_eq_sum_pairs (G : SimpleGraph V) (S : Finset V) (P : Finset (V × V))
(hP : IsPairing G S P) (anc : V → V) (ha : IsAnchor G S anc) :
Fintype.card V = ∑ q ∈ P, (2 + ancDeg S anc q.1 + ancDeg S anc q.2) := by
have h1 : ∑ q ∈ P, (2 + ancDeg S anc q.1 + ancDeg S anc q.2)
= ∑ q ∈ P, ((1 + ancDeg S anc q.1) + (1 + ancDeg S anc q.2)) :=
sum_congr rfl fun q _ => by ring
rw [h1, hP.sum_ends (fun w => 1 + ancDeg S anc w), sum_add_distrib, ancDeg.sum_eq ha S
subset_rfl, sum_const, smul_eq_mul, mul_one]
have h2 : (univ.filter (fun v => v ∉ S ∧ anc v ∈ S)) = univ.filter (fun v => v ∉ S) := by
ext v
simp only [mem_filter, mem_univ, true_and]
exact ⟨fun h => h.1, fun h => ⟨h, (ha v h).1⟩⟩
rw [h2, ← card_univ, ← card_filter_add_card_filter_not (s := univ) (fun v => v ∈ S)]
congr 1
rw [filter_mem_eq_inter, univ_inter]
namespace Aux
theorem card_inter_pair {W : Type*} [DecidableEq W] (X : Finset W) {a b : W} (hab : a ≠ b) :
(X ∩ {a, b}).card = (if a ∈ X then 1 else 0) + (if b ∈ X then 1 else 0) := by
rw [inter_comm, ← filter_mem_eq_inter, card_filter, sum_pair hab]
/-- The exact factorization of `lem:fa-pd-point`. -/
theorem point_factor (G : SimpleGraph V) (S : Finset V)
(P : Finset (V × V)) (hP : IsPairing G S P) (anc : V → V) (ha : IsAnchor G S anc) (y : ℝ) :
∑ X ∈ S.powerset, y ^ X.card * (2:ℝ) ^ (-(pdRhs S P anc X : ℝ))
= ∏ q ∈ P, Ωpair y (ancDeg S anc q.1) (ancDeg S anc q.2) := by
set d := ancDeg S anc with hd
let e : V × V → Finset V := fun q => {q.1, q.2}
let r : V × V → Finset V → ℕ := fun q Z =>
(if q.1 ∉ Z then d q.1 else 0) + (if q.2 ∉ Z then d q.2 else 0) +
(if q.1 ∉ Z ∧ q.2 ∉ Z then 2 else 0)
let F : V × V → Finset V → ℝ := fun q Z => y ^ Z.card * (1 / 2 : ℝ) ^ r q Z
have hS : S = P.biUnion e := by
ext w
simp only [e, mem_biUnion, mem_insert, mem_singleton]
constructor
· intro hw
obtain ⟨q, ⟨hq, hqw⟩, -⟩ := hP.2 w hw
exact ⟨q, hq, by rcases hqw with h | h <;> [left; right] <;> exact h.symm⟩
· rintro ⟨q, hq, h | h⟩
· exact h ▸ (hP.1 q hq).1
· exact h ▸ (hP.1 q hq).2.1
have hdisj : ∀ i ∈ P, ∀ j ∈ P, i ≠ j → Disjoint (e i) (e j) := by
intro q hq q' hq' hne
rw [Finset.disjoint_left]
intro w hw hw'
simp only [e, mem_insert, mem_singleton] at hw hw'
exact hne (hP.eq_of_mem hq hq' (by rcases hw with h | h <;> [left; right] <;> exact h.symm)
(by rcases hw' with h | h <;> [left; right] <;> exact h.symm))
-- each term is a product over the pairs
have hterm : ∀ X ∈ S.powerset, y ^ X.card * (2:ℝ) ^ (-(pdRhs S P anc X : ℝ))
= ∏ q ∈ P, F q (X ∩ e q) := by
intro X hX
rw [mem_powerset] at hX
have hcard : ∑ q ∈ P, (X ∩ e q).card = X.card := by
have h1 : ∑ q ∈ P, (X ∩ e q).card
= ∑ q ∈ P, ((if q.1 ∈ X then 1 else 0) + (if q.2 ∈ X then 1 else 0)) :=
sum_congr rfl fun q hq => card_inter_pair X (hP.fst_ne_snd hq)
have hs : ∑ q ∈ P, ((if q.1 ∈ X then 1 else 0) + (if q.2 ∈ X then 1 else 0))
= ∑ w ∈ S, (if w ∈ X then 1 else 0) := hP.sum_ends (fun w => if w ∈ X then 1 else 0)
rw [h1, hs, ← card_filter]
congr 1
ext w
simp only [mem_filter]
exact ⟨fun h => h.2, fun h => ⟨hX h, h⟩⟩
have hr : ∑ q ∈ P, r q (X ∩ e q) = pdRhs S P anc X := by
have hr1 : ∀ q ∈ P, r q (X ∩ e q) = ((if q.1 ∉ X then d q.1 else 0) +
(if q.2 ∉ X then d q.2 else 0)) + (if q.1 ∉ X ∧ q.2 ∉ X then 2 else 0) := by
intro q _
simp only [r, e, mem_inter, mem_insert, mem_singleton, true_or, or_true, and_true]
have hs : ∑ q ∈ P, ((if q.1 ∉ X then d q.1 else 0) + (if q.2 ∉ X then d q.2 else 0))
= ∑ w ∈ S, (if w ∉ X then d w else 0) := hP.sum_ends (fun w => if w ∉ X then d w else 0)
rw [sum_congr rfl hr1, sum_add_distrib, hs, ← sum_filter, ← sum_filter, sum_const,
smul_eq_mul, hd, ancDeg.sum_eq ha _ (filter_subset _ _)]
unfold pdRhs
have hf : (univ.filter (fun v => v ∉ S ∧ anc v ∈ S.filter (fun w => w ∉ X)))
= univ.filter (fun v => v ∉ S ∧ anc v ∉ X) := by
ext v
simp only [mem_filter, mem_univ, true_and]
constructor
· rintro ⟨hv, -, h⟩; exact ⟨hv, h⟩
· rintro ⟨hv, h⟩; exact ⟨hv, (ha v hv).1, h⟩
rw [hf]
ring
simp only [F]
rw [prod_mul_distrib, prod_pow_eq_pow_sum, prod_pow_eq_pow_sum, hcard, hr,
two_rpow_neg_nat]
-- each factor is `Ωpair`
have hfactor : ∀ q ∈ P, ∑ Z ∈ (e q).powerset, F q Z = Ωpair y (d q.1) (d q.2) := by
intro q hq
have hne : q.1 ≠ q.2 := hP.fst_ne_snd hq
have hnot : q.1 ∉ ({q.2} : Finset V) := by simpa using hne
simp only [e]
have h0 : (∅ : Finset V) ≠ {q.2} := (singleton_nonempty _).ne_empty.symm
have hps : ({q.2} : Finset V).powerset = {∅, {q.2}} := by
ext Z; simp [Finset.subset_singleton_iff]
rw [sum_powerset_insert hnot, hps, sum_pair h0, sum_pair h0]
unfold Ωpair
rw [two_rpow_neg_nat, two_rpow_neg_nat, two_rpow_neg_nat]
simp [F, r, hne, hne.symm, card_pair hne]
ring
rw [sum_congr rfl hterm, hS, sum_powerset_blocks P e hdisj F]
exact prod_congr rfl hfactor
end Aux
/-- `lem:fa-pd-point`. -/
theorem pd_point (G : SimpleGraph V) [DecidableRel G.Adj] (S : Finset V)
(P : Finset (V × V)) (hP : IsPairing G S P) (anc : V → V) (ha : IsAnchor G S anc) :
(∀ X ⊆ S, (und G X).card ≤ pdRhs S P anc X) ∧
∀ y : ℝ, 0 ≤ y →
∏ q ∈ P, Ωpair y (ancDeg S anc q.1) (ancDeg S anc q.2) ≤ pdW G S y := by
have h1 : ∀ X ⊆ S, (und G X).card ≤ pdRhs S P anc X := by
intro X _
set A := univ.filter (fun v => v ∉ S ∧ anc v ∉ X)
set Pf := P.filter (fun q => q.1 ∉ X ∧ q.2 ∉ X)
have hsub : und G X ⊆ A ∪ Pf.biUnion (fun q => ({q.1, q.2} : Finset V)) := by
intro v hv
simp only [und, mem_sdiff, mem_univ, true_and, CDS.mem_closedNbhd, not_or, not_exists,
not_and] at hv
by_cases hvS : v ∈ S
· obtain ⟨q, ⟨hq, hqv⟩, -⟩ := hP.2 v hvS
have hadj := (hP.1 q hq).2.2
have hboth : q.1 ∉ X ∧ q.2 ∉ X := by
rcases hqv with h | h
· rw [h] at hadj ⊢
exact ⟨hv.1, fun h2 => hv.2 _ h2 hadj.symm⟩
· rw [h] at hadj ⊢
exact ⟨fun h2 => hv.2 _ h2 hadj, hv.1⟩
refine mem_union_right _ (mem_biUnion.2 ⟨q, mem_filter.2 ⟨hq, hboth⟩, ?_⟩)
rcases hqv with h | h
· rw [← h]; exact mem_insert_self _ _
· rw [← h]; exact mem_insert_of_mem (mem_singleton_self _)
· refine mem_union_left _ (mem_filter.2 ⟨mem_univ _, hvS, fun h => ?_⟩)
exact hv.2 _ h (ha v hvS).2.symm
have hB : (Pf.biUnion (fun q => ({q.1, q.2} : Finset V))).card ≤ 2 * Pf.card := by
calc (Pf.biUnion (fun q => ({q.1, q.2} : Finset V))).card
≤ ∑ q ∈ Pf, ({q.1, q.2} : Finset V).card := card_biUnion_le
_ ≤ ∑ _q ∈ Pf, 2 := sum_le_sum fun q _ => (card_insert_le _ _).trans (by simp)
_ = 2 * Pf.card := by rw [sum_const, smul_eq_mul, mul_comm]
unfold pdRhs
calc (und G X).card ≤ (A ∪ Pf.biUnion (fun q => ({q.1, q.2} : Finset V))).card :=
card_le_card hsub
_ ≤ A.card + (Pf.biUnion (fun q => ({q.1, q.2} : Finset V))).card := card_union_le _ _
_ ≤ A.card + 2 * Pf.card := by omega
refine ⟨h1, fun y hy => ?_⟩
rw [← Aux.point_factor G S P hP anc ha y, pdW_eq]
refine sum_le_sum fun X hX => ?_
apply mul_le_mul_of_nonneg_left _ (pow_nonneg hy _)
apply Real.rpow_le_rpow_of_exponent_le (by norm_num)
have := h1 X (mem_powerset.1 hX)
have : ((und G X).card : ℝ) ≤ (pdRhs S P anc X : ℝ) := by exact_mod_cast this
linarith
/-- Optional: the factorization in the proof of `lem:fa-pd-point`, an identity for every real `y`. -/
theorem pd_point_factor (G : SimpleGraph V) (S : Finset V)
(P : Finset (V × V)) (hP : IsPairing G S P) (anc : V → V) (ha : IsAnchor G S anc) (y : ℝ) :
∑ X ∈ S.powerset, y ^ X.card * (2:ℝ) ^ (-(pdRhs S P anc X : ℝ))
= ∏ q ∈ P, Ωpair y (ancDeg S anc q.1) (ancDeg S anc q.2) :=
Aux.point_factor G S P hP anc ha y
/-- The AM–GM consequence before `lem:fa-pd-rate`, for `y ≥ 0` (false for some `y < 0`):
`Ω_{uv}(y) ≥ y² + 4·2^{-n_{uv}/2}·y + 2^{-n_{uv}}`, the argument of the logarithm in `h_{n_{uv}}`. -/
theorem Ωpair_amgm (y : ℝ) (hy : 0 ≤ y) (du dv : ℕ) :
y ^ 2 + 4 * (2:ℝ) ^ (-((2 + du + dv : ℕ) : ℝ) / 2) * y + (2:ℝ) ^ (-((2 + du + dv : ℕ) : ℝ))
≤ Ωpair y du dv := by
have hsq : ∀ d : ℕ, (2:ℝ) ^ (-(d:ℝ)) = ((2:ℝ) ^ (-(d:ℝ) / 2)) ^ 2 := by
intro d
rw [← Real.rpow_natCast, ← Real.rpow_mul (by norm_num)]
congr 1; push_cast; ring
have hsplit : (2:ℝ) ^ (-((2 + du + dv : ℕ) : ℝ) / 2)
= (2:ℝ) ^ (-1:ℝ) * ((2:ℝ) ^ (-(du:ℝ) / 2) * (2:ℝ) ^ (-(dv:ℝ) / 2)) := by
rw [← Real.rpow_add (by norm_num), ← Real.rpow_add (by norm_num)]
congr 1; push_cast; ring
have hhalf : (2:ℝ) ^ (-1:ℝ) = 1 / 2 := by rw [Real.rpow_neg_one]; norm_num
unfold Ωpair
rw [hsplit, hhalf, hsq du, hsq dv]
nlinarith [mul_nonneg hy (sq_nonneg ((2:ℝ) ^ (-(du:ℝ) / 2) - (2:ℝ) ^ (-(dv:ℝ) / 2)))]
/-- Optional: a graph with a paired dominating set has no isolated vertex. -/
theorem noIsolated_of_pairedDom (G : SimpleGraph V) (S : Finset V) (hS : IsPairedDom G S) :
∀ v, ∃ u, G.Adj v u := by
intro v
obtain ⟨hdom, M, hMv, hM⟩ := hS
rcases hdom v with hv | ⟨u, -, hu⟩
· have hv' : v ∈ M.verts := by rw [hMv]; exact hv
obtain ⟨w, hw, -⟩ := hM hv'
exact ⟨w, M.adj_sub hw⟩
· exact ⟨u, hu⟩
/-- Optional: a graph without isolated vertices has a paired dominating set
(the setting of `thm:fa-pd`). -/
theorem exists_pairedDom (G : SimpleGraph V) (hG : ∀ v, ∃ u, G.Adj v u) :
∃ S : Finset V, IsPairedDom G S := by
classical
let ends : Finset (V × V) → Finset V := fun P => P.biUnion (fun q => ({q.1, q.2} : Finset V))
have hends : ∀ P w, w ∈ ends P ↔ ∃ q ∈ P, q.1 = w ∨ q.2 = w := by
intro P w
simp only [ends, mem_biUnion, mem_insert, mem_singleton]
constructor
· rintro ⟨q, hq, h | h⟩
· exact ⟨q, hq, Or.inl h.symm⟩
· exact ⟨q, hq, Or.inr h.symm⟩
· rintro ⟨q, hq, h | h⟩
· exact ⟨q, hq, Or.inl h.symm⟩
· exact ⟨q, hq, Or.inr h.symm⟩
let C := (univ : Finset (Finset (V × V))).filter (fun P => IsPairing G (ends P) P)
have hC0 : (∅ : Finset (V × V)) ∈ C := by
simp only [C, mem_filter, mem_univ, true_and]
refine ⟨fun q hq => by simp at hq, fun w hw => ?_⟩
obtain ⟨q, hq, -⟩ := (hends ∅ w).1 hw
simp at hq
obtain ⟨P, hPC, hPmax⟩ := C.exists_max_image card ⟨∅, hC0⟩
have hP : IsPairing G (ends P) P := (mem_filter.1 hPC).2
refine ⟨ends P, ?_, ?_⟩
· intro v
by_cases hv : v ∈ ends P
· exact Or.inl hv
· right
obtain ⟨u, hvu⟩ := hG v
by_cases hu : u ∈ ends P
· exact ⟨u, hu, hvu⟩
· exfalso
have hnotin : (v, u) ∉ P := fun h => hv ((hends P v).2 ⟨_, h, Or.inl rfl⟩)
have hP' : IsPairing G (ends (insert (v, u) P)) (insert (v, u) P) := by
refine ⟨?_, ?_⟩
· intro q hq
refine ⟨(hends _ q.1).2 ⟨q, hq, Or.inl rfl⟩, (hends _ q.2).2 ⟨q, hq, Or.inr rfl⟩, ?_⟩
rcases mem_insert.1 hq with h | h
· rw [h]; exact hvu
· exact (hP.1 q h).2.2
· intro w hw
obtain ⟨q0, hq0, hq0w⟩ := (hends _ w).1 hw
refine ⟨q0, ⟨hq0, hq0w⟩, ?_⟩
rintro q ⟨hq, hqw⟩
rcases mem_insert.1 hq0 with h0 | h0
· rcases mem_insert.1 hq with h | h
· rw [h, h0]
· exfalso
rw [h0] at hq0w
rcases hq0w with h1 | h1
· rw [← h1] at hqw
exact hv ((hends P v).2 ⟨q, h, hqw⟩)
· rw [← h1] at hqw
exact hu ((hends P u).2 ⟨q, h, hqw⟩)
· rcases mem_insert.1 hq with h | h
· exfalso
rw [h] at hqw
rcases hqw with h1 | h1
· rw [← h1] at hq0w
exact hv ((hends P v).2 ⟨q0, h0, hq0w⟩)
· rw [← h1] at hq0w
exact hu ((hends P u).2 ⟨q0, h0, hq0w⟩)
· exact hP.eq_of_mem h h0 hqw hq0w
have hmem : insert (v, u) P ∈ C := by
simp only [C, mem_filter, mem_univ, true_and]
exact hP'
have h1 := hPmax _ hmem
have h2 := card_lt_card (ssubset_insert hnotin)
omega
· obtain ⟨M, hMv, hM, -⟩ := matching_of_pairing G (ends P) P hP
exact ⟨M, hMv, hM⟩
namespace Aux
/-- One pair: `(1+y*)^m 2^{-ψ_pr m} ≤ y*² + 4·2^{-m/2} y* + 2^{-m}` for `m ≥ 2`
(`PDRate.pd_rate`, first claim of `lem:fa-pd-rate`). -/
theorem pair_bound (m : ℕ) (hm : 2 ≤ m) :
(1 + ystar) ^ m * (2:ℝ) ^ (-(ωpr * m))
≤ ystar ^ 2 + 4 * (2:ℝ) ^ (-(m:ℝ) / 2) * ystar + (2:ℝ) ^ (-(m:ℝ)) := by
have hy := ystar_pos
set A := ystar ^ 2 + 4 * (2:ℝ) ^ (-(m:ℝ) / 2) * ystar + (2:ℝ) ^ (-(m:ℝ)) with hA
have hA0 : 0 < A := by
have h1 : 0 < (2:ℝ) ^ (-(m:ℝ)) := by positivity
have h2 : 0 ≤ 4 * (2:ℝ) ^ (-(m:ℝ) / 2) * ystar := by positivity
have h3 : 0 ≤ ystar ^ 2 := sq_nonneg _
linarith
have h1 := pd_rate.1 m hm
unfold hpd at h1
rw [← hA] at h1
have hm0 : (0:ℝ) < m := by exact_mod_cast (show 0 < m by omega)
have h2 : Real.logb 2 (1 + ystar) - ωpr ≤ (1 / (m:ℝ)) * Real.logb 2 A := by linarith
have h3 : Real.logb 2 (1 + ystar) * m + -(ωpr * m) ≤ Real.logb 2 A := by
calc Real.logb 2 (1 + ystar) * m + -(ωpr * m)
= (m:ℝ) * (Real.logb 2 (1 + ystar) - ωpr) := by ring
_ ≤ (m:ℝ) * ((1 / (m:ℝ)) * Real.logb 2 A) := mul_le_mul_of_nonneg_left h2 hm0.le
_ = Real.logb 2 A := by field_simp
have hL : (2:ℝ) ^ (Real.logb 2 (1 + ystar) * m) = (1 + ystar) ^ m := by
rw [Real.rpow_mul (by norm_num), Real.rpow_logb (by norm_num) (by norm_num) (by linarith),
Real.rpow_natCast]
calc (1 + ystar) ^ m * (2:ℝ) ^ (-(ωpr * m))
= (2:ℝ) ^ (Real.logb 2 (1 + ystar) * m + -(ωpr * m)) := by
rw [Real.rpow_add (by norm_num), hL]
_ ≤ (2:ℝ) ^ (Real.logb 2 A) := Real.rpow_le_rpow_of_exponent_le (by norm_num) h3
_ = A := Real.rpow_logb (by norm_num) (by norm_num) hA0
end Aux
/-- `lem:fa-pd-rate`, second claim. The hypothesis `hG` (no isolated vertex) is the paper's,
kept literally; it follows from `hS` by `noIsolated_of_pairedDom`. -/
theorem pd_rate_W (G : SimpleGraph V) [DecidableRel G.Adj] (hG : ∀ v, ∃ u, G.Adj v u)
(S : Finset V) (hS : IsPairedDom G S) :
(1 + ystar) ^ Fintype.card V * (2:ℝ) ^ (-(ωpr * Fintype.card V)) ≤ pdW G S ystar := by
obtain ⟨hdom, M, hMv, hM⟩ := hS
obtain ⟨P, hP, -⟩ := pairing_of_matching G S M hMv hM
obtain ⟨anc, ha⟩ := exists_anchor G S hdom
have hy0 : 0 ≤ ystar := Aux.ystar_pos.le
set c : ℝ := (1 + ystar) * (2:ℝ) ^ (-ωpr) with hcdef
have hc0 : 0 ≤ c := mul_nonneg (by linarith) (Real.rpow_nonneg (by norm_num) _)
have hc : ∀ m : ℕ, (1 + ystar) ^ m * (2:ℝ) ^ (-(ωpr * m)) = c ^ m := by
intro m
rw [hcdef, mul_pow, ← Real.rpow_natCast ((2:ℝ) ^ (-ωpr)), ← Real.rpow_mul (by norm_num),
show -(ωpr * (m:ℝ)) = -ωpr * m by ring]
have hcard := card_eq_sum_pairs G S P hP anc ha
calc (1 + ystar) ^ Fintype.card V * (2:ℝ) ^ (-(ωpr * Fintype.card V))
= c ^ Fintype.card V := hc _
_ = ∏ q ∈ P, c ^ (2 + ancDeg S anc q.1 + ancDeg S anc q.2) := by
rw [prod_pow_eq_pow_sum, ← hcard]
_ ≤ ∏ q ∈ P, Ωpair ystar (ancDeg S anc q.1) (ancDeg S anc q.2) := by
apply prod_le_prod₀ (fun q _ => pow_nonneg hc0 _)
intro q _
rw [← hc]
exact (Aux.pair_bound _ (by omega)).trans (Ωpair_amgm ystar hy0 _ _)
_ ≤ pdW G S ystar := (pd_point G S P hP anc ha).2 ystar hy0
/-- Optional: condition (⋆) of `thm:fw-main` at rate 0.70502 and `Γ = 1`
(proof of `thm:fa-pd`). -/
theorem pd_star (G : SimpleGraph V) [DecidableRel G.Adj] (S : Finset V) (hS : IsPairedDom G S) :
MLS.Star (pdG G) S S.card (70502 / 10 ^ 5) 1 := by
have hW := pd_rate_W G (noIsolated_of_pairedDom G S hS) S hS
have hy0 : 0 ≤ ystar := Aux.ystar_pos.le
apply MLS.star_of_W (pdG G) S S.card rfl _ 1 ystar one_pos hy0
rw [div_one]
refine le_trans ?_ hW
apply mul_le_mul_of_nonneg_left _ (pow_nonneg (by linarith) _)
apply Real.rpow_le_rpow_of_exponent_le (by norm_num)
have h1 := pd_constants.2.2.1
have hn : (0:ℝ) ≤ Fintype.card V := Nat.cast_nonneg _
nlinarith
/-- Optional: success probability of MLS at rate 0.70502, `Γ = 1`, for `k = |S|`,
with the extension algorithm replaced by its specification `ExtYes`. -/
theorem pd_success (G : SimpleGraph V) [DecidableRel G.Adj] (S : Finset V) (hS : IsPairedDom G S)
(κ : ℝ) (hκ : 0 < κ) :
1 - Real.exp (-κ) ≤
(trialMeasure S.card (70502 / 10 ^ 5) 1 κ
{o | Accepts (IsPairedDom G) (pdG G) S.card (70502 / 10 ^ 5) 1 κ o}).toReal :=
MLS.mls_success (IsPairedDom G) (pdG G) (fun _ _ => Nat.cast_nonneg _) S.card (card_le_univ S)
(70502 / 10 ^ 5) 1 κ (by norm_num) le_rfl hκ S hS rfl (pd_star G S hS)
end General
section Tight
/-- Edges of one double star: centres 0, 1; pendants 2, 3 at 0 and 4, 5 at 1. -/
def dsEdge (a b : Fin 6) : Prop :=
(a = 0 ∧ (b = 1 ∨ b = 2 ∨ b = 3)) ∨ (a = 1 ∧ (b = 4 ∨ b = 5))
instance instDecidableRelDsEdge : DecidableRel dsEdge := fun a b => by unfold dsEdge; infer_instance
/-- `G_L`: the disjoint union of `L` double stars. (Not `GL`, which is Mathlib notation.) -/
def dstarGraph (L : ℕ) : SimpleGraph (Fin L × Fin 6) :=
SimpleGraph.fromRel fun p q => p.1 = q.1 ∧ dsEdge p.2 q.2
/-- Needed although Mathlib has `DecidableRel (SimpleGraph.fromRel r).Adj`: instance search
does not unfold the definition `dstarGraph`. `inferInstanceAs` is an allowed form. -/
instance instDecidableRelDstarGraph (L : ℕ) : DecidableRel (dstarGraph L).Adj := fun p q =>
decidable_of_iff (p ≠ q ∧ ((p.1 = q.1 ∧ dsEdge p.2 q.2) ∨ (q.1 = p.1 ∧ dsEdge q.2 p.2)))
(SimpleGraph.fromRel_adj (fun p q : Fin L × Fin 6 => p.1 = q.1 ∧ dsEdge p.2 q.2) p q).symm
/-- `S*`, the `2L` centres. -/
def Sstar (L : ℕ) : Finset (Fin L × Fin 6) := univ ×ˢ ({0, 1} : Finset (Fin 6))
namespace Aux
theorem dsE01 : dsEdge 0 1 := by decide
theorem dsEdge_irrefl : ∀ a : Fin 6, ¬ dsEdge a a := by decide
theorem dsCover : ∀ r : Fin 6, r = 0 ∨ r = 1 ∨ dsEdge 0 r ∨ dsEdge 1 r := by decide
theorem dsPend2 : ∀ x : Fin 6, (dsEdge 2 x ∨ dsEdge x 2) ↔ x = 0 := by decide
theorem dsPend4 : ∀ x : Fin 6, (dsEdge 4 x ∨ dsEdge x 4) ↔ x = 1 := by decide
theorem dsAdj_iff (L : ℕ) (p q : Fin L × Fin 6) :
(dstarGraph L).Adj p q ↔ p.1 = q.1 ∧ (dsEdge p.2 q.2 ∨ dsEdge q.2 p.2) := by
unfold dstarGraph
rw [SimpleGraph.fromRel_adj]
constructor
· rintro ⟨_, h | h⟩
· exact ⟨h.1, Or.inl h.2⟩
· exact ⟨h.1.symm, Or.inr h.2⟩
· rintro ⟨h1, h | h⟩
· refine ⟨fun heq => ?_, Or.inl ⟨h1, h⟩⟩
subst heq
exact dsEdge_irrefl _ h
· refine ⟨fun heq => ?_, Or.inr ⟨h1.symm, h⟩⟩
subst heq
exact dsEdge_irrefl _ h
theorem pend_adj_two {L : ℕ} (i : Fin L) (w : Fin L × Fin 6)
(h : (dstarGraph L).Adj (i, 2) w) : w = (i, 0) := by
rw [dsAdj_iff] at h
obtain ⟨h1, h2⟩ := h
have h3 : w.2 = 0 := (dsPend2 w.2).1 h2
exact Prod.ext h1.symm h3
theorem pend_adj_four {L : ℕ} (i : Fin L) (w : Fin L × Fin 6)
(h : (dstarGraph L).Adj (i, 4) w) : w = (i, 1) := by
rw [dsAdj_iff] at h
obtain ⟨h1, h2⟩ := h
have h3 : w.2 = 1 := (dsPend4 w.2).1 h2
exact Prod.ext h1.symm h3
theorem Sstar_mem_iff {L : ℕ} (p : Fin L × Fin 6) : p ∈ Sstar L ↔ p.2 = 0 ∨ p.2 = 1 := by
simp [Sstar, Finset.mem_product]
theorem card_Sstar (L : ℕ) : (Sstar L).card = 2 * L := by
unfold Sstar
rw [Finset.card_product, Finset.card_univ, Fintype.card_fin]
have h2 : ({0, 1} : Finset (Fin 6)).card = 2 := by decide
rw [h2]
ring
theorem mem_of_pendant {L : ℕ} (S : Finset (Fin L × Fin 6)) (hS : IsPairedDom (dstarGraph L) S)
(p c : Fin L × Fin 6) (hpc : ∀ w, (dstarGraph L).Adj p w → w = c) : c ∈ S := by
unfold IsPairedDom IsDominating at hS
obtain ⟨hdom, M, hMv, hMm⟩ := hS
by_cases hp : p ∈ S
· have hpM : p ∈ M.verts := by
rw [hMv]
exact Finset.mem_coe.2 hp
obtain ⟨w, hw, -⟩ := hMm hpM
have hwc : w = c := hpc w (M.adj_sub hw)
have hwp : M.Adj w p := by
exact M.symm.symm _ _ hw
have hwM : w ∈ M.verts := M.edge_vert hwp
rw [hMv] at hwM
rw [← hwc]
exact Finset.mem_coe.1 hwM
· rcases hdom p with h | ⟨u, hu, hadj⟩
· exact absurd h hp
· have huc : u = c := hpc u hadj
rw [← huc]
exact hu
theorem dom_Sstar (L : ℕ) : IsDominating (dstarGraph L) (Sstar L) := by
unfold IsDominating
rintro ⟨i, r⟩
rcases dsCover r with h | h | h | h
· exact Or.inl ((Sstar_mem_iff (i, r)).2 (Or.inl h))
· exact Or.inl ((Sstar_mem_iff (i, r)).2 (Or.inr h))
· exact Or.inr ⟨(i, 0), (Sstar_mem_iff (i, 0)).2 (Or.inl rfl),
(dsAdj_iff L (i, r) (i, 0)).2 ⟨rfl, Or.inr h⟩⟩
· exact Or.inr ⟨(i, 1), (Sstar_mem_iff (i, 1)).2 (Or.inr rfl),
(dsAdj_iff L (i, r) (i, 1)).2 ⟨rfl, Or.inr h⟩⟩
theorem exists_matching (L : ℕ) :
∃ M : (dstarGraph L).Subgraph, M.verts = (Sstar L : Set (Fin L × Fin 6)) ∧ M.IsMatching := by
have hadj : ∀ p q : Fin L × Fin 6,
(p.1 = q.1 ∧ ((p.2 = 0 ∧ q.2 = 1) ∨ (p.2 = 1 ∧ q.2 = 0))) → (dstarGraph L).Adj p q := by
rintro p q ⟨h1, h2 | h2⟩
· exact (dsAdj_iff L p q).2 ⟨h1, Or.inl (by rw [h2.1, h2.2]; exact dsE01)⟩
· exact (dsAdj_iff L p q).2 ⟨h1, Or.inr (by rw [h2.1, h2.2]; exact dsE01)⟩
have hvert : ∀ p q : Fin L × Fin 6,
(p.1 = q.1 ∧ ((p.2 = 0 ∧ q.2 = 1) ∨ (p.2 = 1 ∧ q.2 = 0))) →
p ∈ (Sstar L : Set (Fin L × Fin 6)) := by
rintro p q ⟨_, h2 | h2⟩
· exact Finset.mem_coe.2 ((Sstar_mem_iff p).2 (Or.inl h2.1))
· exact Finset.mem_coe.2 ((Sstar_mem_iff p).2 (Or.inr h2.1))
refine ⟨{ verts := (Sstar L : Set (Fin L × Fin 6)),
Adj := fun p q => p.1 = q.1 ∧ ((p.2 = 0 ∧ q.2 = 1) ∨ (p.2 = 1 ∧ q.2 = 0)),
adj_sub := by
intro v w h
exact hadj v w h,
edge_vert := by
intro v w h
exact hvert v w h,
symm := ⟨by
intro v w h
obtain ⟨h1, h2 | h2⟩ := h
· exact ⟨h1.symm, Or.inr ⟨h2.2, h2.1⟩⟩
· exact ⟨h1.symm, Or.inl ⟨h2.2, h2.1⟩⟩⟩ }, rfl, ?_⟩
intro v hv
have hv' : v.2 = 0 ∨ v.2 = 1 := (Sstar_mem_iff v).1 (Finset.mem_coe.1 hv)
rcases hv' with h | h
· refine ⟨(v.1, 1), ⟨rfl, Or.inl ⟨h, rfl⟩⟩, ?_⟩
rintro w ⟨h1, h2 | h2⟩
· exact Prod.ext h1.symm h2.2
· exact absurd (h.symm.trans h2.1) (by decide)
· refine ⟨(v.1, 0), ⟨rfl, Or.inr ⟨h, rfl⟩⟩, ?_⟩
rintro w ⟨h1, h2 | h2⟩
· exact absurd (h.symm.trans h2.1) (by decide)
· exact Prod.ext h1.symm h2.2
end Aux
theorem dstarGraph_noIsolated (L : ℕ) : ∀ v, ∃ u, (dstarGraph L).Adj v u := by
rintro ⟨i, r⟩
rcases Aux.dsCover r with h | h | h | h
· subst h
exact ⟨(i, 1), (Aux.dsAdj_iff L (i, 0) (i, 1)).2 ⟨rfl, Or.inl Aux.dsE01⟩⟩
· subst h
exact ⟨(i, 0), (Aux.dsAdj_iff L (i, 1) (i, 0)).2 ⟨rfl, Or.inr Aux.dsE01⟩⟩
· exact ⟨(i, 0), (Aux.dsAdj_iff L (i, r) (i, 0)).2 ⟨rfl, Or.inr h⟩⟩
· exact ⟨(i, 1), (Aux.dsAdj_iff L (i, r) (i, 1)).2 ⟨rfl, Or.inr h⟩⟩
/-- The proof's stronger claim: every paired dominating set contains all centres. -/
theorem Sstar_subset (L : ℕ) (S : Finset (Fin L × Fin 6)) (hS : IsPairedDom (dstarGraph L) S) :
Sstar L ⊆ S := by
rintro ⟨i, r⟩ hv
rcases (Aux.Sstar_mem_iff (i, r)).1 hv with h | h
· obtain rfl : r = 0 := h
exact Aux.mem_of_pendant S hS (i, 2) (i, 0) (fun w hw => Aux.pend_adj_two i w hw)
· obtain rfl : r = 1 := h
exact Aux.mem_of_pendant S hS (i, 4) (i, 1) (fun w hw => Aux.pend_adj_four i w hw)
/-- `prop:fa-pd-tight`, graph part. -/
theorem pd_tight_unique (L : ℕ) :
IsPairedDom (dstarGraph L) (Sstar L) ∧ (Sstar L).card = 2 * L ∧
∀ S : Finset (Fin L × Fin 6), IsPairedDom (dstarGraph L) S → S.card ≤ 2 * L → S = Sstar L := by
refine ⟨?_, Aux.card_Sstar L, ?_⟩
· unfold IsPairedDom
exact ⟨Aux.dom_Sstar L, Aux.exists_matching L⟩
· intro S hS hcard
have hsub := Sstar_subset L S hS
refine (Finset.eq_of_subset_of_card_le hsub ?_).symm
rw [Aux.card_Sstar]
exact hcard
namespace Aux
/-- Anchors at the centres of the double stars. -/
def ctrAnc (L : ℕ) (p : Fin L × Fin 6) : Fin L × Fin 6 := (p.1, if p.2.val ≤ 3 then 0 else 1)
/-- The pairs `u_i v_i` of the centres. -/
def ctrPairs (L : ℕ) : Finset ((Fin L × Fin 6) × (Fin L × Fin 6)) :=
univ.image (fun i : Fin L => ((i, 0), (i, 1)))
theorem ds_pend_eq : ∀ a b : Fin 6, ¬ (b = 0 ∨ b = 1) → (dsEdge a b ∨ dsEdge b a) →
a = (if b.val ≤ 3 then 0 else 1) := by decide
theorem ds_anc_edge : ∀ b : Fin 6, ¬ (b = 0 ∨ b = 1) → dsEdge (if b.val ≤ 3 then 0 else 1) b := by
decide
theorem ctr_pairing (L : ℕ) : IsPairing (dstarGraph L) (Sstar L) (ctrPairs L) := by
have hmem : ∀ q, q ∈ ctrPairs L ↔ ∃ i : Fin L, ((i, 0), (i, 1)) = q := by
intro q; simp [ctrPairs]
refine ⟨?_, ?_⟩
· intro q hq
obtain ⟨i, rfl⟩ := (hmem q).1 hq
exact ⟨(Sstar_mem_iff _).2 (Or.inl rfl), (Sstar_mem_iff _).2 (Or.inr rfl),
(dsAdj_iff L _ _).2 ⟨rfl, Or.inl dsE01⟩⟩
· rintro ⟨i, c⟩ hw
have hc := (Sstar_mem_iff (i, c)).1 hw
refine ⟨((i, 0), (i, 1)), ⟨(hmem _).2 ⟨i, rfl⟩, ?_⟩, ?_⟩
· rcases hc with h | h
· exact Or.inl (Prod.ext rfl h.symm)
· exact Or.inr (Prod.ext rfl h.symm)
· rintro q ⟨hq, hqw⟩
obtain ⟨j, rfl⟩ := (hmem q).1 hq
have : j = i := by rcases hqw with h | h <;> exact congrArg Prod.fst h
rw [this]
theorem ctr_anchor (L : ℕ) : IsAnchor (dstarGraph L) (Sstar L) (ctrAnc L) := by
rintro ⟨i, b⟩ hv
have hb : ¬ (b = 0 ∨ b = 1) := fun h => hv ((Sstar_mem_iff (i, b)).2 h)
refine ⟨(Sstar_mem_iff _).2 ?_, (dsAdj_iff L _ _).2 ⟨rfl, Or.inr (ds_anc_edge b hb)⟩⟩
simp only [ctrAnc]
split_ifs <;> simp
theorem ctr_deg (L : ℕ) (i : Fin L) (c : Fin 6) (hc : c = 0 ∨ c = 1) :
ancDeg (Sstar L) (ctrAnc L) (i, c) = 2 := by
unfold ancDeg
have h : (univ.filter (fun v : Fin L × Fin 6 => v ∉ Sstar L ∧ ctrAnc L v = (i, c)))
= (univ.filter (fun x : Fin 6 => ¬ (x = 0 ∨ x = 1) ∧
(if x.val ≤ 3 then (0 : Fin 6) else 1) = c)).image (fun x => (i, x)) := by
ext ⟨j, x⟩
simp only [mem_filter, mem_univ, true_and, mem_image, Sstar_mem_iff, ctrAnc, Prod.mk.injEq]
constructor
· rintro ⟨h1, h2, h3⟩; exact ⟨x, ⟨h1, h3⟩, h2.symm, rfl⟩
· rintro ⟨y, ⟨h1, h3⟩, rfl, rfl⟩; exact ⟨h1, rfl, h3⟩
rw [h, card_image_of_injective _ (fun a b hab => (Prod.ext_iff.1 hab).2)]
rcases hc with rfl | rfl <;> decide
theorem card_ctrPairs (L : ℕ) : (ctrPairs L).card = L := by
unfold ctrPairs
rw [card_image_of_injective _ (fun a b h => congrArg Prod.fst (congrArg Prod.fst h)), card_univ,
Fintype.card_fin]
/-- With anchors at the centres, the first inequality of `lem:fa-pd-point` is an equality. -/
theorem und_eq (L : ℕ) (X : Finset (Fin L × Fin 6)) (hX : X ⊆ Sstar L) :
(und (dstarGraph L) X).card = pdRhs (Sstar L) (ctrPairs L) (ctrAnc L) X := by
apply le_antisymm ((pd_point _ _ _ (ctr_pairing L) _ (ctr_anchor L)).1 X hX)
set A := univ.filter (fun v => v ∉ Sstar L ∧ ctrAnc L v ∉ X) with hA
set Pf := (ctrPairs L).filter (fun q => q.1 ∉ X ∧ q.2 ∉ X) with hPf
set E := Pf.biUnion (fun q => ({q.1, q.2} : Finset (Fin L × Fin 6))) with hE
have hP := ctr_pairing L
have hEc : E.card = 2 * Pf.card := by
rw [hE, card_biUnion]
· rw [sum_congr rfl (fun q hq => card_pair (hP.fst_ne_snd (mem_filter.1 hq).1)), sum_const,
smul_eq_mul, mul_comm]
· intro q hq q' hq' hne
simp only [Function.onFun]
rw [Finset.disjoint_left]
intro w hw hw'
simp only [mem_insert, mem_singleton] at hw hw'
exact hne (hP.eq_of_mem (mem_filter.1 hq).1 (mem_filter.1 hq').1
(by rcases hw with h | h <;> [left; right] <;> exact h.symm)
(by rcases hw' with h | h <;> [left; right] <;> exact h.symm))
have hdis : Disjoint A E := by
rw [Finset.disjoint_left]
intro v hvA hvE
have h1 := (mem_filter.1 hvA).2.1
obtain ⟨q, hq, hvq⟩ := mem_biUnion.1 hvE
have := hP.1 q (mem_filter.1 hq).1
simp only [mem_insert, mem_singleton] at hvq
rcases hvq with h | h
· rw [h] at h1; exact h1 this.1
· rw [h] at h1; exact h1 this.2.1
have hsub : A ∪ E ⊆ und (dstarGraph L) X := by
intro v hv
simp only [und, mem_sdiff, mem_univ, true_and, CDS.mem_closedNbhd, not_or, not_exists,
not_and]
rcases mem_union.1 hv with hvA | hvE
· obtain ⟨hvS, hanc⟩ := (mem_filter.1 hvA).2
refine ⟨fun h => hvS (hX h), fun x hx hadj => hanc ?_⟩
have hb : ¬ (v.2 = 0 ∨ v.2 = 1) := fun h => hvS ((Sstar_mem_iff v).2 h)
obtain ⟨h1, h2⟩ := (dsAdj_iff L x v).1 hadj
have hx2 := ds_pend_eq x.2 v.2 hb h2
have : x = ctrAnc L v := Prod.ext h1 hx2
rw [← this]; exact hx
· obtain ⟨q, hq, hvq⟩ := mem_biUnion.1 hvE
obtain ⟨hqP, hq1, hq2⟩ := mem_filter.1 hq
obtain ⟨i, -, rfl⟩ := mem_image.1 hqP
simp only [mem_insert, mem_singleton] at hvq
refine ⟨by rcases hvq with h | h <;> rw [h] <;> assumption, fun x hx hadj => ?_⟩
have hx2 := (Sstar_mem_iff x).1 (hX hx)
have hx1 : x.1 = i := by
have := ((dsAdj_iff L x v).1 hadj).1
rcases hvq with h | h <;> rw [h] at this <;> exact this
rcases hx2 with h | h
· have : x = (i, 0) := Prod.ext hx1 h
rw [this] at hx; exact hq1 hx
· have : x = (i, 1) := Prod.ext hx1 h
rw [this] at hx; exact hq2 hx
calc pdRhs (Sstar L) (ctrPairs L) (ctrAnc L) X = A.card + 2 * Pf.card := rfl
_ = (A ∪ E).card := by rw [card_union_of_disjoint hdis, hEc]
_ ≤ (und (dstarGraph L) X).card := card_le_card hsub
end Aux
/-- `W_{S*}(y) = (y² + y/2 + 1/64)^L` (proof of `prop:fa-pd-tight`). -/
theorem pd_tight_W (L : ℕ) (y : ℝ) :
pdW (dstarGraph L) (Sstar L) y = (y ^ 2 + y / 2 + 1 / 64) ^ L := by
have hP := Aux.ctr_pairing L
have ha := Aux.ctr_anchor L
rw [pdW_eq]
have h1 : ∑ X ∈ (Sstar L).powerset, y ^ X.card * (2:ℝ) ^ (-((und (dstarGraph L) X).card : ℝ))
= ∑ X ∈ (Sstar L).powerset,
y ^ X.card * (2:ℝ) ^ (-(pdRhs (Sstar L) (Aux.ctrPairs L) (Aux.ctrAnc L) X : ℝ)) :=
sum_congr rfl fun X hX => by rw [Aux.und_eq L X (mem_powerset.1 hX)]
rw [h1, pd_point_factor _ _ _ hP _ ha]
have h2 : ∀ q ∈ Aux.ctrPairs L, Ωpair y (ancDeg (Sstar L) (Aux.ctrAnc L) q.1)
(ancDeg (Sstar L) (Aux.ctrAnc L) q.2) = y ^ 2 + y / 2 + 1 / 64 := by
intro q hq
obtain ⟨i, -, rfl⟩ := mem_image.1 hq
show Ωpair y (ancDeg (Sstar L) (Aux.ctrAnc L) (i, 0)) (ancDeg (Sstar L) (Aux.ctrAnc L) (i, 1))
= _
rw [Aux.ctr_deg L i 0 (Or.inl rfl), Aux.ctr_deg L i 1 (Or.inr rfl)]
unfold Ωpair
simp only [Aux.two_rpow_neg_nat]
ring
rw [prod_congr rfl h2, prod_const, Aux.card_ctrPairs]
theorem hpd6_eq (y : ℝ) :
hpd 6 y = Real.logb 2 (1 + y) - (1 / 6) * Real.logb 2 (y ^ 2 + y / 2 + 1 / 64) := by
have h1 : (2:ℝ) ^ (-(6:ℝ) / 2) = 1 / 8 := by
rw [show -(6:ℝ) / 2 = ((-3 : ℤ) : ℝ) by norm_num, Real.rpow_intCast]
norm_num
have h2 : (2:ℝ) ^ (-(6:ℝ)) = 1 / 64 := by
rw [show -(6:ℝ) = ((-6 : ℤ) : ℝ) by norm_num, Real.rpow_intCast]
norm_num
unfold hpd
rw [h1, h2, show y ^ 2 + 4 * (1 / 8) * y + 1 / 64 = y ^ 2 + y / 2 + 1 / 64 by ring]
namespace Aux
theorem hpd6_fun : hpd 6 = fun y : ℝ => Real.logb 2 (1 + y) - (1 / 6) * Real.logb 2 (y ^ 2 + y / 2 + 1 / 64) :=
funext hpd6_eq
theorem hpd6_cont : ContinuousOn (hpd 6) (Set.Ici 0) := by
rw [hpd6_fun]
have hL1 : ContinuousOn (fun x : ℝ => Real.log (1 + x)) (Set.Ici 0) :=
ContinuousOn.log (by fun_prop) (fun x hx => by
have hx' : (0:ℝ) ≤ x := hx
exact (show (0:ℝ) < 1 + x by linarith).ne')
have hL2 : ContinuousOn (fun x : ℝ => Real.log (x ^ 2 + x / 2 + 1 / 64)) (Set.Ici 0) :=
ContinuousOn.log (by fun_prop) (fun x hx => by
have hx' : (0:ℝ) ≤ x := hx
have := sq_nonneg x
exact (show (0:ℝ) < x ^ 2 + x / 2 + 1 / 64 by linarith).ne')
exact (hL1.div_const (Real.log 2)).sub (continuousOn_const.mul (hL2.div_const (Real.log 2)))
theorem den_pos (y : ℝ) (hy : 0 < y) :
0 < Real.log 2 * (6 * (y ^ 2 + y / 2 + 1 / 64) * (1 + y)) := by
have hQ0 : 0 < y ^ 2 + y / 2 + 1 / 64 := by
have := sq_nonneg y
linarith
exact mul_pos (Real.log_pos one_lt_two) (mul_pos (mul_pos (by norm_num) hQ0) (by linarith))
theorem hasDeriv_pos (y : ℝ) (hy : 0 < y) :
HasDerivAt (hpd 6) ((4 * y ^ 2 + y / 2 - 13 / 32) /
(Real.log 2 * (6 * (y ^ 2 + y / 2 + 1 / 64) * (1 + y)))) y := by
have hQ0 : 0 < y ^ 2 + y / 2 + 1 / 64 := by
have := sq_nonneg y
linarith
have hP0 : (0:ℝ) < 1 + y := by linarith
have hlog2 : 0 < Real.log 2 := Real.log_pos one_lt_two
have hQne : y ^ 2 + y / 2 + 1 / 64 ≠ 0 := hQ0.ne'
have hPne : (1:ℝ) + y ≠ 0 := hP0.ne'
have hlne : Real.log 2 ≠ 0 := hlog2.ne'
have hA : HasDerivAt (fun x : ℝ => Real.log (1 + x)) (1 / (1 + y)) y :=
((hasDerivAt_id' y).const_add 1).log hPne
have hQ : HasDerivAt (fun x : ℝ => x ^ 2 + x / 2 + 1 / 64) (2 * y + 1 / 2) y :=
(((hasDerivAt_pow 2 y).add ((hasDerivAt_id' y).div_const 2)).add_const (1 / 64 : ℝ)).congr_deriv
(by norm_num)
have hB : HasDerivAt (fun x : ℝ => Real.log (x ^ 2 + x / 2 + 1 / 64))
((2 * y + 1 / 2) / (y ^ 2 + y / 2 + 1 / 64)) y :=
hQ.log hQne
have hC := (hA.div_const (Real.log 2)).sub ((hB.div_const (Real.log 2)).const_mul (1 / 6 : ℝ))
have hkey : 1 / (1 + y) / Real.log 2
- 1 / 6 * ((2 * y + 1 / 2) / (y ^ 2 + y / 2 + 1 / 64) / Real.log 2)
= (4 * y ^ 2 + y / 2 - 13 / 32) / (Real.log 2 * (6 * (y ^ 2 + y / 2 + 1 / 64) * (1 + y))) := by
field_simp
ring
rw [hpd6_fun]
exact hC.congr_deriv hkey
theorem hpd6_anti : StrictAntiOn (hpd 6) (Set.Icc 0 ystar) := by
apply strictAntiOn_of_deriv_neg (convex_Icc 0 ystar) (hpd6_cont.mono Set.Icc_subset_Ici_self)
intro τ hτ
rw [interior_Icc] at hτ
rw [(hasDeriv_pos τ hτ.1).deriv]
apply div_neg_of_neg_of_pos
· rw [N_factor τ]
exact mul_neg_of_neg_of_pos (mul_neg_of_pos_of_neg (by norm_num) (by linarith [hτ.2]))
(by linarith [Real.sqrt_nonneg 3, hτ.1])
· exact den_pos τ hτ.1
theorem hpd6_mono : StrictMonoOn (hpd 6) (Set.Ici ystar) := by
apply strictMonoOn_of_deriv_pos (convex_Ici ystar)
(hpd6_cont.mono (Set.Ici_subset_Ici.mpr ystar_pos.le))
intro τ hτ
rw [interior_Ici] at hτ
have hτ' : ystar < τ := hτ
have hτ0 : 0 < τ := lt_trans ystar_pos hτ'
rw [(hasDeriv_pos τ hτ0).deriv]
apply div_pos
· rw [N_factor τ]
exact mul_pos (mul_pos (by norm_num) (by linarith)) (by linarith [Real.sqrt_nonneg 3])
· exact den_pos τ hτ0
theorem argmin_strict (y : ℝ) (hy : 0 ≤ y) (hne : y ≠ ystar) : ωpr < hpd 6 y := by
unfold ωpr
rcases lt_or_gt_of_ne hne with hlt | hgt
· exact hpd6_anti ⟨hy, hlt.le⟩ ⟨ystar_pos.le, le_rfl⟩ hlt
· exact hpd6_mono (Set.mem_Ici.mpr le_rfl) (Set.mem_Ici.mpr hgt.le) hgt
end Aux
/-- `prop:fa-pd-tight`, first sentence, critical point. -/
theorem pd_tight_crit :
0 < ystar ∧
(∀ y : ℝ, 0 < y → DifferentiableAt ℝ (hpd 6) y) ∧
∀ y : ℝ, 0 < y → (deriv (hpd 6) y = 0 ↔ y = ystar) := by
refine ⟨Aux.ystar_pos, fun y hy => (Aux.hasDeriv_pos y hy).differentiableAt, fun y hy => ?_⟩
rw [(Aux.hasDeriv_pos y hy).deriv]
constructor
· intro h
rcases div_eq_zero_iff.mp h with h1 | h1
· have h2 : 4 * (y - ystar) * (y - (-1 - 3 * Real.sqrt 3) / 16) = 0 := by
rw [← Aux.N_factor y]
exact h1
rcases mul_eq_zero.mp h2 with h3 | h3
· rcases mul_eq_zero.mp h3 with h4 | h4
· norm_num at h4
· linarith
· exfalso
linarith [Real.sqrt_nonneg 3]
· exact absurd h1 (Aux.den_pos y hy).ne'
· intro h
have hN : 4 * ystar ^ 2 + ystar / 2 - 13 / 32 = 0 := by
unfold ystar
linear_combination (9 / 64 : ℝ) * Aux.sqrt3_sq
rw [h, hN, zero_div]
/-- `prop:fa-pd-tight`, first sentence, minimum: `min_{y ≥ 0} h_6(y) = h_6(y*)`. -/
theorem pd_tight_min : 0 ≤ ystar ∧ ∀ y : ℝ, 0 ≤ y → ωpr ≤ hpd 6 y := by
refine ⟨Aux.ystar_pos.le, fun y hy => ?_⟩
by_cases h : y = ystar
· subst h
unfold ωpr
exact le_rfl
· exact (Aux.argmin_strict y hy h).le
/-- Optional: `y*` is the only minimizer of `h_6` on `[0, ∞)`. -/
theorem pd_tight_argmin : ∀ y : ℝ, 0 ≤ y → y ≠ ystar → ωpr < hpd 6 y := by
intro y hy hne
exact Aux.argmin_strict y hy hne
/-- `(1+y)^n / W_{S*}(y) = 2^{n h_6(y)}` with `n = 6L`. -/
theorem pd_tight_ratio (L : ℕ) (y : ℝ) (hy : 0 ≤ y) :
(1 + y) ^ (6 * L) = (2:ℝ) ^ (((6 * L : ℕ) : ℝ) * hpd 6 y) * pdW (dstarGraph L) (Sstar L) y := by
set Q := y ^ 2 + y / 2 + 1 / 64 with hQ
have hQ0 : 0 < Q := by have := sq_nonneg y; linarith
have hP0 : 0 < 1 + y := by linarith
rw [pd_tight_W, hpd6_eq, ← hQ]
have e : ((6 * L : ℕ) : ℝ) * (Real.logb 2 (1 + y) - 1 / 6 * Real.logb 2 Q)
= Real.logb 2 (1 + y) * ((6 * L : ℕ) : ℝ) + -(Real.logb 2 Q * (L : ℝ)) := by
push_cast; ring
rw [e, Real.rpow_add (by norm_num), Real.rpow_neg (by norm_num), Real.rpow_mul (by norm_num),
Real.rpow_mul (by norm_num), Real.rpow_logb (by norm_num) (by norm_num) hP0,
Real.rpow_logb (by norm_num) (by norm_num) hQ0, Real.rpow_natCast, Real.rpow_natCast,
mul_assoc, inv_mul_cancel₀ (pow_ne_zero _ hQ0.ne'), mul_one]
theorem pd_tight_W_le (L : ℕ) (y : ℝ) (hy : 0 ≤ y) :
pdW (dstarGraph L) (Sstar L) y ≤ (1 + y) ^ (6 * L) * (2:ℝ) ^ (-(ωpr * (6 * L : ℕ))) := by
have hr := pd_tight_ratio L y hy
have hW0 : 0 ≤ pdW (dstarGraph L) (Sstar L) y := by
rw [pd_tight_W]; exact pow_nonneg (by nlinarith [sq_nonneg y]) _
have hm := pd_tight_min.2 y hy
set n : ℝ := ((6 * L : ℕ) : ℝ) with hn
have hn0 : 0 ≤ n := Nat.cast_nonneg _
have h1 : (1:ℝ) ≤ (2:ℝ) ^ (n * hpd 6 y) * (2:ℝ) ^ (-(ωpr * n)) := by
rw [← Real.rpow_add (by norm_num)]
apply Real.one_le_rpow (by norm_num)
nlinarith
calc pdW (dstarGraph L) (Sstar L) y
≤ pdW (dstarGraph L) (Sstar L) y * ((2:ℝ) ^ (n * hpd 6 y) * (2:ℝ) ^ (-(ωpr * n))) :=
le_mul_of_one_le_right hW0 h1
_ = (1 + y) ^ (6 * L) * (2:ℝ) ^ (-(ωpr * n)) := by rw [hr]; ring
namespace Aux
theorem card_dstar (L : ℕ) : Fintype.card (Fin L × Fin 6) = 6 * L := by
rw [Fintype.card_prod, Fintype.card_fin, Fintype.card_fin, mul_comm]
end Aux
/-- Proof of `prop:fa-pd-tight`: `max_t μ_t(S*)/C(n,t) ≤ (n+1) 2^{-ψ_pr n}`. -/
theorem pd_tight_moments (L : ℕ) (t : ℕ) (ht : t ≤ 2 * L) :
mu (pdG (dstarGraph L)) (Sstar L) (2 * L) t / ((6 * L).choose t : ℝ)
≤ (((6 * L : ℕ) : ℝ) + 1) * (2:ℝ) ^ (-(ωpr * (6 * L : ℕ))) := by
have hcard : (Sstar L).card = 2 * L := (pd_tight_unique L).2.1
obtain ⟨y, hy, hle⟩ := MLSNec.fw_gf_upper (pdG (dstarGraph L)) (Sstar L) (2 * L) hcard t ht
rw [Aux.card_dstar] at hle
have hW : W (pdG (dstarGraph L)) (Sstar L) (2 * L) y = pdW (dstarGraph L) (Sstar L) y := by
unfold pdW; rw [hcard]
rw [hW] at hle
have hWle := pd_tight_W_le L y hy
have hC : (0:ℝ) < (6 * L).choose t := Nat.cast_pos.2 (Nat.choose_pos (by omega))
have hP : (0:ℝ) < (1 + y) ^ (6 * L) := pow_pos (by linarith) _
rw [div_le_iff₀ hC]
have h2 : mu (pdG (dstarGraph L)) (Sstar L) (2 * L) t * (1 + y) ^ (6 * L)
≤ ((((6 * L : ℕ) : ℝ) + 1) * (2:ℝ) ^ (-(ωpr * (6 * L : ℕ))) * ((6 * L).choose t : ℝ))
* (1 + y) ^ (6 * L) := by
calc mu (pdG (dstarGraph L)) (Sstar L) (2 * L) t * (1 + y) ^ (6 * L)
≤ (((6 * L : ℕ) : ℝ) + 1) * ((6 * L).choose t : ℝ) * pdW (dstarGraph L) (Sstar L) y := hle
_ ≤ (((6 * L : ℕ) : ℝ) + 1) * ((6 * L).choose t : ℝ) *
((1 + y) ^ (6 * L) * (2:ℝ) ^ (-(ωpr * (6 * L : ℕ)))) :=
mul_le_mul_of_nonneg_left hWle (by positivity)
_ = _ := by ring
exact le_of_mul_le_mul_right h2 hP
/-- Proof of `prop:fa-pd-tight`: "a trial for `k = 2L` accepts only if its sample lies in `S*`", for outcomes
whose samples have their nominal sizes; the accepting trial also has `g ≤ θ`. -/
theorem pd_tight_accepts (L : ℕ) (ψ Γ κ : ℝ)
(o : Slot (Fintype.card (Fin L × Fin 6)) (2 * L) ψ Γ κ → Finset (Fin L × Fin 6))
(ho : ∀ j, (o j).card = (j.1.1 : ℕ))
(hA : Accepts (IsPairedDom (dstarGraph L)) (pdG (dstarGraph L)) (2 * L) ψ Γ κ o) :
∃ j, o j ⊆ Sstar L ∧ pdG (dstarGraph L) (o j) (2 * L - j.1.1) ≤ ((j.1.2 : ℕ) : ℝ) := by
obtain ⟨j, hg, Y, hdisj, hY, hsol⟩ := hA
refine ⟨j, ?_, hg⟩
have ht : (j.1.1 : ℕ) ≤ 2 * L := Nat.lt_succ_iff.1 j.1.1.isLt
have hcard : (o j ∪ Y).card ≤ 2 * L := by
rw [card_union_of_disjoint hdisj, ho j]; omega
have := (pd_tight_unique L).2.2 _ hsol hcard
rw [← this]
exact subset_union_left
namespace Aux
/-- For each `L`, the acceptance probability is at most the bound of `prop:fw-necessary`. -/
theorem prob_le (L : ℕ) (ψ' Γ κ : ℝ) (h0 : 0 ≤ ψ') (hΓ : 1 ≤ Γ) (hκ : 0 < κ) :
(trialMeasure (U := Fin L × Fin 6) (2 * L) ψ' Γ κ
{o | Accepts (IsPairedDom (dstarGraph L)) (pdG (dstarGraph L)) (2 * L) ψ' Γ κ o}).toReal
≤ MLSNec.Pnec (6 * L) (2 * L) ψ' Γ κ * (2:ℝ) ^ (ψ' * ((6 * L : ℕ) : ℝ)) *
((((6 * L : ℕ) : ℝ) + 1) * (2:ℝ) ^ (-(ωpr * (6 * L : ℕ)))) := by
have hU := card_dstar L
have hk : 2 * L ≤ Fintype.card (Fin L × Fin 6) := by rw [hU]; omega
have hcard : (Sstar L).card = 2 * L := (pd_tight_unique L).2.1
have hfac := trialMeasure_factor_prob (U := Fin L × Fin 6) (2 * L) hk ψ' Γ κ
set μ := trialMeasure (U := Fin L × Fin 6) (2 * L) ψ' Γ κ with hμ
haveI : MeasureTheory.IsProbabilityMeasure μ := by
rw [hμ]; unfold trialMeasure
have := hfac
infer_instance
set N := {o : Slot (Fintype.card (Fin L × Fin 6)) (2 * L) ψ' Γ κ → Finset (Fin L × Fin 6) |
∃ j, (o j).card ≠ (j.1.1 : ℕ)} with hNdef
set E := {o : Slot (Fintype.card (Fin L × Fin 6)) (2 * L) ψ' Γ κ → Finset (Fin L × Fin 6) |
∃ j, o j ⊆ Sstar L ∧ pdG (dstarGraph L) (o j) (2 * L - j.1.1) ≤ ((j.1.2 : ℕ) : ℝ)}
with hEdef
have hN : μ N = 0 := MLSNec.trialMeasure_card_null (2 * L) ψ' Γ κ
have hsub : {o | Accepts (IsPairedDom (dstarGraph L)) (pdG (dstarGraph L)) (2 * L) ψ' Γ κ o}
⊆ N ∪ E := by
intro o ho
by_cases h : ∃ j, (o j).card ≠ (j.1.1 : ℕ)
· exact Or.inl h
· push Not at h
exact Or.inr (pd_tight_accepts L ψ' Γ κ o h ho)
have hle : μ {o | Accepts (IsPairedDom (dstarGraph L)) (pdG (dstarGraph L)) (2 * L) ψ' Γ κ o}
≤ μ E := by
calc μ {o | Accepts (IsPairedDom (dstarGraph L)) (pdG (dstarGraph L)) (2 * L) ψ' Γ κ o}
≤ μ (N ∪ E) := MeasureTheory.measure_mono hsub
_ ≤ μ N + μ E := MeasureTheory.measure_union_le N E
_ = μ E := by rw [hN, zero_add]
have hB : ∀ t ≤ (Sstar L).card, mu (pdG (dstarGraph L)) (Sstar L) (2 * L) t /
((Fintype.card (Fin L × Fin 6)).choose t : ℝ)
≤ (((6 * L : ℕ) : ℝ) + 1) * (2:ℝ) ^ (-(ωpr * (6 * L : ℕ))) := by
intro t ht
rw [hU]
exact pd_tight_moments L t (hcard ▸ ht)
have hnec := MLSNec.mls_necessary (pdG (dstarGraph L)) (2 * L) hk ψ' Γ κ h0 hΓ hκ (Sstar L)
hcard.le _ hB
calc (μ {o | Accepts (IsPairedDom (dstarGraph L)) (pdG (dstarGraph L)) (2 * L) ψ' Γ κ o}).toReal
≤ (μ E).toReal := ENNReal.toReal_mono (MeasureTheory.measure_ne_top μ E) hle
_ ≤ MLSNec.Pnec (Fintype.card (Fin L × Fin 6)) (2 * L) ψ' Γ κ *
(2:ℝ) ^ (ψ' * (Fintype.card (Fin L × Fin 6) : ℝ)) *
((((6 * L : ℕ) : ℝ) + 1) * (2:ℝ) ^ (-(ωpr * (6 * L : ℕ)))) := hnec
_ = _ := by rw [hU]
end Aux
/-- `prop:fa-pd-tight`, last claim, for the trial model of `MLS`. -/
theorem pd_tight_prob (ψ' Γ κ : ℝ) (h0 : 0 ≤ ψ') (hψ : ψ' < ωpr) (hΓ : 1 ≤ Γ) (hκ : 0 < κ) :
Filter.Tendsto
(fun L : ℕ => (trialMeasure (U := Fin L × Fin 6) (2 * L) ψ' Γ κ
{o | Accepts (IsPairedDom (dstarGraph L)) (pdG (dstarGraph L)) (2 * L) ψ' Γ κ o}).toReal)
Filter.atTop (nhds 0) := by
set a : ℝ := 6 * ψ' with ha_def
set b : ℝ := Real.logb 2 Γ + 3 with hb_def
have hlogΓ : 0 ≤ Real.logb 2 Γ := Real.logb_nonneg (by norm_num) hΓ
have ha : 0 ≤ a := by rw [ha_def]; linarith
have hb : 0 ≤ b := by rw [hb_def]; linarith
set r : ℝ := (2:ℝ) ^ (6 * (ψ' - ωpr)) with hr_def
have hr0 : 0 < r := by positivity
have hr1 : r < 1 := Real.rpow_lt_one_of_one_lt_of_neg (by norm_num) (by linarith)
set C : ℝ := 8 * Γ * 2 * (a + b) * (κ * (a + b) + 1) * 7 with hC_def
have hbound : ∀ L : ℕ, (trialMeasure (U := Fin L × Fin 6) (2 * L) ψ' Γ κ
{o | Accepts (IsPairedDom (dstarGraph L)) (pdG (dstarGraph L)) (2 * L) ψ' Γ κ o}).toReal
≤ C * (((L : ℝ) + 1) ^ 4 * r ^ L) := by
intro L
refine (Aux.prob_le L ψ' Γ κ h0 hΓ hκ).trans ?_
unfold MLSNec.Pnec
set Θ := cap (6 * L) ψ' Γ with hΘ
have hx : 0 ≤ ψ' * ((6 * L : ℕ) : ℝ) + Real.logb 2 Γ := add_nonneg (by positivity) hlogΓ
have hc := Nat.ceil_lt_add_one hx
have hΘr : (Θ : ℝ) < ψ' * ((6 * L : ℕ) : ℝ) + Real.logb 2 Γ + 2 := by
rw [hΘ]; unfold cap; push_cast at hc ⊢; linarith
have hL0 : (0:ℝ) ≤ L := Nat.cast_nonneg _
have e2 : (Θ : ℝ) + 1 ≤ (a + b) * ((L : ℝ) + 1) := by
rw [ha_def, hb_def]
push_cast at hΘr
nlinarith [mul_nonneg hb hL0]
have e1 : ((2 * L : ℕ) : ℝ) + 1 ≤ 2 * ((L : ℝ) + 1) := by push_cast; linarith
have e3 : κ * ((Θ : ℝ) + 1) + 1 ≤ (κ * (a + b) + 1) * ((L : ℝ) + 1) := by
nlinarith [mul_le_mul_of_nonneg_left e2 hκ.le]
have e4 : ((6 * L : ℕ) : ℝ) + 1 ≤ 7 * ((L : ℝ) + 1) := by push_cast; linarith
have p0 : (0:ℝ) ≤ 8 * Γ := by linarith
have p2 : (0:ℝ) ≤ (Θ : ℝ) + 1 := by positivity
have p3 : (0:ℝ) ≤ κ * ((Θ : ℝ) + 1) + 1 := by
have := mul_nonneg hκ.le p2; linarith
have p4 : (0:ℝ) ≤ ((6 * L : ℕ) : ℝ) + 1 := by positivity
have hy1 : (0:ℝ) ≤ 2 * ((L : ℝ) + 1) := by positivity
have hy2 : (0:ℝ) ≤ (a + b) * ((L : ℝ) + 1) := mul_nonneg (by linarith) (by positivity)
have hy3 : (0:ℝ) ≤ (κ * (a + b) + 1) * ((L : ℝ) + 1) := by
have := mul_nonneg hκ.le (add_nonneg ha hb)
exact mul_nonneg (by linarith) (by positivity)
have q1 : 8 * Γ * (((2 * L : ℕ) : ℝ) + 1) ≤ 8 * Γ * (2 * ((L : ℝ) + 1)) :=
mul_le_mul_of_nonneg_left e1 p0
have q2 := mul_le_mul q1 e2 p2 (mul_nonneg p0 hy1)
have q3 := mul_le_mul q2 e3 p3 (mul_nonneg (mul_nonneg p0 hy1) hy2)
have q4 := mul_le_mul q3 e4 p4 (mul_nonneg (mul_nonneg (mul_nonneg p0 hy1) hy2) hy3)
have hexp : (2:ℝ) ^ (ψ' * ((6 * L : ℕ) : ℝ)) * (2:ℝ) ^ (-(ωpr * ((6 * L : ℕ) : ℝ))) = r ^ L := by
rw [← Real.rpow_add (by norm_num), hr_def, ← Real.rpow_natCast, ← Real.rpow_mul (by norm_num)]
congr 1; push_cast; ring
calc _ = (8 * Γ * (((2 * L : ℕ) : ℝ) + 1) * ((Θ : ℝ) + 1) * (κ * ((Θ : ℝ) + 1) + 1) *
(((6 * L : ℕ) : ℝ) + 1)) * r ^ L := by rw [← hexp]; ring
_ ≤ (8 * Γ * (2 * ((L : ℝ) + 1)) * ((a + b) * ((L : ℝ) + 1)) *
((κ * (a + b) + 1) * ((L : ℝ) + 1)) * (7 * ((L : ℝ) + 1))) * r ^ L :=
mul_le_mul_of_nonneg_right q4 (pow_nonneg hr0.le _)
_ = C * (((L : ℝ) + 1) ^ 4 * r ^ L) := by rw [hC_def]; ring
have hlim : Filter.Tendsto (fun L : ℕ => C * (((L : ℝ) + 1) ^ 4 * r ^ L)) Filter.atTop
(nhds 0) := by
have h1 := tendsto_pow_const_mul_const_pow_of_abs_lt_one 4 (r := r)
(by rw [abs_of_pos hr0]; exact hr1)
have h2 := h1.comp (Filter.tendsto_add_atTop_nat 1)
have h3 : Filter.Tendsto (fun L : ℕ => (((L + 1 : ℕ) : ℝ) ^ 4 * r ^ (L + 1)) * r⁻¹)
Filter.atTop (nhds (0 * r⁻¹)) := h2.mul_const _
rw [zero_mul] at h3
have h4 := h3.const_mul C
rw [mul_zero] at h4
refine h4.congr fun L => ?_
show C * ((((L + 1 : ℕ) : ℝ) ^ 4 * r ^ (L + 1)) * r⁻¹) = C * (((L : ℝ) + 1) ^ 4 * r ^ L)
rw [pow_succ r L, Nat.cast_add, Nat.cast_one,
show ((L : ℝ) + 1) ^ 4 * (r ^ L * r) * r⁻¹ = ((L : ℝ) + 1) ^ 4 * r ^ L * (r * r⁻¹) by ring,
mul_inv_cancel₀ hr0.ne', mul_one]
exact squeeze_zero (fun L => ENNReal.toReal_nonneg) hbound hlim
/-- `prop:fa-pd-tight`, assembled. -/
theorem fa_pd_tight :
(0 < ystar ∧
(∀ y : ℝ, 0 < y → DifferentiableAt ℝ (hpd 6) y) ∧
(∀ y : ℝ, 0 < y → (deriv (hpd 6) y = 0 ↔ y = ystar)) ∧
0 ≤ ystar ∧ ∀ y : ℝ, 0 ≤ y → ωpr ≤ hpd 6 y) ∧
(∀ L : ℕ, IsPairedDom (dstarGraph L) (Sstar L) ∧ (Sstar L).card = 2 * L ∧
∀ S : Finset (Fin L × Fin 6), IsPairedDom (dstarGraph L) S → S.card ≤ 2 * L →
S = Sstar L) ∧
∀ ψ' Γ κ : ℝ, 0 ≤ ψ' → ψ' < ωpr → 1 ≤ Γ → 0 < κ →
Filter.Tendsto
(fun L : ℕ => (trialMeasure (U := Fin L × Fin 6) (2 * L) ψ' Γ κ
{o | Accepts (IsPairedDom (dstarGraph L)) (pdG (dstarGraph L)) (2 * L) ψ' Γ κ o}).toReal)
Filter.atTop (nhds 0) :=
⟨⟨pd_tight_crit.1, pd_tight_crit.2.1, pd_tight_crit.2.2, pd_tight_min.1, pd_tight_min.2⟩,
pd_tight_unique, fun ψ' Γ κ h0 hψ hΓ hκ => pd_tight_prob ψ' Γ κ h0 hψ hΓ hκ⟩
end Tight
namespace Examples
/-- E1: `pd_rate_W` for one double star. -/
theorem ex1_rate_W :
(1 + ystar) ^ Fintype.card (Fin 1 × Fin 6) *
(2:ℝ) ^ (-(ωpr * Fintype.card (Fin 1 × Fin 6)))
≤ pdW (dstarGraph 1) (Sstar 1) ystar :=
pd_rate_W (dstarGraph 1) (dstarGraph_noIsolated 1) (Sstar 1) (pd_tight_unique 1).1
def dsAnc (p : Fin 1 × Fin 6) : Fin 1 × Fin 6 := (p.1, if p.2.val ≤ 3 then 0 else 1)
theorem ex2_point :
IsPairing (dstarGraph 1) (Sstar 1) {((0, 0), (0, 1))} ∧
IsAnchor (dstarGraph 1) (Sstar 1) dsAnc ∧
ancDeg (Sstar 1) dsAnc (0, 0) = 2 ∧ ancDeg (Sstar 1) dsAnc (0, 1) = 2 ∧
∀ y : ℝ, 0 ≤ y →
∏ q ∈ ({((0, 0), (0, 1))} : Finset ((Fin 1 × Fin 6) × (Fin 1 × Fin 6))),
Ωpair y (ancDeg (Sstar 1) dsAnc q.1) (ancDeg (Sstar 1) dsAnc q.2)
≤ pdW (dstarGraph 1) (Sstar 1) y := by
have hcov : ∀ w : Fin 1 × Fin 6, w ∈ Sstar 1 → w = (0, 0) ∨ w = (0, 1) := by decide
have hP : IsPairing (dstarGraph 1) (Sstar 1) {((0, 0), (0, 1))} := by
refine ⟨?_, ?_⟩
· intro q hq
rw [Finset.mem_singleton] at hq
subst hq
exact ⟨by decide, by decide, by decide⟩
· intro w hw
refine ⟨((0, 0), (0, 1)), ⟨Finset.mem_singleton_self _, ?_⟩, ?_⟩
· rcases hcov w hw with rfl | rfl
· exact Or.inl rfl
· exact Or.inr rfl
· intro q hq
exact Finset.mem_singleton.1 hq.1
have ha : IsAnchor (dstarGraph 1) (Sstar 1) dsAnc := by
unfold IsAnchor
decide
refine ⟨hP, ha, by decide, by decide, (pd_point (dstarGraph 1) (Sstar 1) _ hP dsAnc ha).2⟩
def pathG : SimpleGraph (Fin 6) := SimpleGraph.fromRel fun i j => j.val = i.val + 1
instance instDecidableRelPathG : DecidableRel pathG.Adj :=
inferInstanceAs (DecidableRel (SimpleGraph.fromRel fun i j : Fin 6 => j.val = i.val + 1).Adj)
def pathAnc (v : Fin 6) : Fin 6 := if v = 0 then 1 else if v = 5 then 4 else v
theorem ex3_path :
IsPairing pathG {1, 2, 3, 4} {(1, 2), (3, 4)} ∧ IsAnchor pathG {1, 2, 3, 4} pathAnc ∧
(und pathG {2}).card = 3 ∧ pdRhs {1, 2, 3, 4} {(1, 2), (3, 4)} pathAnc {2} = 4 := by
have hP : IsPairing pathG {1, 2, 3, 4} {(1, 2), (3, 4)} := by
refine ⟨by decide, ?_⟩
have key : ∀ w ∈ ({1, 2, 3, 4} : Finset (Fin 6)),
∃ q ∈ ({(1, 2), (3, 4)} : Finset (Fin 6 × Fin 6)),
(q.1 = w ∨ q.2 = w) ∧
∀ q' ∈ ({(1, 2), (3, 4)} : Finset (Fin 6 × Fin 6)),
(q'.1 = w ∨ q'.2 = w) → q' = q := by decide
intro w hw
obtain ⟨q, hq, hcov, huniq⟩ := key w hw
exact ⟨q, ⟨hq, hcov⟩, fun q' hq' => huniq q' hq'.1 hq'.2⟩
have ha : IsAnchor pathG {1, 2, 3, 4} pathAnc := by
unfold IsAnchor
decide
exact ⟨hP, ha, by decide, by decide⟩
/-- E4: `pd_tight_prob` at `ψ' = 7/10`, `Γ = 2`, `κ = 1`. -/
theorem ex4_tight_prob :
Filter.Tendsto
(fun L : ℕ => (trialMeasure (U := Fin L × Fin 6) (2 * L) (7 / 10) 2 1
{o | Accepts (IsPairedDom (dstarGraph L)) (pdG (dstarGraph L)) (2 * L) (7 / 10) 2 1 o}).toReal)
Filter.atTop (nhds 0) :=
pd_tight_prob (7 / 10) 2 1 (by norm_num) (lt_of_lt_of_le (by norm_num) pd_rate.2.1) (by norm_num)
one_pos
/-- E5: the event of (c) is not null by construction. -/
theorem ex5_success (L : ℕ) :
1 - Real.exp (-1) ≤
(trialMeasure (U := Fin L × Fin 6) (Sstar L).card (70502 / 10 ^ 5) 1 1
{o | Accepts (IsPairedDom (dstarGraph L)) (pdG (dstarGraph L)) (Sstar L).card
(70502 / 10 ^ 5) 1 1 o}).toReal :=
pd_success (dstarGraph L) (Sstar L) (pd_tight_unique L).1 1 one_pos
/-- E6: the boundary `ψ' = ψ_pr`. -/
theorem ex6_boundary (L : ℕ) :
1 - Real.exp (-1) ≤
(trialMeasure (U := Fin L × Fin 6) (2 * L) ωpr 1 1
{o | Accepts (IsPairedDom (dstarGraph L)) (pdG (dstarGraph L)) (2 * L) ωpr 1 1 o}).toReal := by
have hcard := (pd_tight_unique L).2.1
have hU : 2 * L ≤ Fintype.card (Fin L × Fin 6) := by
rw [Fintype.card_prod, Fintype.card_fin, Fintype.card_fin]; omega
have hω : 0 ≤ ωpr := le_trans (by norm_num) pd_rate.2.1
apply MLS.mls_success (IsPairedDom (dstarGraph L)) (pdG (dstarGraph L))
(fun _ _ => Nat.cast_nonneg _) (2 * L) hU ωpr 1 1 hω le_rfl one_pos (Sstar L)
(pd_tight_unique L).1 hcard
apply MLS.star_of_W (pdG (dstarGraph L)) (Sstar L) (2 * L) hcard ωpr 1 ystar one_pos
pd_tight_min.1
rw [div_one]
have := pd_rate_W (dstarGraph L) (dstarGraph_noIsolated L) (Sstar L) (pd_tight_unique L).1
unfold pdW at this
rw [hcard] at this
exact this
end Examples
end MaxLeafFormal.PDGraph
Back to top