55# ' @param sensitivity Sensitivity of the function
66# ' @param epsilon Numeric differential privacy parameter
77# ' @param fun Function to evaluate
8+ # ' @param inputObject the Bootstrap mechanism object on which the input function will be evaluated
89# ' @return Value of the function applied to one bootstrap sample
910# ' @import stats
1011# ' @export
1112
12- bootstrap.replication <- function (x , n , sensitivity , epsilon , fun ) {
13+ bootstrap.replication <- function (x , n , sensitivity , epsilon , fun , inputObject , ... ) {
1314 partition <- rmultinom(n = 1 , size = n , prob = rep(1 / n , n ))
14- max.appearances <- max(partition )
15- probs <- sapply(1 : max.appearances , dbinom , size = n , prob = (1 / n ))
16- stat.partitions <- vector(' list' , max.appearances )
17- for (i in 1 : max.appearances ) {
18- variance.i <- (i * probs [i ] * (sensitivity ^ 2 )) / (2 * epsilon )
19- stat.i <- fun(x [partition == i ])
20- noise.i <- dpNoise(n = length(stat.i ), scale = sqrt(variance.i ), dist = ' gaussian' )
21- stat.partitions [[i ]] <- i * stat.i + noise.i
15+ # make a sorted vector of the partitions of the data
16+ # because it is not guaranteed that every partition from 1:max.appearances will have a value in it
17+ # so we need to loop through only the partitions that have data
18+ validPartitions <- sort(unique(partition [,1 ]))
19+ # we do not want the 0 partition, so we remove it from the list
20+ validPartitions <- validPartitions [2 : length(validPartitions )]
21+ # print the unique values of the partition, to track which entries may result in NaN
22+ print(validPartitions )
23+ probs <- sapply(1 : length(validPartitions ), dbinom , size = n , prob = (1 / n ))
24+ stat.partitions <- vector(' list' , length(validPartitions ))
25+ for (i in 1 : length(validPartitions )) {
26+ currentPartition <- validPartitions [i ]
27+ variance.currentPartition <- (currentPartition * probs [i ] * (sensitivity ^ 2 )) / (2 * epsilon )
28+ stat.currentPartition <- inputObject $ bootStatEval(x [partition == currentPartition ], fun , ... )
29+ noise.currentPartition <- dpNoise(n = length(stat.currentPartition ), scale = sqrt(variance.currentPartition ), dist = ' gaussian' )
30+ stat.partitions [[i ]] <- currentPartition * stat.currentPartition + noise.currentPartition
2231 }
2332 stat.out <- do.call(rbind , stat.partitions )
2433 return (apply(stat.out , 2 , sum ))
@@ -39,10 +48,10 @@ mechanismBootstrap <- setRefClass(
3948)
4049
4150mechanismBootstrap $ methods(
42- bootStatEval = function (xi ) {
51+ bootStatEval = function (xi , fun , ... ) {
4352 fun.args <- getFuncArgs(fun , inputList = list (... ), inputObject = .self )
44- input.vals = c(list (x = x ), fun.args )
45- stat <- do.call(boot. fun , input.vals )
53+ input.vals = c(list (x = xi ), fun.args )
54+ stat <- do.call(fun , input.vals )
4655 return (stat )
4756})
4857
@@ -58,11 +67,11 @@ mechanismBootstrap$methods(
5867})
5968
6069mechanismBootstrap $ methods(
61- evaluate = function (fun , x , sens , postFun ) {
70+ evaluate = function (fun , x , sens , postFun , ... ) {
6271 x <- censordata(x , .self $ var.type , .self $ rng )
6372 x <- fillMissing(x , .self $ var.type , .self $ impute.rng [0 ], .self $ impute.rng [1 ])
6473 epsilon.part <- epsilon / .self $ n.boot
65- release <- replicate(.self $ n.boot , bootstrap.replication(x , n , sens , epsilon.part , fun = .self $ bootStatEval ))
74+ release <- replicate(.self $ n.boot , bootstrap.replication(x , n , sens , epsilon.part , fun = fun , inputObject = .self , ... ))
6675 std.error <- .self $ bootSE(release , .self $ n.boot , sens )
6776 out <- list (' release' = release , ' std.error' = std.error )
6877 out <- postFun(out )
0 commit comments