Source code for aijack.defense.dp.manager.rdp

import math

import numpy as np
from scipy import special
from scipy.special import logsumexp

from .utils import _log_add, _log_coef_i, _log_e, _log_s, _log_sub, _log_t


[docs]def eps_gaussian(alpha, params): if alpha == math.inf: return min( 4 * (np.exp(eps_gaussian(2, params) - 1)), 2 * np.exp(eps_gaussian(2, params)), ) return alpha / (2 * (params["sigma"] ** 2))
[docs]def eps_laplace(alpha, params): if alpha <= 1: return 1 / params["b"] + np.exp(-1 / params["b"]) - 1 elif alpha == math.inf: return 1 / params["b"] return (1 / (alpha - 1)) * logsumexp( [ np.log(alpha / (2 * alpha - 1)) + (alpha - 1) / params["b"], np.log((alpha - 1) / (2 * alpha - 1)) + (-alpha) / params["b"], ], b=[1, 1], )
[docs]def eps_randresp(alpha, params): if params["p"] == 1 or params["p"] == 0: return math.inf if alpha <= 1: return (2 * params["p"] - 1) * np.log(params["p"] / (1 - params["p"])) elif alpha == math.inf: return np.abs(np.log((1.0 * params["p"] / (1 - params["p"])))) return (1 / (alpha - 1)) * logsumexp( [ alpha * np.log(params["p"]) + (1 - alpha) * np.log(1 - params["p"]), alpha * np.log(1 - params["p"]) + (1 - alpha) * params["p"], ], b=[1, 1], )
[docs]def calc_upperbound_of_rdp_with_Sampled_Gaussian_Mechanism( alpha, params, sampling_rate, _eps ): """Compute log(A_alpha) for any positive finite alpha.""" if float(alpha).is_integer(): return calc_upperbound_of_rdp_with_Sampled_Gaussian_Mechanism_int( int(alpha), params, sampling_rate ) else: return calc_upperbound_of_rdp_with_Sampled_Gaussian_Mechanism_float( alpha, params, sampling_rate )
[docs]def calc_upperbound_of_rdp_with_Sampled_Gaussian_Mechanism_int( alpha, params, sampling_rate ): """Renyi Differential Privacy of the Sampled Gaussian Mechanism 3.3 Numerically Stable Computatio """ log_a = -np.inf for i in range(alpha + 1): log_coef_i = ( np.log(special.binom(alpha, i)) + i * np.log(sampling_rate) + (alpha - i) * np.log(1 - sampling_rate) ) s = log_coef_i + (i * i - i) / (2 * (params["sigma"] ** 2)) log_a = _log_add(log_a, s) return float(log_a) / (alpha - 1)
[docs]def calc_upperbound_of_rdp_with_Sampled_Gaussian_Mechanism_float( alpha, params, sampling_rate ): """Compute log(A_alpha) for fractional alpha. 0 < q < 1.""" # The two parts of A_alpha, integrals over (-inf,z0] and [z0, +inf), are # initialized to 0 in the log space: log_a0, log_a1 = -np.inf, -np.inf i = 0 z0 = params["sigma"] ** 2 * np.log(1 / sampling_rate - 1) + 0.5 while True: # do ... until loop coef = special.binom(alpha, i) log_coef = np.log(abs(coef)) j = alpha - i log_t0 = _log_t(log_coef, i, j, sampling_rate) log_t1 = _log_t(log_coef, j, i, sampling_rate) log_e0 = _log_e(i, z0, params["sigma"]) log_e1 = _log_e(z0, j, params["sigma"]) log_s0 = _log_s(i, log_t0, log_e0, params["sigma"]) log_s1 = _log_s(j, log_t1, log_e1, params["sigma"]) if coef > 0: log_a0 = _log_add(log_a0, log_s0) log_a1 = _log_add(log_a1, log_s1) else: log_a0 = _log_sub(log_a0, log_s0) log_a1 = _log_sub(log_a1, log_s1) i += 1 if max(log_s0, log_s1) < -30: break return _log_add(log_a0, log_a1) / (alpha - 1)
[docs]def calc_upperbound_of_rdp_with_theorem27_of_wang_2019( alpha, params, sampling_rate, _eps ): def B(el): res = 0 for i in range(el + 1): res += ( ((-1) ** (i)) * special.binom(el, i) * np.exp((i - 1) * _eps(i, params)) ) return abs(res) """ def logAbsB(el): ts = [] ss = [] for i in range(el + 1): ts.append(np.log(special.binom(el, i)) + (i - 1) * _eps(i, params)) ss.append((-1) ** (i + el % 2)) return logsumexp(ts, b=ss) """ terms = [] signs = [] terms.append(np.log(1)) signs.append(1) second = ( 2 * np.log(sampling_rate) + np.log(special.binom(alpha, 2)) + min( np.log(4) + logsumexp([_eps(2, params), np.log(1)], b=[1, -1]), _eps(2, params) + min( np.log(2), 2 * logsumexp([_eps(math.inf, params), np.log(1)], b=[1, -1]), ), ) ) terms.append(second) signs.append(1) for j in range(3, alpha + 1): terms.append( np.log(4) + j * np.log(sampling_rate) + np.log(special.binom(alpha, j)) + (1 / 2) * (np.log(B(2 * math.floor(j / 2))) + np.log(B(2 * math.ceil(j / 2)))) ) signs.append(1) return (1 / (alpha - 1)) * logsumexp(terms, b=signs)
[docs]def calc_first_term_of_general_upper_bound_of_rdp(alpha, sampling_rate): return ((alpha - 1) * np.log(1 - sampling_rate)) + np.log( alpha * sampling_rate - sampling_rate + 1 )
[docs]def calc_general_upperbound_of_rdp_with_theorem5_of_zhu_2019( alpha, params, sampling_rate, _eps ): terms = [] signs = [] first = calc_first_term_of_general_upper_bound_of_rdp(alpha, sampling_rate) terms.append(first) signs.append(1) if alpha >= 2: second = ( np.log(special.binom(alpha, 2)) + (2 * np.log(sampling_rate)) + ((alpha - 2) * np.log(1 - sampling_rate)) + _eps(2, params) ) terms.append(second) signs.append(1) if alpha >= 3: for el in range(3, alpha + 1): third = np.log(3) + ( _log_coef_i(alpha, el, sampling_rate) + ((el - 1) * _eps(el, params)) ) terms.append(third) signs.append(1) return (1 / (alpha - 1)) * logsumexp(terms, b=signs)
[docs]def calc_tightupperbound_lowerbound_of_rdp_with_theorem6and8_of_zhu_2019( alpha, params, sampling_rate, _eps ): terms = [] signs = [] first = calc_first_term_of_general_upper_bound_of_rdp(alpha, sampling_rate) terms.append(first) signs.append(1) if alpha >= 2: for el in range(2, alpha + 1): second = _log_coef_i(alpha, el, sampling_rate) + ( (el - 1) * _eps(el, params) ) terms.append(second) signs.append(1) return (1 / (alpha - 1)) * logsumexp(terms, b=signs)
[docs]def calc_tightupperbound_lowerbound_of_rdp_with_theorem6and8_of_zhu_2019_with_tau_estimation( alpha, params, sampling_rate, _eps, tau=10 ): terms = [] signs = [] eps_alpha_minus_tau = _eps(alpha - tau, params) first = alpha * np.log(1 - sampling_rate) + logsumexp( [np.log(1), -eps_alpha_minus_tau], b=[1, -1] ) terms.append(first) signs.append(1) second = -eps_alpha_minus_tau + alpha * logsumexp( [ np.log(1), np.log(sampling_rate), np.log(sampling_rate) + eps_alpha_minus_tau, ], b=[1, -1, 1], ) terms.append(second) signs.append(1) for el in range(2, tau): third = _log_coef_i(alpha, el, sampling_rate) + logsumexp( [(el - 1) * eps_alpha_minus_tau, (el - 1) * _eps(el, params)], b=[1, -1] ) terms.append(third) signs.append(-1) for el in range(alpha - tau + 1, alpha + 1): fourth = _log_coef_i(alpha, el, sampling_rate) + logsumexp( [(el - 1) * _eps(el, params), (el - 1) * eps_alpha_minus_tau], b=[1, -1], ) terms.append(fourth) signs.append(1) return (1 / (alpha - 1)) * logsumexp(terms, b=signs)