Skip to content

Commit 64de71c

Browse files
authored
Merge pull request #5 from zkcrypto/port-fundamentals-to-lean4
Port fundamentals to Lean 4
2 parents ad1019f + 46fdfa8 commit 64de71c

7 files changed

Lines changed: 480 additions & 512 deletions

File tree

Lines changed: 245 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,245 @@
1+
/-
2+
Copyright (c) 2021 Joey Lupo
3+
Released under Apache 2.0 license as described in the file LICENSE-APACHE.
4+
Authors: Joey Lupo
5+
-/
6+
import Mathlib.Analysis.SpecialFunctions.Log.Basic
7+
import Mathlib.Analysis.SpecialFunctions.Pow.NNReal
8+
import Mathlib.Analysis.SpecialFunctions.Pow.Real
9+
import Mathlib.Data.Nat.Basic
10+
import Mathlib.Data.Real.Basic
11+
import Mathlib.Tactic.Cases
12+
import Mathlib.Tactic.Monotonicity
13+
14+
/-!
15+
# Negligible functions.
16+
17+
This file defines negligible functions and provides several useful lemmas regarding
18+
negligible functions.
19+
20+
TO-DO connect with security parameter, (or not, as in Nowak),
21+
and refactor proofs/improve variable naming
22+
-/
23+
24+
/-
25+
A function f : ℤ≥1 → ℝ is called negligible if
26+
for all c ∈ ℝ>0 there exists n₀ ∈ ℤ≥1 such that
27+
n₀ ≤ n → |f(n)| < 1/n^c
28+
-/
29+
def negligible (f : ℕ → ℝ) :=
30+
∀ c > 0, ∃ n₀, ∀ n,
31+
n₀ ≤ n → abs (f n) < 1 / (n : ℝ)^c
32+
33+
def negligible' (f : ℕ → ℝ) :=
34+
∀ (c : ℝ), ∃ (n₀ : ℕ), ∀ (n : ℕ),
35+
0 < c → n₀ ≤ n → abs (f n) < 1 / n^c
36+
37+
lemma negl_equiv (f : ℕ → ℝ) : negligible f ↔ negligible' f := by
38+
constructor
39+
{-- Forward direction
40+
intros h c
41+
have arch := exists_nat_gt c
42+
cases' arch with k hk
43+
let k₀ := max k 1
44+
have k_leq_k₀ : k ≤ k₀ := le_max_left k 1
45+
have kr_leq_k₀r : (k:ℝ) ≤ k₀ := Nat.cast_le.mpr k_leq_k₀
46+
have k₀_pos : 0 < k₀ := by {apply le_max_right k 1}
47+
have a := h k₀ k₀_pos
48+
49+
-- use k₀
50+
-- intros n c_pos hn
51+
-- have hnnn : k ≤ n := by linarith
52+
53+
cases' a with n' hn₀
54+
let n₀ := max n' 1
55+
have n₀_pos : 0 < n₀ := by apply le_max_right n' 1
56+
have n'_leq_n₀ : n' ≤ n₀ := le_max_left n' 1
57+
use n₀
58+
intros n c_pos hn
59+
have hnnn : n' ≤ n := by linarith
60+
61+
have b : (n : ℝ)^c ≤ (n : ℝ)^(k₀ : ℝ) := by
62+
apply Real.rpow_le_rpow_of_exponent_le
63+
norm_cast
64+
linarith
65+
linarith
66+
have daf : (n : ℝ)^(k₀ : ℝ) = (n : ℝ)^k₀ := (n : ℝ).rpow_natCast k₀
67+
rw [daf] at b
68+
have d : 1 / (n : ℝ)^k₀ ≤ 1 / n^c := by
69+
apply one_div_le_one_div_of_le
70+
{ -- Proving 0 < (n:ℝ) ^ c
71+
apply Real.rpow_pos_of_pos
72+
norm_cast
73+
linarith
74+
}
75+
{exact b}
76+
have goal : abs (f n) < 1 / n^c :=
77+
calc
78+
abs (f n) < 1 / (n : ℝ)^k₀ := hn₀ n hnnn
79+
_ ≤ 1 / n^c := d
80+
exact goal
81+
}
82+
83+
{-- Reverse direction
84+
intros h c hc
85+
cases' h c with n₀ hn₀
86+
use n₀
87+
intros n hn
88+
have goal := hn₀ n (Nat.cast_pos.mpr hc) hn
89+
rw [(n : ℝ).rpow_natCast c] at goal
90+
exact goal
91+
}
92+
93+
lemma zero_negl : negligible (λ_ => 0) := by
94+
intros c hc
95+
use 1
96+
intros n hn
97+
norm_num
98+
apply pow_pos
99+
have h : 0 < n := by linarith
100+
exact Nat.cast_pos.mpr h
101+
102+
lemma negl_add_negl_negl {f g : ℕ → ℝ} : negligible f → negligible g → negligible (f + g) := by
103+
intros hf hg
104+
intros c hc
105+
have hc1 : (c+1) > 0 := Nat.lt.step hc
106+
have hf2 := hf (c+1) hc1
107+
have hg2 := hg (c+1) hc1
108+
cases' hf2 with nf hnf
109+
cases' hg2 with ng hng
110+
let n₀ := max (max nf ng) 2
111+
use n₀
112+
intros n hn
113+
let nr := (n:ℝ)
114+
have n_eq_nr : (n:ℝ) = nr := by rfl
115+
116+
have tn : max nf ng ≤ n₀ := le_max_left (max nf ng) 2
117+
have t2n₀ : 2 ≤ n₀ := le_max_right (max nf ng) 2
118+
have t2n : 2 ≤ n := by linarith
119+
have t2nr : 2 ≤ nr := by
120+
-- have j := Nat.cast_le.mpr t2n
121+
-- rw [n_eq_nr] at j
122+
-- norm_num at j
123+
-- exact j
124+
-- exact is_R_or_C.char_zero_R_or_C
125+
simp_all only [Nat.ofNat_le_cast, t2n, nr]
126+
have tnr_pos : 0 < nr := by linarith
127+
128+
have t2na : (1 / nr) * (1/nr^c) ≤ (1 / (2 : ℝ)) * (1 / nr^c) := by
129+
have ht2 : 0 < (1 / nr^c) := by {apply one_div_pos.mpr; exact pow_pos tnr_pos c}
130+
apply (mul_le_mul_right ht2).mpr
131+
apply one_div_le_one_div_of_le
132+
exact zero_lt_two
133+
exact t2nr
134+
135+
have tnr2 : 1 / nr^(c + 1) ≤ (1 / (2 : ℝ)) * (1 / nr^c) :=
136+
calc
137+
1 / nr ^ (c + 1) = (1 / nr)^(c + 1) := by rw [one_div_pow]
138+
_ = (1 / nr)^c * (1 / nr) := pow_succ (1 / nr) c
139+
_ = (1 / nr) * (1 / nr)^c := by ac_nf
140+
_ = (1 / nr) * (1 / nr^c) := by rw [one_div_pow]
141+
_ ≤ (1 / (2 : ℝ)) * (1 / nr^c) := t2na
142+
143+
have tnf : nf ≤ n :=
144+
calc
145+
nf ≤ n₀ := le_of_max_le_left tn
146+
_ ≤ n := hn
147+
have tfn := hnf n tnf
148+
have tf : abs (f n) < (1 / (2 : ℝ)) * (1 / nr^c) := by linarith
149+
150+
have tng : ng ≤ n :=
151+
calc ng ≤ n₀ := le_of_max_le_right tn
152+
_ ≤ n := hn
153+
have tgn := hng n tng
154+
have tg : abs (g n) < (1/(2:ℝ)) * (1/nr^c) := by linarith
155+
156+
have goal : abs ((f + g) n) < 1 / nr ^ c :=
157+
calc
158+
abs ((f + g) n) = abs (f n + g n) := by rw [Pi.add_apply f g n]
159+
_ ≤ abs (f n) + abs (g n) := abs_add (f n) (g n)
160+
_ < (1/(2:ℝ)) * (1/nr^c) + abs (g n) := by linarith
161+
_ < (1/(2:ℝ)) * (1/nr^c) + (1/(2:ℝ)) * (1/nr^c) := by linarith
162+
_ = 1/nr^c := by ring_nf
163+
exact goal
164+
165+
lemma bounded_negl_negl {f g : ℕ → ℝ} (hg : negligible g):
166+
(∀ n, abs (f n) ≤ abs (g n)) → negligible f := by
167+
intro h
168+
intros c hc
169+
have hh := hg c hc
170+
cases' hh with n₀ hn₀
171+
use n₀
172+
intros n hn
173+
have goal : abs (f n) < 1 / (n : ℝ) ^ c :=
174+
calc
175+
abs (f n) ≤ abs (g n) := h n
176+
_ < 1 / (n : ℝ)^c := hn₀ n hn
177+
exact goal
178+
179+
lemma nat_mul_negl_negl {f : ℕ → ℝ} (m : ℕ):
180+
negligible f → negligible (λn => m * (f n)) := by
181+
intros hf
182+
induction' m with k hk
183+
{ -- Base case
184+
norm_num
185+
exact zero_negl
186+
}
187+
{ -- Inductive step
188+
norm_num
189+
have d : (λn => ((k : ℝ) + 1) * (f n)) = (λn => (k : ℝ) * (f n)) + (λn => f n) := by
190+
ring_nf
191+
rfl
192+
rw [d]
193+
apply negl_add_negl_negl
194+
exact hk
195+
exact hf
196+
}
197+
198+
lemma const_mul_negl_negl {f : ℕ → ℝ} (m : ℝ) :
199+
negligible f → negligible (λn => m * (f n)) := by
200+
intro hf
201+
-- Use Archimedian property to get arch : ℕ with abs m < arch
202+
have arch := exists_nat_gt (abs m)
203+
cases' arch with k hk
204+
apply bounded_negl_negl
205+
206+
{ -- Demonstrate a negligible function kf
207+
have kf_negl := nat_mul_negl_negl k hf
208+
exact kf_negl
209+
}
210+
211+
{ -- Show kf bounds mf from above
212+
intro n
213+
have h : abs m ≤ abs (k : ℝ) :=
214+
calc
215+
abs m ≤ (k : ℝ) := le_of_lt hk
216+
_ = abs (k : ℝ) := (Nat.abs_cast k).symm
217+
218+
have goal : abs (m * f n) ≤ abs ((k : ℝ) * f n) :=
219+
calc
220+
abs (m * f n) = abs m * abs (f n) := by rw [abs_mul]
221+
_ ≤ abs (k : ℝ) * abs (f n) := mul_le_mul_of_nonneg_right h (abs_nonneg (f n))
222+
_ = abs ((k : ℝ) * f n) := by rw [<- abs_mul]
223+
224+
exact goal
225+
}
226+
227+
theorem neg_exp_negl : negligible ((λn => (1 : ℝ) / 2^n) : ℕ → ℝ) := by sorry
228+
229+
-- Need to prove lim n^c/2^n = 0 by induction on c using L'Hopital's rule to apply inductive
230+
-- hypothesis
231+
/-
232+
let m := 2
233+
have hm : 0 < 2 := zero_lt_two
234+
have c2_negl := c2_mul_neg_exp_is_negl 2 hm
235+
have r : (λ (n : ℕ) => 16 * (1 / (2 ^ n * 16)): ℕ → ℝ) = ((λn => (1:ℝ)/2^n): ℕ → ℝ) := by
236+
funext
237+
have h : (1:ℝ) / 2^n / 16 = (1:ℝ) / (2^n * 16) := div_div_eq_div_mul 1 (2^n) 16
238+
rw [<- h]
239+
ring_nf
240+
241+
have goal := const_mul_negl_is_negl 16 c2_negl
242+
norm_num at goal
243+
rw [<-r]
244+
exact goal
245+
-/
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
/-
2+
Copyright (c) 2021 Joey Lupo
3+
Released under Apache 2.0 license as described in the file LICENSE-APACHE.
4+
Authors: Joey Lupo
5+
-/
6+
import Cryptolib.ToMathlib
7+
import Mathlib.Probability.Distributions.Uniform
8+
9+
/-!
10+
# Uniform distributions over ZMod q, BitVecs, and finite groups
11+
12+
This file defines the uniform distribution over a finite group as a PMF, including the
13+
special case of Z_q, the integers modulo q.
14+
15+
It also provides two useful lemmas regarding uniform probabilities.
16+
-/
17+
18+
variable (G : Type) [Fintype G] [Nonempty G] [Group G] [DecidableEq G]
19+
20+
noncomputable section
21+
22+
def uniform_bitvec (n : ℕ) : PMF (BitVec n) :=
23+
PMF.uniformOfFintype (BitVec n)
24+
25+
def uniform_grp : PMF G :=
26+
PMF.uniformOfFintype G
27+
28+
#check (uniform_grp G)
29+
30+
def uniform_zmod (n : ℕ) [NeZero n] : PMF (ZMod n) := uniform_grp (ZMod n)
31+
32+
def uniform_2 : PMF (ZMod 2) := uniform_zmod 2
33+
34+
lemma uniform_grp_prob :
35+
∀ (g : G), (uniform_grp G) g = 1 / Fintype.card G := by
36+
intro g
37+
rw [uniform_grp, PMF.uniformOfFintype_apply, inv_eq_one_div]
38+
39+
lemma uniform_zmod_prob {n : ℕ} [NeZero n] :
40+
∀ (a : ZMod n), (uniform_zmod n) a = 1/n := by
41+
intro a
42+
rw [uniform_zmod, uniform_grp, PMF.uniformOfFintype_apply]
43+
simp

0 commit comments

Comments
 (0)