MaxLeafFormal.RSCheck
Source file MaxLeafFormal/RSCheck.lean of the Lean project (how it is built).
import MaxLeafFormal.EncloseH
/-!
# RS closed-form rate: the function and the interval checker
`F*(σ) = H(σ) + (1 - σ) log(1 - 2^{-1/σ})` (`eq:rs-F`), and the checker used by the
generated covers `RSCover*.lean`. On `[a, b] ⊆ (0, 1)` the three summands are bounded by
monotonicity, in natural logarithms:
`-σ ln σ ≤ b (-ln a)`, `-(1-σ) ln(1-σ) ≤ (1-a)(-ln(1-b))`,
`(1-σ) ln(1 - 2^{-1/σ}) ≤ (1-b) ln(1 - 2^{-1/a})`, with the rational enclosures of
`MaxLeafFormal.Enclose` at the endpoints. The sum is compared with `T · ln 2`.
The main theorems are in `RSRate.lean`.
-/
namespace MaxLeafFormal.RSRate
open Enclose
/-- The rational `a / b`. -/
def q (a b : ℕ) : ℚ := (a : ℚ) / b
/-- `F*`, the second expression of `eq:rs-F`, for every real `σ`. -/
noncomputable def rsF (σ : ℝ) : ℝ := MLS.H2 σ + (1 - σ) * Real.logb 2 (1 - (2:ℝ) ^ (-1 / σ))
/-- Series terms of the logarithms and of the exponential, and the rounding precision. -/
def nL : ℕ := 32
def nE : ℕ := 12
def pr : ℕ := 40
/-- One interval `[a, b]` with target `T`: the monotone bound of `F* · ln 2` on `[a, b]` lies below
`T` times a lower bound of `ln 2`. -/
def cellOK (T a b : ℚ) : Bool :=
let L2 := ln2Q nL pr
let LA := (lnQ a nL pr).lo
let LB := (lnQ (1 - b) nL pr).lo
let PL := (expQ (-L2.hi / a) nE pr).lo
let U := (lnQ (1 - PL) nL pr).hi
decide (0 ≤ T) && decide (0 < a) && decide (a < b) && decide (b < 1) && decide (PL < 1) &&
decide (U ≤ 0) && decide (b * (-LA) + (1 - a) * (-LB) + (1 - b) * U < T * L2.lo)
/-- A chain of consecutive intervals `[a, b₁], [b₁, b₂], …, [b_{k-1}, e]`, given by their right
ends `b₁, …, b_k`; the last right end must be `e`. -/
def checkCover (T e : ℚ) : ℚ → List ℚ → Bool
| _, [] => false
| a, [b] => cellOK T a b && decide (b = e)
| a, b :: c :: rest => cellOK T a b && checkCover T e b (c :: rest)
/-- `rsF σ · ln 2 = binEntropy σ + (1 - σ) ln (1 - 2^{-1/σ})`. -/
theorem rsF_mul_log2 (σ : ℝ) :
rsF σ * Real.log 2 = Real.binEntropy σ + (1 - σ) * Real.log (1 - (2:ℝ) ^ (-1 / σ)) := by
have h2 : Real.log 2 ≠ 0 := (Real.log_pos (by norm_num : (1:ℝ) < 2)).ne'
unfold rsF MLS.H2 Real.logb
field_simp
theorem cellOK_sound {T a b : ℚ} (h : cellOK T a b = true) {σ : ℝ}
(hσ : σ ∈ Set.Icc (a : ℝ) b) : rsF σ < T := by
unfold cellOK at h
simp only [Bool.and_eq_true, decide_eq_true_eq] at h
obtain ⟨⟨⟨⟨⟨⟨hT, ha⟩, hab⟩, hb⟩, hPL⟩, hU0⟩, hB⟩ := h
set L2 := ln2Q nL pr with hL2def
set LA := (lnQ a nL pr).lo with hLAdef
set LB := (lnQ (1 - b) nL pr).lo with hLBdef
set PL := (expQ (-L2.hi / a) nE pr).lo with hPLdef
set U := (lnQ (1 - PL) nL pr).hi with hUdef
obtain ⟨hσa, hσb⟩ := hσ
-- enclosures
have hL2 : L2.Contains (Real.log 2) := ln2Q_sound nL pr
have hLA : (LA : ℝ) ≤ Real.log a := (lnQ_sound ha nL pr).1
have hb1 : (0 : ℚ) < 1 - b := by linarith
have hLB : (LB : ℝ) ≤ Real.log ((1 - b : ℚ) : ℝ) := (lnQ_sound hb1 nL pr).1
have hPL1 : (0 : ℚ) < 1 - PL := by linarith
have hU : Real.log ((1 - PL : ℚ) : ℝ) ≤ U := (lnQ_sound hPL1 nL pr).2
have hPLe : (PL : ℝ) ≤ Real.exp ((-L2.hi / a : ℚ) : ℝ) := (expQ_sound (-L2.hi / a) nE pr).1
-- real facts
have ha' : (0 : ℝ) < a := by exact_mod_cast ha
have hb' : (b : ℝ) < 1 := by exact_mod_cast hb
have hσ0 : 0 < σ := lt_of_lt_of_le ha' hσa
have hσ1 : σ < 1 := lt_of_le_of_lt hσb hb'
have hlog2 : 0 < Real.log 2 := Real.log_pos (by norm_num)
-- first summand: -σ ln σ ≤ b (-LA)
have t1 : -σ * Real.log σ ≤ (b : ℝ) * (-(LA : ℝ)) := by
have e1 : Real.log a ≤ Real.log σ := Real.log_le_log ha' hσa
have e2 : Real.log σ ≤ 0 := Real.log_nonpos hσ0.le hσ1.le
have e3 : 0 ≤ -(LA : ℝ) := by linarith
have e4 : -Real.log σ ≤ -(LA : ℝ) := by linarith
calc -σ * Real.log σ = σ * (-Real.log σ) := by ring
_ ≤ σ * (-(LA : ℝ)) := mul_le_mul_of_nonneg_left e4 hσ0.le
_ ≤ (b : ℝ) * (-(LA : ℝ)) := mul_le_mul_of_nonneg_right hσb e3
-- second summand: -(1-σ) ln(1-σ) ≤ (1-a)(-LB)
have t2 : -(1 - σ) * Real.log (1 - σ) ≤ (1 - (a : ℝ)) * (-(LB : ℝ)) := by
have hcb : ((1 - b : ℚ) : ℝ) = 1 - (b : ℝ) := by push_cast; ring
rw [hcb] at hLB
have e1 : Real.log (1 - (b : ℝ)) ≤ Real.log (1 - σ) :=
Real.log_le_log (by linarith) (by linarith)
have e2 : Real.log (1 - σ) ≤ 0 := Real.log_nonpos (by linarith) (by linarith)
have e3 : 0 ≤ -(LB : ℝ) := by linarith
have e4 : -Real.log (1 - σ) ≤ -(LB : ℝ) := by linarith
calc -(1 - σ) * Real.log (1 - σ) = (1 - σ) * (-Real.log (1 - σ)) := by ring
_ ≤ (1 - σ) * (-(LB : ℝ)) := mul_le_mul_of_nonneg_left e4 (by linarith)
_ ≤ (1 - (a : ℝ)) * (-(LB : ℝ)) := mul_le_mul_of_nonneg_right (by linarith) e3
-- third summand: (1-σ) ln(1 - 2^{-1/σ}) ≤ (1-b) U
have t3 : (1 - σ) * Real.log (1 - (2:ℝ) ^ (-1 / σ)) ≤ (1 - (b : ℝ)) * U := by
have hp : (2:ℝ) ^ (-1 / σ) = Real.exp (Real.log 2 * (-1 / σ)) :=
Real.rpow_def_of_pos (by norm_num) _
have hU0' : (U : ℝ) ≤ 0 := by exact_mod_cast hU0
have hhi : Real.log 2 ≤ (L2.hi : ℝ) := hL2.2
-- PL ≤ 2^{-1/σ}
have c1 : ((-L2.hi / a : ℚ) : ℝ) ≤ Real.log 2 * (-1 / σ) := by
push_cast
have f1 : -(L2.hi : ℝ) / a ≤ -Real.log 2 / a :=
div_le_div_of_nonneg_right (by linarith) ha'.le
have f2 : -Real.log 2 / a ≤ -Real.log 2 / σ := by
rw [div_le_div_iff₀ ha' hσ0]
nlinarith
have f3 : Real.log 2 * (-1 / σ) = -Real.log 2 / σ := by ring
linarith
have hPp : (PL : ℝ) ≤ (2:ℝ) ^ (-1 / σ) := by
rw [hp]; exact hPLe.trans (Real.exp_le_exp.mpr c1)
have hp1 : (2:ℝ) ^ (-1 / σ) < 1 := by
rw [hp, Real.exp_lt_one_iff]
have : -1 / σ < 0 := by rw [neg_div]; exact neg_neg_of_pos (by positivity)
nlinarith
have g1 : Real.log (1 - (2:ℝ) ^ (-1 / σ)) ≤ Real.log ((1 - PL : ℚ) : ℝ) := by
push_cast
exact Real.log_le_log (by linarith) (by linarith)
have g2 : Real.log (1 - (2:ℝ) ^ (-1 / σ)) ≤ U := g1.trans hU
calc (1 - σ) * Real.log (1 - (2:ℝ) ^ (-1 / σ)) ≤ (1 - σ) * U :=
mul_le_mul_of_nonneg_left g2 (by linarith)
_ ≤ (1 - (b : ℝ)) * U := mul_le_mul_of_nonpos_right (by linarith) hU0'
-- assemble
have hBr : (b : ℝ) * (-(LA : ℝ)) + (1 - (a : ℝ)) * (-(LB : ℝ)) + (1 - (b : ℝ)) * U
< (T : ℝ) * L2.lo := by exact_mod_cast hB
have hTl : (T : ℝ) * L2.lo ≤ (T : ℝ) * Real.log 2 :=
mul_le_mul_of_nonneg_left hL2.1 (by exact_mod_cast hT)
have hent : Real.binEntropy σ = -σ * Real.log σ + -(1 - σ) * Real.log (1 - σ) := by
rw [Real.binEntropy_eq_negMulLog_add_negMulLog_one_sub]
simp only [Real.negMulLog]
have key : rsF σ * Real.log 2 < (T : ℝ) * Real.log 2 := by
rw [rsF_mul_log2, hent]
linarith
exact lt_of_mul_lt_mul_right key hlog2.le
theorem checkCover_sound_aux {T e : ℚ} :
∀ (l : List ℚ) (a : ℚ), checkCover T e a l = true →
∀ σ ∈ Set.Icc (a : ℝ) e, rsF σ ≤ T := by
intro l
induction l with
| nil => intro a h; simp [checkCover] at h
| cons b rest ih =>
intro a h σ hσ
cases rest with
| nil =>
simp only [checkCover, Bool.and_eq_true, decide_eq_true_eq] at h
obtain ⟨hc, rfl⟩ := h
exact (cellOK_sound hc hσ).le
| cons c rest' =>
simp only [checkCover, Bool.and_eq_true] at h
obtain ⟨hc, hr⟩ := h
rcases le_total σ b with hσb | hσb
· exact (cellOK_sound hc ⟨hσ.1, hσb⟩).le
· exact ih b hr σ ⟨hσb, hσ.2⟩
/-- A checked cover proves the bound on the whole range. -/
theorem checkCover_sound {T e a : ℚ} {l : List ℚ} (h : checkCover T e a l = true) :
∀ σ ∈ Set.Icc (a : ℝ) e, rsF σ ≤ T :=
checkCover_sound_aux l a h
end MaxLeafFormal.RSRate
Back to top