Skip to main content

entrenar/optim/dp/
utils.rs

1//! Utility functions for differential privacy.
2
3use super::accountant::RdpAccountant;
4
5/// Estimate required noise multiplier for target epsilon
6///
7/// Given target (epsilon, delta), dataset size, batch size, and epochs,
8/// estimate the noise multiplier needed.
9pub fn estimate_noise_multiplier(
10    target_epsilon: f64,
11    delta: f64,
12    dataset_size: usize,
13    batch_size: usize,
14    epochs: usize,
15) -> f64 {
16    if target_epsilon <= 0.0 || delta <= 0.0 {
17        return f64::INFINITY;
18    }
19
20    let sample_rate = batch_size as f64 / dataset_size as f64;
21    let steps = (epochs * dataset_size) / batch_size;
22
23    // Binary search for noise multiplier
24    let mut low = 0.1;
25    let mut high = 100.0;
26
27    for _ in 0..100 {
28        let mid = f64::midpoint(low, high);
29
30        // Simulate privacy accounting
31        let mut accountant = RdpAccountant::new();
32        for _ in 0..steps {
33            accountant.step(mid, sample_rate);
34        }
35
36        let (epsilon, _) = accountant.get_privacy_spent(delta);
37
38        if epsilon < target_epsilon {
39            high = mid;
40        } else {
41            low = mid;
42        }
43
44        if (high - low) < 0.01 {
45            break;
46        }
47    }
48
49    high * 1.1 // Add 10% safety margin
50}
51
52/// Privacy cost per step for given parameters
53pub fn privacy_cost_per_step(noise_multiplier: f64, sample_rate: f64, delta: f64) -> f64 {
54    let mut accountant = RdpAccountant::new();
55    accountant.step(noise_multiplier, sample_rate);
56    accountant.get_privacy_spent(delta).0
57}