-
Notifications
You must be signed in to change notification settings - Fork 16
/
Copy pathagm-example.py
69 lines (52 loc) · 2.41 KB
/
agm-example.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
from math import exp, sqrt
from scipy.special import erf
def calibrateAnalyticGaussianMechanism(epsilon, delta, GS, tol = 1.e-12):
""" Calibrate a Gaussian perturbation for differential privacy using the analytic Gaussian mechanism of [Balle and Wang, ICML'18]
Arguments:
epsilon : target epsilon (epsilon > 0)
delta : target delta (0 < delta < 1)
GS : upper bound on L2 global sensitivity (GS >= 0)
tol : error tolerance for binary search (tol > 0)
Output:
sigma : standard deviation of Gaussian noise needed to achieve (epsilon,delta)-DP under global sensitivity GS
"""
def Phi(t):
return 0.5*(1.0 + erf(float(t)/sqrt(2.0)))
def caseA(epsilon,s):
return Phi(sqrt(epsilon*s)) - exp(epsilon)*Phi(-sqrt(epsilon*(s+2.0)))
def caseB(epsilon,s):
return Phi(-sqrt(epsilon*s)) - exp(epsilon)*Phi(-sqrt(epsilon*(s+2.0)))
def doubling_trick(predicate_stop, s_inf, s_sup):
while(not predicate_stop(s_sup)):
s_inf = s_sup
s_sup = 2.0*s_inf
return s_inf, s_sup
def binary_search(predicate_stop, predicate_left, s_inf, s_sup):
s_mid = s_inf + (s_sup-s_inf)/2.0
while(not predicate_stop(s_mid)):
if (predicate_left(s_mid)):
s_sup = s_mid
else:
s_inf = s_mid
s_mid = s_inf + (s_sup-s_inf)/2.0
return s_mid
delta_thr = caseA(epsilon, 0.0)
if (delta == delta_thr):
alpha = 1.0
else:
if (delta > delta_thr):
predicate_stop_DT = lambda s : caseA(epsilon, s) >= delta
function_s_to_delta = lambda s : caseA(epsilon, s)
predicate_left_BS = lambda s : function_s_to_delta(s) > delta
function_s_to_alpha = lambda s : sqrt(1.0 + s/2.0) - sqrt(s/2.0)
else:
predicate_stop_DT = lambda s : caseB(epsilon, s) <= delta
function_s_to_delta = lambda s : caseB(epsilon, s)
predicate_left_BS = lambda s : function_s_to_delta(s) < delta
function_s_to_alpha = lambda s : sqrt(1.0 + s/2.0) + sqrt(s/2.0)
predicate_stop_BS = lambda s : abs(function_s_to_delta(s) - delta) <= tol
s_inf, s_sup = doubling_trick(predicate_stop_DT, 0.0, 1.0)
s_final = binary_search(predicate_stop_BS, predicate_left_BS, s_inf, s_sup)
alpha = function_s_to_alpha(s_final)
sigma = alpha*GS/sqrt(2.0*epsilon)
return sigma