1
1
use super :: {
2
2
CombinationsByRecord , DpParameters , DpPercentile , NoisyCountThreshold ,
3
- DEFAULT_NUMBER_OF_RECORDS_EPSILON ,
3
+ DEFAULT_NUMBER_OF_RECORDS_EPSILON_PROPORTION ,
4
4
} ;
5
5
use fnv:: FnvHashSet ;
6
6
use itertools:: Itertools ;
@@ -44,13 +44,14 @@ pub struct NoiseAggregator {
44
44
45
45
impl NoiseAggregator {
46
46
#[ inline]
47
- fn calc_percentile_epsilon_and_sigma_by_len (
47
+ fn calc_percentile_epsilon_number_of_records_epsilon_and_sigma_by_len (
48
48
reporting_length : usize ,
49
49
epsilon : f64 ,
50
50
delta : f64 ,
51
51
percentile_epsilon_proportion : f64 ,
52
+ number_of_records_proportion : f64 ,
52
53
sigma_proportions : & Option < Vec < f64 > > ,
53
- ) -> ( f64 , Vec < f64 > ) {
54
+ ) -> ( f64 , f64 , Vec < f64 > ) {
54
55
let proportions = match sigma_proportions {
55
56
Some ( proportions) => proportions. clone ( ) ,
56
57
None => {
@@ -60,37 +61,58 @@ impl NoiseAggregator {
60
61
}
61
62
} ;
62
63
63
- assert ! (
64
- reporting_length == proportions. len( ) ,
65
- "sigma proportions array size should match the reporting length" ,
66
- ) ;
67
-
68
64
info ! (
69
- "calculating percentile epsilon and sigma by len: total epsilon = {}, delta = {}, percentile_epsilon_proportion = {}, sigma_proportions = {:?}" ,
65
+ "calculating percentile epsilon, number of records epsilon and sigma by len: total epsilon = {}, delta = {}, percentile_epsilon_proportion = {}, number_of_records_proportion = {}, sigma_proportions = {:?}" ,
70
66
epsilon,
71
67
delta,
72
68
percentile_epsilon_proportion,
69
+ number_of_records_proportion,
73
70
proportions
74
71
) ;
75
72
73
+ assert ! (
74
+ reporting_length == proportions. len( ) ,
75
+ "sigma proportions array size should match the reporting length" ,
76
+ ) ;
77
+
78
+ assert ! (
79
+ percentile_epsilon_proportion < 1.0 && percentile_epsilon_proportion > 0.0 ,
80
+ "percentile_epsilon_proportion must be > 0 and < 1"
81
+ ) ;
82
+
83
+ assert ! (
84
+ number_of_records_proportion < 1.0 && number_of_records_proportion > 0.0 ,
85
+ "number_of_records_proportion must be > 0 and < 1"
86
+ ) ;
87
+
88
+ assert ! (
89
+ number_of_records_proportion + percentile_epsilon_proportion < 1.0 ,
90
+ "(percentile_epsilon_proportion + number_of_records_proportion) must be > 0 and < 1"
91
+ ) ;
92
+
76
93
let t = reporting_length as f64 ;
77
94
let rho = ( epsilon + ( 2.0 / delta) . ln ( ) ) . sqrt ( ) - ( 2.0 / delta) . ln ( ) . sqrt ( ) ;
78
95
let k: f64 = proportions. iter ( ) . map ( |p| 1.0 / ( p * p) ) . sum ( ) ;
79
96
let percentile_epsilon = ( 2.0 * rho * percentile_epsilon_proportion / t) . sqrt ( ) ;
80
- let base_sigma = ( k / ( 2.0 * rho * ( 1.0 - percentile_epsilon_proportion) ) ) . sqrt ( ) ;
97
+ let number_of_records_epsilon = ( 2.0 * rho * number_of_records_proportion) . sqrt ( ) ;
98
+ let base_sigma = ( k
99
+ / ( 2.0 * rho * ( 1.0 - percentile_epsilon_proportion - number_of_records_proportion) ) )
100
+ . sqrt ( ) ;
81
101
let sigmas: Vec < f64 > = proportions. iter ( ) . map ( |p| p * base_sigma) . collect ( ) ;
82
102
let lhs = ( ( t * percentile_epsilon * percentile_epsilon) / 2.0 )
103
+ + ( ( number_of_records_epsilon * number_of_records_epsilon) / 2.0 )
83
104
+ ( sigmas. iter ( ) . map ( |s| 1.0 / ( s * s) ) . sum :: < f64 > ( ) / 2.0 ) ;
84
105
85
106
info ! ( "percentile epsilon = {}" , percentile_epsilon) ;
107
+ info ! ( "number of records epsilon = {}" , number_of_records_epsilon) ;
86
108
info ! ( "calculated sigmas = {:?}" , sigmas) ;
87
109
88
110
assert ! (
89
111
( lhs - rho) . abs( ) <= DEFAULT_TOLERANCE ,
90
112
"something went wrong calculating DP sigmas"
91
113
) ;
92
114
93
- ( percentile_epsilon, sigmas)
115
+ ( percentile_epsilon, number_of_records_epsilon , sigmas)
94
116
}
95
117
96
118
#[ inline]
@@ -427,12 +449,15 @@ impl NoiseAggregator {
427
449
dp_parameters : & DpParameters ,
428
450
threshold : NoisyCountThreshold ,
429
451
) -> NoiseAggregator {
430
- let ( percentile_epsilon, sigmas) =
431
- NoiseAggregator :: calc_percentile_epsilon_and_sigma_by_len (
452
+ let ( percentile_epsilon, number_of_records_epsilon , sigmas) =
453
+ NoiseAggregator :: calc_percentile_epsilon_number_of_records_epsilon_and_sigma_by_len (
432
454
reporting_length,
433
455
dp_parameters. epsilon ,
434
456
dp_parameters. delta ,
435
457
dp_parameters. percentile_epsilon_proportion ,
458
+ dp_parameters
459
+ . number_of_records_epsilon_proportion
460
+ . unwrap_or ( DEFAULT_NUMBER_OF_RECORDS_EPSILON_PROPORTION ) ,
436
461
& dp_parameters. sigma_proportions ,
437
462
) ;
438
463
@@ -444,9 +469,7 @@ impl NoiseAggregator {
444
469
delta : dp_parameters. delta ,
445
470
sigmas,
446
471
threshold,
447
- number_of_records_epsilon : dp_parameters
448
- . number_of_records_epsilon
449
- . unwrap_or ( DEFAULT_NUMBER_OF_RECORDS_EPSILON ) ,
472
+ number_of_records_epsilon,
450
473
}
451
474
}
452
475
0 commit comments