def subsample_func_int(x): # output the cgf of the subsampled mechanism mm = int(x) eps_inf = func(np.inf) moments_two = 2 * np.log(prob) + utils.logcomb(mm,2) \ + np.minimum(np.log(4) + func(2.0) + np.log(1-np.exp(-func(2.0))), func(2.0) + np.minimum(np.log(2), 2 * (eps_inf+np.log(1-np.exp(-eps_inf))))) moment_bound = lambda j: np.minimum(j * (eps_inf + np.log(1-np.exp(-eps_inf))), np.log(2)) + cgf(j - 1) \ + j * np.log(prob) + utils.logcomb(mm, j) moments = [moment_bound(j) for j in range(3, mm + 1, 1)] return np.minimum( (x - 1) * func(x), utils.stable_logsumexp([0, moments_two] + moments))
def subsample_func_int(x): # This function evaluates the CGF at alpha = x, i.e., lamb = x- 1 if np.isinf(func(x)): return np.inf if prob == 1.0: return func(x) mm = int(x) fastbound = fast_poission_subsampled_cgf_upperbound( func, mm, prob) if x <= self.alphas[-1]: # compute the bound exactly. moments = [ cgf(1) + 2 * np.log(prob) + (mm - 2) * np.log(1 - prob) + self.logBinomC[mm, 2] ] moments = moments + [ cgf(j - 1 + 1) + j * np.log(prob) + (mm - j) * np.log(1 - prob) + self.logBinomC[mm, j] for j in range(3, mm + 1, 1) ] return utils.stable_logsumexp( [(mm - 1) * np.log(1 - prob) + np.log(1 + (mm - 1) * prob)] + moments) elif mm <= self.m_lin_max: moments = [ cgf(1) + 2 * np.log(prob) + (mm - 2) * np.log(1 - prob) + utils.logcomb(mm, 2) ] moments = moments + [ cgf(j - 1 + 1) + j * np.log(prob) + (mm - j) * np.log(1 - prob) + utils.logcomb(mm, j) for j in range(3, mm + 1, 1) ] return utils.stable_logsumexp( [(mm - 1) * np.log(1 - prob) + np.log(1 + (mm - 1) * prob)] + moments) else: return fastbound
def subsample_func_int(x): # This function evaluates teh CGF at alpha = x, i.e., lamb = x- 1 deltas_local, signs_deltas_local = self.deltas_cache[(func, prob)] if np.isinf(func(x)): return np.inf mm = int(x) fastupperbound = fast_subsampled_cgf_upperbound( func, mm, prob, deltas_local) fastupperbound2 = general_upperbound(func, mm, prob) if self.approx == True: if fastupperbound2 < 0: print('general rdp is negative', x) return fastupperbound2 if mm <= self.alphas[ -1]: # compute the bound exactly. Requires book keeping of O(x^2) moments = [ np.minimum( np.minimum((j) * np.log(np.exp(func(np.inf)) - 1) + np.minimum(cgf(j - 1), np.log(4)), np.log(2) + cgf(j - 1)), np.log(4) + 0.5 * deltas_local[int(2 * np.floor(j / 2.0)) - 1] + 0.5 * deltas_local[int(2 * np.ceil(j / 2.0)) - 1]) + j * np.log(prob) + self.logBinomC[int(mm), j] for j in range(2, int(mm + 1), 1) ] return np.minimum(fastupperbound, utils.stable_logsumexp([0] + moments)) elif mm <= self.m_lin_max: # compute the bound with stirling approximation. Everything is O(x) now. moment_bound = lambda j: np.minimum( j * np.log(np.exp(func(np.inf)) - 1) + np.minimum( cgf(j - 1), np.log(4)), np.log(2) + cgf(j - 1)) + j * np.log( prob) + utils.logcomb(mm, j) moments = [moment_bound(j) for j in range(2, mm + 1, 1)] return np.minimum(fastupperbound, utils.stable_logsumexp([0] + moments)) else: # Compute the O(1) upper bound return fastupperbound
def subsample_func_int(x): # This function evaluates teh CGF at alpha = x, i.e., lamb = x- 1 if np.isinf(func(x)): return np.inf mm = int(x) # fastbound = fast_poission_subsampled_cgf_upperbound( func, mm, prob) k = self.alphas[-1] fastbound_k = fast_k_subsample_upperbound(func, mm, prob, k) if self.approx == True: return fastbound_k #fastbound = min(fastbound, fastbound_k) if x <= self.alphas[-1]: # compute the bound exactly. moments = [ cgf(j - 1) + j * np.log(prob) + (mm - j) * np.log(1 - prob) + self.logBinomC[mm, j] for j in range(2, mm + 1, 1) ] return utils.stable_logsumexp( [(mm - 1) * np.log(1 - prob) + np.log(1 + (mm - 1) * prob)] + moments) elif mm <= self.m_lin_max: moments = [ cgf(j - 1) + j * np.log(prob) + (mm - j) * np.log(1 - prob) + utils.logcomb(mm, j) for j in range(2, mm + 1, 1) ] return utils.stable_logsumexp( [(mm - 1) * np.log(1 - prob) + np.log(1 + (mm - 1) * prob)] + moments) else: return fastbound
def moment_bound(j): return np.minimum(j * (eps_inf + np.log(1-np.exp(-eps_inf))), np.log(2)) + cgf(j - 1) \ + j * np.log(prob) + utils.logcomb(mm, j) moments = [moment_bound(j) for j in range(3, mm + 1, 1)]
def subsample_func_int(x): # This function evaluates teh CGF at alpha = x, i.e., lamb = x- 1 deltas_local, signs_deltas_local = self.deltas_cache[( func, prob)] if np.isinf(func(x)): return np.inf mm = int(x) eps_inf = func(np.inf) moments_two = 2 * np.log(prob) + utils.logcomb(mm, 2) \ + np.minimum( np.log(4) + func(2.0) + np.log(1 - np.exp(-func(2.0))), func(2.0) + np.minimum(np.log(2), 2 * (eps_inf + np.log(1 - np.exp(-eps_inf))))) moment_bound = lambda j: np.minimum(np.log(4) + 0.5*deltas_local[int(2*np.floor(j/2.0))-1] + 0.5*deltas_local[int(2*np.ceil(j/2.0))-1], np.minimum(j * (eps_inf + np.log(1 - np.exp(-eps_inf))), np.log(2)) + cgf(j - 1)) \ + j * np.log(prob) + utils.logcomb(mm, j) moment_bound_linear = lambda j: np.minimum(j * (eps_inf + np.log(1-np.exp(-eps_inf))), np.log(2)) + cgf(j - 1) \ + j * np.log(prob) + utils.logcomb(mm, j) fastupperbound = fast_subsampled_cgf_upperbound( func, mm, prob, deltas_local) if mm <= self.alphas[ -1]: # compute the bound exactly. Requires book keeping of O(x^2) # # moments = [ np.minimum(np.minimum((j)*np.log(np.exp(func(np.inf))-1) + np.minimum(cgf(j-1),np.log(4)), # np.log(2) + cgf(j-1)), # np.log(4) + 0.5*deltas_local[int(2*np.floor(j/2.0))-1] # + 0.5*deltas_local[int(2*np.ceil(j/2.0))-1]) + j*np.log(prob) # +self.logBinomC[int(mm), j] for j in range(2,int(mm+1),1)] moments = [ moment_bound(j) for j in range(3, mm + 1, 1) ] return np.minimum( fastupperbound, utils.stable_logsumexp([0, moments_two] + moments)) elif mm <= self.m_lin_max: # compute the bound with stirling approximation. Everything is O(x) now. # moment_bound = lambda j: np.minimum(j * np.log(np.exp(func(np.inf)) - 1) # + np.minimum(cgf(j - 1), np.log(4)), np.log(2) # + cgf(j - 1)) + j * np.log(prob) + utils.logcomb(mm, j) # moments = [moment_bound(j) for j in range(2,mm+1,1)] moments = [ moment_bound_linear(j) for j in range(3, mm + 1, 1) ] return np.minimum( fastupperbound, utils.stable_logsumexp([0, moments_two] + moments)) else: # Compute the O(1) upper bound return fastupperbound