Skip to content

Commit 91e2222

Browse files
Differential Privacy Teamcopybara-github
authored andcommitted
n/a
PiperOrigin-RevId: 763339052
1 parent 529c6d1 commit 91e2222

File tree

1 file changed

+54
-5
lines changed

1 file changed

+54
-5
lines changed

privacy-on-beam/pbeam/testutils/testutils.go

Lines changed: 54 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -657,8 +657,35 @@ func ComplementaryGaussianTolerance(flakinessK, l0Sensitivity, lInfSensitivity,
657657
return math.Erfinv(math.Pow(10, -flakinessK)) * noise.SigmaForGaussian(int64(l0Sensitivity), lInfSensitivity, epsilon, delta) * math.Sqrt(2)
658658
}
659659

660+
// GaussianToleranceForMean returns tolerances to be used in approxEquals for tests
661+
// for mean using Gaussian Noise to pass with 10⁻ᵏ flakiness.
662+
//
663+
// The return values include the tolerances for count, normalized sum, and mean.
664+
//
665+
// - flakinessK: parameter used to specify k in the flakiness.
666+
// - lower: minimum possible value of the input entities.
667+
// - upper: maximum possible value of the input entities.
668+
// - epsilon: the differential privacy parameter epsilon.
669+
// - stats.NormalizedSum: \sum { clamp(x_i, lower, upper) - midPoint }.
670+
//
671+
// distanceFromMidPoint = upper - midPoint, where midPoint = (lower + upper)/2.
672+
//
673+
// To see the logic and the math behind flakiness and tolerance calculation,
674+
// See https://github.com/google/differential-privacy/blob/main/privacy-on-beam/docs/Tolerance_Calculation.pdf
675+
func GaussianToleranceForMean(
676+
flakinessK, lower, upper float64, maxContributionsPerPartition, maxPartitionsContributed int64,
677+
epsilon float64, delta float64, stats VarianceStatistics,
678+
) (VarianceStatistics, error) {
679+
getToleranceOfNoise := func(flakinessK, eps, delta float64, sensitivify sensitivity) float64 {
680+
return GaussianTolerance(flakinessK, sensitivify.L0, sensitivify.LInf, eps, delta)
681+
}
682+
return toleranceForNoisyMeanImpl(
683+
flakinessK, lower, upper, maxContributionsPerPartition, maxPartitionsContributed,
684+
epsilon, delta, stats, getToleranceOfNoise)
685+
}
686+
660687
// LaplaceToleranceForMean returns tolerances to be used in approxEquals for tests
661-
// for mean to pass with 10⁻ᵏ flakiness.
688+
// for mean using Laplace Noise to pass with 10⁻ᵏ flakiness.
662689
//
663690
// The return values include the tolerances for count, normalized sum, and mean.
664691
//
@@ -675,24 +702,46 @@ func ComplementaryGaussianTolerance(flakinessK, l0Sensitivity, lInfSensitivity,
675702
func LaplaceToleranceForMean(
676703
flakinessK, lower, upper float64, maxContributionsPerPartition, maxPartitionsContributed int64,
677704
epsilon float64, stats VarianceStatistics,
705+
) (VarianceStatistics, error) {
706+
getToleranceOfNoise := func(flakinessK, eps, delta float64, sensitivify sensitivity) float64 {
707+
return LaplaceTolerance(flakinessK, sensitivify.L1, eps)
708+
}
709+
const delta float64 = 0 // Not used.
710+
return toleranceForNoisyMeanImpl(
711+
flakinessK, lower, upper, maxContributionsPerPartition, maxPartitionsContributed,
712+
epsilon, delta, stats, getToleranceOfNoise)
713+
}
714+
715+
// toleranceForNoisyMeanImpl calculates the tolerance for noisy mean of a certain noise kind.
716+
//
717+
// The return values include the tolerances for count, normalized sum, and mean.
718+
//
719+
// - getToleranceOfNoise calculates the noise specific tolerance given flakiness and sensitivity.
720+
func toleranceForNoisyMeanImpl(
721+
flakinessK, lower, upper float64,
722+
maxContributionsPerPartition, maxPartitionsContributed int64,
723+
epsilon, delta float64, stats VarianceStatistics,
724+
getToleranceOfNoise func(flakinessK, eps, delta float64, sensitivify sensitivity) float64,
678725
) (VarianceStatistics, error) {
679726
// The term below is equivalent to -log_10(1-sqrt(1-1e-k)).
680727
// It is formulated this way to increase precision and to avoid having this term go to infinity.
681728
// Count and normalized sum uses the same following flakiness for simplicity.
682729
newFlakinessK := -math.Log10(-math.Expm1(0.5 * math.Log1p(-math.Pow(10, -flakinessK))))
683730
halfEpsilon := epsilon / 2
731+
halfDelta := delta / 2
684732

685733
computer := sensitivityComputer{
686734
Lower: lower,
687735
Upper: upper,
688736
MaxContributionsPerPartition: maxContributionsPerPartition,
689737
MaxPartitionsContributed: maxPartitionsContributed,
690738
}
691-
l1Count := computer.SensitivitiesForCount().L1
692-
l1NormalizedSum := computer.SensitivitiesForNormalizedSum().L1
739+
countSens := computer.SensitivitiesForCount()
740+
normalizedSumSens := computer.SensitivitiesForNormalizedSum()
693741

694-
countTolerance := math.Ceil(LaplaceTolerance(newFlakinessK, l1Count, halfEpsilon))
695-
normalizedSumTolerance := LaplaceTolerance(newFlakinessK, l1NormalizedSum, halfEpsilon)
742+
countTolerance := math.Ceil(getToleranceOfNoise(newFlakinessK, halfEpsilon, halfDelta, countSens))
743+
normalizedSumTolerance := getToleranceOfNoise(
744+
newFlakinessK, halfEpsilon, halfDelta, normalizedSumSens)
696745

697746
tolerances := VarianceStatistics{
698747
Count: countTolerance,

0 commit comments

Comments
 (0)