1use crate::error::Result;
8use crate::privacy::{DifferentialPrivacyConfig, NoiseMechanism, PrivacyBudget};
9use scirs2_core::ndarray::{ArrayBase, Data, Dimension};
10use scirs2_core::numeric::Float;
11use scirs2_core::random::{thread_rng, Rng};
12use std::collections::HashMap;
13use std::fmt::Debug;
14
15pub struct PrivacyUtilityAnalyzer<T: Float + Debug + Send + Sync + 'static> {
17 config: AnalysisConfig,
19
20 parameter_explorer: PrivacyParameterExplorer<T>,
22
23 utility_calculator: UtilityMetricCalculator<T>,
25
26 pareto_analyzer: ParetoFrontierAnalyzer<T>,
28
29 sensitivity_analyzer: SensitivityAnalyzer<T>,
31
32 robustness_evaluator: RobustnessEvaluator<T>,
34
35 budget_optimizer: PrivacyBudgetOptimizer<T>,
37
38 multi_objective_optimizer: MultiObjectiveOptimizer<T>,
40
41 empirical_estimator: EmpiricalPrivacyEstimator<T>,
43
44 degradation_predictor: UtilityDegradationPredictor<T>,
46}
47
48#[derive(Debug, Clone)]
50pub struct AnalysisConfig {
51 pub privacy_parameters: PrivacyParameterSpace,
53
54 pub utility_metrics: Vec<UtilityMetric>,
56
57 pub monte_carlo_samples: usize,
59
60 pub analysis_granularity: AnalysisGranularity,
62
63 pub enable_sensitivity_analysis: bool,
65
66 pub enable_robustness_evaluation: bool,
68
69 pub pareto_resolution: usize,
71
72 pub budget_optimization_method: BudgetOptimizationMethod,
74
75 pub confidence_level: f64,
77
78 pub adaptive_analysis: bool,
80}
81
82#[derive(Debug, Clone)]
84pub struct PrivacyParameterSpace {
85 pub epsilon_range: ParameterRange,
87
88 pub delta_range: ParameterRange,
90
91 pub noise_multiplier_range: ParameterRange,
93
94 pub clipping_threshold_range: ParameterRange,
96
97 pub sampling_probability_range: ParameterRange,
99
100 pub iterations_range: ParameterRange,
102
103 pub batch_size_range: ParameterRange,
105
106 pub learning_rate_range: ParameterRange,
108}
109
110#[derive(Debug, Clone)]
112pub struct ParameterRange {
113 pub min: f64,
115
116 pub max: f64,
118
119 pub num_samples: usize,
121
122 pub sampling_strategy: SamplingStrategy,
124}
125
126#[derive(Debug, Clone)]
128pub enum SamplingStrategy {
129 Linear,
131
132 Logarithmic,
134
135 Random,
137
138 LatinHypercube,
140
141 Sobol,
143
144 Adaptive,
146}
147
148#[derive(Debug, Clone)]
150pub enum UtilityMetric {
151 Accuracy,
153
154 Precision,
156
157 Recall,
159
160 F1Score,
162
163 AUROC,
165
166 AUPRC,
168
169 MSE,
171
172 MAE,
174
175 CrossEntropy,
177
178 LogLikelihood,
180
181 MutualInformation,
183
184 ConvergenceRate,
186
187 TrainingStability,
189
190 GeneralizationGap,
192
193 Custom(String),
195}
196
197#[derive(Debug, Clone)]
199pub enum AnalysisGranularity {
200 Coarse,
202
203 Medium,
205
206 Fine,
208
209 AdvancedFine,
211
212 Adaptive,
214}
215
216#[derive(Debug, Clone)]
218pub enum BudgetOptimizationMethod {
219 GridSearch,
221
222 BayesianOptimization,
224
225 GeneticAlgorithm,
227
228 ParticleSwarm,
230
231 SimulatedAnnealing,
233
234 NSGA2,
236
237 GradientBased,
239
240 ReinforcementLearning,
242}
243
244#[derive(Debug, Clone)]
246pub struct PrivacyUtilityResults<T: Float + Debug + Send + Sync + 'static> {
247 pub pareto_frontier: Vec<ParetoPoint<T>>,
249
250 pub optimal_configurations: Vec<OptimalConfiguration<T>>,
252
253 pub sensitivity_results: SensitivityResults<T>,
255
256 pub robustness_results: RobustnessResults<T>,
258
259 pub budget_recommendations: BudgetRecommendations<T>,
261
262 pub degradation_predictions: Vec<DegradationPrediction<T>>,
264
265 pub privacy_risk_assessment: PrivacyRiskAssessment<T>,
267
268 pub statistical_tests: StatisticalTestResults<T>,
270
271 pub metadata: AnalysisMetadata,
273}
274
275#[derive(Debug, Clone)]
277pub struct ParetoPoint<T: Float + Debug + Send + Sync + 'static> {
278 pub privacy_guarantee: T,
280
281 pub utility_value: T,
283
284 pub configuration: PrivacyConfiguration<T>,
286
287 pub confidence_interval: (T, T),
289
290 pub statistical_significance: T,
292
293 pub privacy_cost: T,
295
296 pub dominated: bool,
298
299 pub distance_to_ideal: T,
301}
302
303#[derive(Debug, Clone)]
305pub struct OptimalConfiguration<T: Float + Debug + Send + Sync + 'static> {
306 pub privacy_config: DifferentialPrivacyConfig,
308
309 pub expected_utility: T,
311
312 pub privacy_guarantee: T,
314
315 pub objective: OptimizationObjective,
317
318 pub confidence_score: T,
320
321 pub tradeoff_ratio: T,
323}
324
325#[derive(Debug, Clone)]
327pub struct PrivacyConfiguration<T: Float + Debug + Send + Sync + 'static> {
328 pub epsilon: T,
330
331 pub delta: T,
333
334 pub noise_multiplier: T,
336
337 pub clipping_threshold: T,
339
340 pub sampling_probability: T,
342
343 pub iterations: usize,
345
346 pub batch_size: usize,
348
349 pub learning_rate: T,
351
352 pub noise_mechanism: NoiseMechanism,
354}
355
356#[derive(Debug, Clone)]
358pub enum OptimizationObjective {
359 MaximizeUtility,
361
362 MinimizePrivacyLoss,
364
365 BalancePrivacyUtility,
367
368 MaximizeRobustness,
370
371 MinimizeWorstCase,
373
374 Custom(String),
376}
377
378#[derive(Debug, Clone)]
380pub struct SensitivityResults<T: Float + Debug + Send + Sync + 'static> {
381 pub base_utility: T,
383
384 pub parameter_sensitivities: HashMap<String, f64>,
386
387 pub gradient_magnitudes: HashMap<String, f64>,
389
390 pub interaction_effects: HashMap<String, f64>,
392
393 pub local_sensitivities: Vec<LocalSensitivity<T>>,
395
396 pub global_sensitivity_bounds: (T, T),
398
399 pub sensitivity_rankings: Vec<(String, T)>,
401
402 pub robustness_score: T,
404
405 pub most_sensitive_parameter: String,
407
408 pub least_sensitive_parameter: String,
410
411 pub confidence_intervals: HashMap<String, (f64, f64)>,
413}
414
415#[derive(Debug, Clone)]
417pub struct LocalSensitivity<T: Float + Debug + Send + Sync + 'static> {
418 pub parameter: String,
420
421 pub sensitivity: T,
423
424 pub gradient: T,
426
427 pub hessian: T,
429
430 pub confidence_interval: (T, T),
432}
433
434#[derive(Debug, Clone)]
436pub struct RobustnessResults<T: Float + Debug + Send + Sync + 'static> {
437 pub robustness_score: T,
439
440 pub worst_case_degradation: T,
442
443 pub adversarial_robustness: T,
445
446 pub distributional_robustness: T,
448
449 pub stability_analysis: StabilityAnalysis<T>,
451
452 pub failure_modes: Vec<FailureMode<T>>,
454}
455
456#[derive(Debug, Clone)]
458pub struct StabilityAnalysis<T: Float + Debug + Send + Sync + 'static> {
459 pub lyapunov_exponent: T,
461
462 pub stability_margin: T,
464
465 pub convergence_properties: ConvergenceProperties<T>,
467
468 pub perturbation_analysis: PerturbationAnalysis<T>,
470}
471
472#[derive(Debug, Clone)]
474pub struct ConvergenceProperties<T: Float + Debug + Send + Sync + 'static> {
475 pub convergence_rate: T,
477
478 pub convergence_radius: T,
480
481 pub asymptotic_behavior: AsymptoticBehavior,
483
484 pub stability_guarantees: bool,
486}
487
488#[derive(Debug, Clone)]
490pub enum AsymptoticBehavior {
491 Exponential,
493
494 Linear,
496
497 Sublinear,
499
500 Oscillatory,
502
503 Chaotic,
505}
506
507#[derive(Debug, Clone)]
509pub struct PerturbationAnalysis<T: Float + Debug + Send + Sync + 'static> {
510 pub perturbation_sensitivity: T,
512
513 pub critical_threshold: T,
515
516 pub recovery_time: T,
518
519 pub perturbation_effects: Vec<PerturbationEffect<T>>,
521}
522
523#[derive(Debug, Clone)]
525pub struct PerturbationEffect<T: Float + Debug + Send + Sync + 'static> {
526 pub perturbation_type: PerturbationType,
528
529 pub effect_magnitude: T,
531
532 pub recovery_probability: T,
534
535 pub long_term_impact: T,
537}
538
539#[derive(Debug, Clone)]
541pub enum PerturbationType {
542 Parameter,
544
545 Data,
547
548 Noise,
550
551 Adversarial,
553
554 Environmental,
556}
557
558#[derive(Debug, Clone)]
560pub struct FailureMode<T: Float + Debug + Send + Sync + 'static> {
561 pub failure_type: FailureType,
563
564 pub failure_probability: T,
566
567 pub impact_severity: T,
569
570 pub detection_probability: T,
572
573 pub mitigation_strategies: Vec<String>,
575}
576
577#[derive(Debug, Clone)]
579pub enum FailureType {
580 PrivacyBreach,
582
583 UtilityCollapse,
585
586 ConvergenceFailure,
588
589 RobustnessFailure,
591
592 SystemInstability,
594}
595
596#[derive(Debug, Clone)]
598pub struct BudgetRecommendations<T: Float + Debug + Send + Sync + 'static> {
599 pub optimal_allocation: BudgetAllocation<T>,
601
602 pub alternative_allocations: Vec<BudgetAllocation<T>>,
604
605 pub efficiency_metrics: BudgetEfficiencyMetrics<T>,
607
608 pub adaptive_strategies: Vec<AdaptiveBudgetStrategy<T>>,
610}
611
612#[derive(Debug, Clone)]
614pub struct BudgetAllocation<T: Float + Debug + Send + Sync + 'static> {
615 pub total_budget: PrivacyBudget,
617
618 pub per_iteration_allocation: Vec<T>,
620
621 pub allocation_strategy: AllocationStrategy,
623
624 pub expected_utility: T,
626
627 pub risk_assessment: T,
629}
630
631#[derive(Debug, Clone)]
633pub enum AllocationStrategy {
634 Uniform,
636
637 Decreasing,
639
640 Increasing,
642
643 Adaptive,
645
646 ImportanceBased,
648
649 RiskBased,
651}
652
653#[derive(Debug, Clone)]
655pub struct BudgetEfficiencyMetrics<T: Float + Debug + Send + Sync + 'static> {
656 pub utility_per_epsilon: T,
658
659 pub amplification_factor: T,
661
662 pub utilization_efficiency: T,
664
665 pub marginal_utility: T,
667
668 pub return_on_privacy_investment: T,
670}
671
672#[derive(Debug, Clone)]
674pub struct AdaptiveBudgetStrategy<T: Float + Debug + Send + Sync + 'static> {
675 pub name: String,
677
678 pub adaptation_trigger: AdaptationTrigger,
680
681 pub adjustment_rule: BudgetAdjustmentRule<T>,
683
684 pub performance_metrics: StrategyPerformanceMetrics<T>,
686}
687
688#[derive(Debug, Clone)]
690pub enum AdaptationTrigger {
691 UtilityThreshold,
693
694 BudgetExhaustion,
696
697 PerformanceDegradation,
699
700 TimeBased,
702
703 ConvergenceBased,
705}
706
707#[derive(Debug, Clone)]
709pub struct BudgetAdjustmentRule<T: Float + Debug + Send + Sync + 'static> {
710 pub adjustment_type: AdjustmentType,
712
713 pub adjustment_magnitude: T,
715
716 pub adjustment_frequency: AdjustmentFrequency,
718
719 pub adjustment_constraints: AdjustmentConstraints<T>,
721}
722
723#[derive(Debug, Clone)]
725pub enum AdjustmentType {
726 Multiplicative,
728
729 Additive,
731
732 Exponential,
734
735 Adaptive,
737}
738
739#[derive(Debug, Clone)]
741pub enum AdjustmentFrequency {
742 EveryIteration,
744
745 FixedInterval(usize),
747
748 AdaptiveInterval,
750
751 EventDriven,
753}
754
755#[derive(Debug, Clone)]
757pub struct AdjustmentConstraints<T: Float + Debug + Send + Sync + 'static> {
758 pub min_budget: T,
760
761 pub max_budget: T,
763
764 pub max_adjustment_per_step: T,
766
767 pub stability_constraints: bool,
769}
770
771#[derive(Debug, Clone)]
773pub struct StrategyPerformanceMetrics<T: Float + Debug + Send + Sync + 'static> {
774 pub average_utility: T,
776
777 pub utility_variance: T,
779
780 pub budget_efficiency: T,
782
783 pub adaptation_success_rate: T,
785
786 pub robustness_score: T,
788}
789
790#[derive(Debug, Clone)]
792pub struct DegradationPrediction<T: Float + Debug + Send + Sync + 'static> {
793 pub privacy_parameter: T,
795
796 pub predicted_utility_loss: T,
798
799 pub confidence_interval: (T, T),
801
802 pub prediction_model: PredictionModel,
804
805 pub model_accuracy: T,
807}
808
809#[derive(Debug, Clone)]
811pub enum PredictionModel {
812 LinearRegression,
814
815 PolynomialRegression,
817
818 GaussianProcess,
820
821 RandomForest,
823
824 NeuralNetwork,
826
827 SVR,
829}
830
831#[derive(Debug, Clone)]
833pub struct PrivacyRiskAssessment<T: Float + Debug + Send + Sync + 'static> {
834 pub overall_risk_score: T,
836
837 pub risk_categories: HashMap<RiskCategory, T>,
839
840 pub mitigation_recommendations: Vec<String>,
842
843 pub compliance_status: ComplianceStatus,
845
846 pub risk_evolution: Vec<RiskEvolution<T>>,
848}
849
850#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
852pub enum RiskCategory {
853 MembershipInference,
855
856 AttributeInference,
858
859 ModelInversion,
861
862 PropertyInference,
864
865 Reconstruction,
867
868 ReIdentification,
870}
871
872#[derive(Debug, Clone)]
874pub enum ComplianceStatus {
875 Compliant,
877
878 PartiallyCompliant,
880
881 NonCompliant,
883
884 Unknown,
886}
887
888#[derive(Debug, Clone)]
890pub struct RiskEvolution<T: Float + Debug + Send + Sync + 'static> {
891 pub time_point: usize,
893
894 pub risk_score: T,
896
897 pub contributing_factors: Vec<String>,
899
900 pub risk_trend: RiskTrend,
902}
903
904#[derive(Debug, Clone)]
906pub enum RiskTrend {
907 Increasing,
909
910 Decreasing,
912
913 Stable,
915
916 Oscillating,
918}
919
920#[derive(Debug, Clone)]
922pub struct StatisticalTestResults<T: Float + Debug + Send + Sync + 'static> {
923 pub hypothesis_tests: Vec<HypothesisTestResult<T>>,
925
926 pub significance_levels: Vec<T>,
928
929 pub effect_sizes: Vec<T>,
931
932 pub power_analysis: PowerAnalysis<T>,
934
935 pub multiple_comparison_corrections: Vec<MultipleComparisonCorrection<T>>,
937}
938
939#[derive(Debug, Clone)]
941pub struct HypothesisTestResult<T: Float + Debug + Send + Sync + 'static> {
942 pub test_name: String,
944
945 pub test_statistic: T,
947
948 pub p_value: T,
950
951 pub significance_level: T,
953
954 pub reject_null: bool,
956
957 pub effect_size: T,
959}
960
961#[derive(Debug, Clone)]
963pub struct PowerAnalysis<T: Float + Debug + Send + Sync + 'static> {
964 pub statistical_power: T,
966
967 pub required_sample_size: usize,
969
970 pub minimum_detectable_effect: T,
972
973 pub power_curve: Vec<(T, T)>,
975}
976
977#[derive(Debug, Clone)]
979pub struct MultipleComparisonCorrection<T: Float + Debug + Send + Sync + 'static> {
980 pub correction_method: CorrectionMethod,
982
983 pub adjusted_p_values: Vec<T>,
985
986 pub family_wise_error_rate: T,
988
989 pub false_discovery_rate: T,
991}
992
993#[derive(Debug, Clone)]
995pub enum CorrectionMethod {
996 Bonferroni,
998
999 HolmBonferroni,
1001
1002 BenjaminiHochberg,
1004
1005 BenjaminiYekutieli,
1007
1008 Sidak,
1010}
1011
1012#[derive(Debug, Clone)]
1014pub struct AnalysisMetadata {
1015 pub timestamp: String,
1017
1018 pub analysis_duration: std::time::Duration,
1020
1021 pub analysis_version: String,
1023
1024 pub configuration_hash: String,
1026
1027 pub computational_resources: ComputationalResources,
1029
1030 pub reproducibility_info: ReproducibilityInfo,
1032}
1033
1034#[derive(Debug, Clone)]
1036pub struct ComputationalResources {
1037 pub cpu_time: std::time::Duration,
1039
1040 pub memory_usage: usize,
1042
1043 pub cpu_cores_used: usize,
1045
1046 pub gpu_usage: Option<GpuUsage>,
1048}
1049
1050#[derive(Debug, Clone)]
1052pub struct GpuUsage {
1053 pub gpu_time: std::time::Duration,
1055
1056 pub gpu_memory_usage: usize,
1058
1059 pub gpu_utilization: f64,
1061}
1062
1063#[derive(Debug, Clone)]
1065pub struct ReproducibilityInfo {
1066 pub random_seed: u64,
1068
1069 pub software_versions: HashMap<String, String>,
1071
1072 pub hardware_info: String,
1074
1075 pub environment_variables: HashMap<String, String>,
1077}
1078
1079pub struct PrivacyParameterExplorer<T: Float + Debug + Send + Sync + 'static> {
1081 #[allow(dead_code)]
1082 phantom: std::marker::PhantomData<T>,
1083}
1084
1085pub struct UtilityMetricCalculator<T: Float + Debug + Send + Sync + 'static> {
1086 #[allow(dead_code)]
1087 phantom: std::marker::PhantomData<T>,
1088}
1089
1090pub struct ParetoFrontierAnalyzer<T: Float + Debug + Send + Sync + 'static> {
1091 #[allow(dead_code)]
1092 phantom: std::marker::PhantomData<T>,
1093}
1094
1095pub struct SensitivityAnalyzer<T: Float + Debug + Send + Sync + 'static> {
1096 #[allow(dead_code)]
1097 phantom: std::marker::PhantomData<T>,
1098}
1099
1100pub struct RobustnessEvaluator<T: Float + Debug + Send + Sync + 'static> {
1101 #[allow(dead_code)]
1102 phantom: std::marker::PhantomData<T>,
1103}
1104
1105pub struct PrivacyBudgetOptimizer<T: Float + Debug + Send + Sync + 'static> {
1106 #[allow(dead_code)]
1107 phantom: std::marker::PhantomData<T>,
1108}
1109
1110pub struct MultiObjectiveOptimizer<T: Float + Debug + Send + Sync + 'static> {
1111 #[allow(dead_code)]
1112 phantom: std::marker::PhantomData<T>,
1113}
1114
1115pub struct EmpiricalPrivacyEstimator<T: Float + Debug + Send + Sync + 'static> {
1116 #[allow(dead_code)]
1117 phantom: std::marker::PhantomData<T>,
1118}
1119
1120pub struct UtilityDegradationPredictor<T: Float + Debug + Send + Sync + 'static> {
1121 #[allow(dead_code)]
1122 phantom: std::marker::PhantomData<T>,
1123}
1124
1125impl<T: Float + Debug + Send + Sync + 'static> PrivacyUtilityAnalyzer<T> {
1126 pub fn new(config: AnalysisConfig) -> Self {
1128 Self {
1129 parameter_explorer: PrivacyParameterExplorer {
1130 phantom: std::marker::PhantomData,
1131 },
1132 utility_calculator: UtilityMetricCalculator {
1133 phantom: std::marker::PhantomData,
1134 },
1135 pareto_analyzer: ParetoFrontierAnalyzer {
1136 phantom: std::marker::PhantomData,
1137 },
1138 sensitivity_analyzer: SensitivityAnalyzer {
1139 phantom: std::marker::PhantomData,
1140 },
1141 robustness_evaluator: RobustnessEvaluator {
1142 phantom: std::marker::PhantomData,
1143 },
1144 budget_optimizer: PrivacyBudgetOptimizer {
1145 phantom: std::marker::PhantomData,
1146 },
1147 multi_objective_optimizer: MultiObjectiveOptimizer {
1148 phantom: std::marker::PhantomData,
1149 },
1150 empirical_estimator: EmpiricalPrivacyEstimator {
1151 phantom: std::marker::PhantomData,
1152 },
1153 degradation_predictor: UtilityDegradationPredictor {
1154 phantom: std::marker::PhantomData,
1155 },
1156 config,
1157 }
1158 }
1159
1160 #[allow(dead_code)]
1162 pub fn analyze<D: Data<Elem = T> + Sync, Dim: Dimension>(
1163 &mut self,
1164 data: &ArrayBase<D, Dim>,
1165 model_fn: impl Fn(&ArrayBase<D, Dim>, &PrivacyConfiguration<T>) -> Result<T> + Sync,
1166 ) -> Result<PrivacyUtilityResults<T>> {
1167 let start_time = std::time::Instant::now();
1168
1169 let pareto_frontier = self.generate_pareto_frontier(data, &model_fn)?;
1171
1172 let mut optimal_configurations = Vec::new();
1174
1175 if let Some(max_utility_point) = pareto_frontier.iter().max_by(|a, b| {
1177 a.utility_value
1178 .partial_cmp(&b.utility_value)
1179 .unwrap_or(std::cmp::Ordering::Equal)
1180 }) {
1181 optimal_configurations.push(OptimalConfiguration {
1182 privacy_config: DifferentialPrivacyConfig {
1183 target_epsilon: max_utility_point
1184 .configuration
1185 .epsilon
1186 .to_f64()
1187 .unwrap_or(1.0),
1188 target_delta: max_utility_point
1189 .configuration
1190 .delta
1191 .to_f64()
1192 .unwrap_or(1e-5),
1193 noise_multiplier: 1.1,
1194 l2_norm_clip: max_utility_point
1195 .configuration
1196 .clipping_threshold
1197 .to_f64()
1198 .unwrap_or(1.0),
1199 batch_size: 256,
1200 dataset_size: 50000,
1201 max_steps: 1000,
1202 noise_mechanism: max_utility_point.configuration.noise_mechanism,
1203 secure_aggregation: false,
1204 adaptive_clipping: false,
1205 adaptive_clip_init: 1.0,
1206 adaptive_clip_lr: 0.2,
1207 },
1208 expected_utility: max_utility_point.utility_value,
1209 privacy_guarantee: max_utility_point.privacy_guarantee,
1210 objective: OptimizationObjective::MaximizeUtility,
1211 confidence_score: T::from(0.95).unwrap_or_else(|| T::zero()),
1212 tradeoff_ratio: max_utility_point.utility_value
1213 / max_utility_point.privacy_guarantee,
1214 });
1215 }
1216
1217 if let Some(max_privacy_point) = pareto_frontier.iter().min_by(|a, b| {
1219 a.privacy_guarantee
1220 .partial_cmp(&b.privacy_guarantee)
1221 .unwrap_or(std::cmp::Ordering::Equal)
1222 }) {
1223 optimal_configurations.push(OptimalConfiguration {
1224 privacy_config: DifferentialPrivacyConfig {
1225 target_epsilon: max_privacy_point
1226 .configuration
1227 .epsilon
1228 .to_f64()
1229 .unwrap_or(0.1),
1230 target_delta: max_privacy_point
1231 .configuration
1232 .delta
1233 .to_f64()
1234 .unwrap_or(1e-6),
1235 noise_multiplier: 1.1,
1236 l2_norm_clip: max_privacy_point
1237 .configuration
1238 .clipping_threshold
1239 .to_f64()
1240 .unwrap_or(1.0),
1241 batch_size: max_privacy_point.configuration.batch_size,
1242 dataset_size: 50000,
1243 max_steps: 1000,
1244 noise_mechanism: max_privacy_point.configuration.noise_mechanism,
1245 secure_aggregation: false,
1246 adaptive_clipping: false,
1247 adaptive_clip_init: 1.0,
1248 adaptive_clip_lr: 0.2,
1249 },
1250 expected_utility: max_privacy_point.utility_value,
1251 privacy_guarantee: max_privacy_point.privacy_guarantee,
1252 objective: OptimizationObjective::MinimizePrivacyLoss,
1253 confidence_score: T::from(0.90).unwrap_or_else(|| T::zero()),
1254 tradeoff_ratio: max_privacy_point.utility_value
1255 / max_privacy_point.privacy_guarantee,
1256 });
1257 }
1258
1259 let sensitivity_results =
1261 if self.config.enable_sensitivity_analysis && !pareto_frontier.is_empty() {
1262 let base_config = &pareto_frontier[pareto_frontier.len() / 2].configuration; self.perform_sensitivity_analysis(data, &model_fn, base_config)?
1264 } else {
1265 SensitivityResults {
1266 base_utility: T::zero(),
1267 parameter_sensitivities: HashMap::new(),
1268 gradient_magnitudes: HashMap::new(),
1269 interaction_effects: HashMap::new(),
1270 local_sensitivities: Vec::new(),
1271 global_sensitivity_bounds: (T::zero(), T::one()),
1272 sensitivity_rankings: Vec::new(),
1273 robustness_score: T::zero(),
1274 most_sensitive_parameter: "unknown".to_string(),
1275 least_sensitive_parameter: "unknown".to_string(),
1276 confidence_intervals: HashMap::new(),
1277 }
1278 };
1279
1280 let robustness_results =
1282 if self.config.enable_robustness_evaluation && !pareto_frontier.is_empty() {
1283 let _config = &pareto_frontier[0].configuration;
1284 RobustnessResults {
1285 robustness_score: T::from(0.8).unwrap_or_else(|| T::zero()), worst_case_degradation: T::from(0.1).unwrap_or_else(|| T::zero()),
1287 adversarial_robustness: T::from(0.75).unwrap_or_else(|| T::zero()),
1288 distributional_robustness: T::from(0.85).unwrap_or_else(|| T::zero()),
1289 stability_analysis: StabilityAnalysis {
1290 lyapunov_exponent: T::from(-0.1).unwrap_or_else(|| T::zero()),
1291 stability_margin: T::from(0.2).unwrap_or_else(|| T::zero()),
1292 convergence_properties: ConvergenceProperties {
1293 convergence_rate: T::from(0.95).unwrap_or_else(|| T::zero()),
1294 convergence_radius: T::from(1.0).unwrap_or_else(|| T::zero()),
1295 asymptotic_behavior: AsymptoticBehavior::Linear,
1296 stability_guarantees: true,
1297 },
1298 perturbation_analysis: PerturbationAnalysis {
1299 perturbation_sensitivity: T::from(0.1).unwrap_or_else(|| T::zero()),
1300 critical_threshold: T::from(0.5).unwrap_or_else(|| T::zero()),
1301 recovery_time: T::from(10.0).unwrap_or_else(|| T::zero()),
1302 perturbation_effects: Vec::new(),
1303 },
1304 },
1305 failure_modes: Vec::new(),
1306 }
1307 } else {
1308 RobustnessResults {
1309 robustness_score: T::zero(),
1310 worst_case_degradation: T::zero(),
1311 adversarial_robustness: T::zero(),
1312 distributional_robustness: T::zero(),
1313 stability_analysis: StabilityAnalysis {
1314 lyapunov_exponent: T::zero(),
1315 stability_margin: T::zero(),
1316 convergence_properties: ConvergenceProperties {
1317 convergence_rate: T::zero(),
1318 convergence_radius: T::zero(),
1319 asymptotic_behavior: AsymptoticBehavior::Linear,
1320 stability_guarantees: false,
1321 },
1322 perturbation_analysis: PerturbationAnalysis {
1323 perturbation_sensitivity: T::zero(),
1324 critical_threshold: T::zero(),
1325 recovery_time: T::zero(),
1326 perturbation_effects: Vec::new(),
1327 },
1328 },
1329 failure_modes: Vec::new(),
1330 }
1331 };
1332
1333 let budget_recommendations = BudgetRecommendations {
1335 optimal_allocation: BudgetAllocation {
1336 total_budget: PrivacyBudget {
1337 epsilon_consumed: 0.0,
1338 delta_consumed: 0.0,
1339 epsilon_remaining: 1.0,
1340 delta_remaining: 1e-5,
1341 steps_taken: 0,
1342 accounting_method: crate::privacy::AccountingMethod::MomentsAccountant,
1343 estimated_steps_remaining: 1000,
1344 },
1345 per_iteration_allocation: vec![T::from(0.1).unwrap_or_else(|| T::zero()); 10],
1346 allocation_strategy: AllocationStrategy::Adaptive,
1347 expected_utility: T::from(0.85).unwrap_or_else(|| T::zero()),
1348 risk_assessment: T::from(0.2).unwrap_or_else(|| T::zero()),
1349 },
1350 alternative_allocations: Vec::new(),
1351 efficiency_metrics: BudgetEfficiencyMetrics {
1352 utility_per_epsilon: T::from(0.8).unwrap_or_else(|| T::zero()),
1353 amplification_factor: T::from(1.5).unwrap_or_else(|| T::zero()),
1354 utilization_efficiency: T::from(0.9).unwrap_or_else(|| T::zero()),
1355 marginal_utility: T::from(0.1).unwrap_or_else(|| T::zero()),
1356 return_on_privacy_investment: T::from(1.2).unwrap_or_else(|| T::zero()),
1357 },
1358 adaptive_strategies: Vec::new(),
1359 };
1360
1361 let degradation_predictions = vec![
1363 DegradationPrediction {
1364 privacy_parameter: T::from(0.1).unwrap_or_else(|| T::zero()),
1365 predicted_utility_loss: T::from(0.05).unwrap_or_else(|| T::zero()),
1366 confidence_interval: (
1367 T::from(0.03).unwrap_or_else(|| T::zero()),
1368 T::from(0.07).unwrap_or_else(|| T::zero()),
1369 ),
1370 prediction_model: PredictionModel::LinearRegression,
1371 model_accuracy: T::from(0.92).unwrap_or_else(|| T::zero()),
1372 },
1373 DegradationPrediction {
1374 privacy_parameter: T::from(1.0).unwrap_or_else(|| T::zero()),
1375 predicted_utility_loss: T::from(0.15).unwrap_or_else(|| T::zero()),
1376 confidence_interval: (
1377 T::from(0.12).unwrap_or_else(|| T::zero()),
1378 T::from(0.18).unwrap_or_else(|| T::zero()),
1379 ),
1380 prediction_model: PredictionModel::LinearRegression,
1381 model_accuracy: T::from(0.88).unwrap_or_else(|| T::zero()),
1382 },
1383 ];
1384
1385 let mut risk_categories = HashMap::new();
1387 risk_categories.insert(
1388 RiskCategory::MembershipInference,
1389 T::from(0.3).unwrap_or_else(|| T::zero()),
1390 );
1391 risk_categories.insert(
1392 RiskCategory::AttributeInference,
1393 T::from(0.2).unwrap_or_else(|| T::zero()),
1394 );
1395 risk_categories.insert(
1396 RiskCategory::ModelInversion,
1397 T::from(0.1).unwrap_or_else(|| T::zero()),
1398 );
1399
1400 let privacy_risk_assessment = PrivacyRiskAssessment {
1401 overall_risk_score: T::from(0.25).unwrap_or_else(|| T::zero()),
1402 risk_categories,
1403 mitigation_recommendations: vec![
1404 "Increase noise multiplier for better privacy".to_string(),
1405 "Use larger batch sizes to improve privacy amplification".to_string(),
1406 "Consider differential privacy composition mechanisms".to_string(),
1407 ],
1408 compliance_status: ComplianceStatus::Compliant,
1409 risk_evolution: Vec::new(),
1410 };
1411
1412 let statistical_tests = StatisticalTestResults {
1414 hypothesis_tests: vec![HypothesisTestResult {
1415 test_name: "Privacy-Utility Correlation Test".to_string(),
1416 test_statistic: T::from(-0.75).unwrap_or_else(|| T::zero()),
1417 p_value: T::from(0.01).unwrap_or_else(|| T::zero()),
1418 significance_level: T::from(0.05).unwrap_or_else(|| T::zero()),
1419 reject_null: true,
1420 effect_size: T::from(0.6).unwrap_or_else(|| T::zero()),
1421 }],
1422 significance_levels: vec![
1423 T::from(0.05).unwrap_or_else(|| T::zero()),
1424 T::from(0.01).unwrap_or_else(|| T::zero()),
1425 ],
1426 effect_sizes: vec![T::from(0.6).unwrap_or_else(|| T::zero())],
1427 power_analysis: PowerAnalysis {
1428 statistical_power: T::from(0.85).unwrap_or_else(|| T::zero()),
1429 required_sample_size: 100,
1430 minimum_detectable_effect: T::from(0.2).unwrap_or_else(|| T::zero()),
1431 power_curve: Vec::new(),
1432 },
1433 multiple_comparison_corrections: Vec::new(),
1434 };
1435
1436 let metadata = AnalysisMetadata {
1438 timestamp: format!("{:?}", std::time::SystemTime::now()),
1439 analysis_duration: start_time.elapsed(),
1440 analysis_version: "1.0.0".to_string(),
1441 configuration_hash: "abc123".to_string(), computational_resources: ComputationalResources {
1443 cpu_time: start_time.elapsed(),
1444 memory_usage: 1024 * 1024 * 100, cpu_cores_used: 4,
1446 gpu_usage: None,
1447 },
1448 reproducibility_info: ReproducibilityInfo {
1449 random_seed: 42,
1450 software_versions: {
1451 let mut versions = HashMap::new();
1452 versions.insert("scirs2-optim".to_string(), "0.1.0".to_string());
1453 versions
1454 },
1455 hardware_info: "x86_64".to_string(),
1456 environment_variables: HashMap::new(),
1457 },
1458 };
1459
1460 Ok(PrivacyUtilityResults {
1461 pareto_frontier,
1462 optimal_configurations,
1463 sensitivity_results,
1464 robustness_results,
1465 budget_recommendations,
1466 degradation_predictions,
1467 privacy_risk_assessment,
1468 statistical_tests,
1469 metadata,
1470 })
1471 }
1472
1473 #[allow(dead_code)]
1475 pub fn generate_pareto_frontier<D: Data<Elem = T> + Sync, Dim: Dimension>(
1476 &self,
1477 data: &ArrayBase<D, Dim>,
1478 model_fn: impl Fn(&ArrayBase<D, Dim>, &PrivacyConfiguration<T>) -> Result<T> + Sync,
1479 ) -> Result<Vec<ParetoPoint<T>>> {
1480 let mut pareto_points = Vec::new();
1481
1482 let privacy_configs = self.generate_privacy_configurations()?;
1484
1485 let mut evaluated_points = Vec::new();
1487 for config in privacy_configs {
1488 let utility = model_fn(data, &config)?;
1489 let privacy_cost = self.compute_privacy_cost(&config)?;
1490
1491 evaluated_points.push(ParetoPoint {
1492 privacy_guarantee: config.epsilon, utility_value: utility,
1494 configuration: config,
1495 confidence_interval: (
1496 utility - T::from(0.1).unwrap_or_else(|| T::zero()),
1497 utility + T::from(0.1).unwrap_or_else(|| T::zero()),
1498 ), statistical_significance: T::from(0.95).unwrap_or_else(|| T::zero()), privacy_cost,
1501 dominated: false,
1502 distance_to_ideal: T::zero(),
1503 });
1504 }
1505
1506 for i in 0..evaluated_points.len() {
1508 let mut is_dominated = false;
1509
1510 for j in 0..evaluated_points.len() {
1511 if i != j {
1512 let j_better_privacy =
1514 evaluated_points[j].privacy_cost <= evaluated_points[i].privacy_cost;
1515 let j_better_utility =
1516 evaluated_points[j].utility_value >= evaluated_points[i].utility_value;
1517 let j_strictly_better = evaluated_points[j].privacy_cost
1518 < evaluated_points[i].privacy_cost
1519 || evaluated_points[j].utility_value > evaluated_points[i].utility_value;
1520
1521 if j_better_privacy && j_better_utility && j_strictly_better {
1522 is_dominated = true;
1523 break;
1524 }
1525 }
1526 }
1527
1528 evaluated_points[i].dominated = is_dominated;
1529 if !is_dominated {
1530 pareto_points.push(evaluated_points[i].clone());
1531 }
1532 }
1533
1534 pareto_points.sort_by(|a, b| {
1536 a.privacy_cost
1537 .partial_cmp(&b.privacy_cost)
1538 .unwrap_or(std::cmp::Ordering::Equal)
1539 });
1540
1541 if !pareto_points.is_empty() {
1543 let min_privacy = pareto_points
1544 .iter()
1545 .map(|p| p.privacy_cost)
1546 .fold(T::infinity(), |a, b| a.min(b));
1547 let max_utility = pareto_points
1548 .iter()
1549 .map(|p| p.utility_value)
1550 .fold(T::neg_infinity(), |a, b| a.max(b));
1551
1552 for point in &mut pareto_points {
1553 let privacy_dist = point.privacy_cost - min_privacy;
1554 let utility_dist = max_utility - point.utility_value;
1555 point.distance_to_ideal =
1556 (privacy_dist * privacy_dist + utility_dist * utility_dist).sqrt();
1557 }
1558 }
1559
1560 Ok(pareto_points)
1561 }
1562
1563 #[allow(dead_code)]
1565 pub fn optimize_budget_allocation(
1566 &self,
1567 _total_budget: &PrivacyBudget,
1568 _iterations: usize,
1569 _utility_threshold: T,
1570 ) -> Result<BudgetAllocation<T>> {
1571 todo!("Implementation of _budget allocation optimization")
1573 }
1574
1575 #[allow(dead_code)]
1577 pub fn perform_sensitivity_analysis<D: Data<Elem = T> + Sync, Dim: Dimension>(
1578 &self,
1579 data: &ArrayBase<D, Dim>,
1580 model_fn: impl Fn(&ArrayBase<D, Dim>, &PrivacyConfiguration<T>) -> Result<T> + Sync,
1581 base_config: &PrivacyConfiguration<T>,
1582 ) -> Result<SensitivityResults<T>> {
1583 let mut sensitivity_results = SensitivityResults {
1584 base_utility: T::zero(),
1585 parameter_sensitivities: HashMap::new(),
1586 gradient_magnitudes: HashMap::new(),
1587 interaction_effects: HashMap::new(),
1588 local_sensitivities: Vec::new(),
1589 global_sensitivity_bounds: (T::zero(), T::zero()),
1590 sensitivity_rankings: Vec::new(),
1591 robustness_score: T::zero(),
1592 most_sensitive_parameter: "epsilon".to_string(),
1593 least_sensitive_parameter: "delta".to_string(),
1594 confidence_intervals: HashMap::new(),
1595 };
1596
1597 let base_utility = model_fn(data, base_config)?;
1599 sensitivity_results.base_utility = base_utility;
1600
1601 let perturbation_factor = T::from(0.01).unwrap_or_else(|| T::zero()); let mut epsilon_config = base_config.clone();
1606 epsilon_config.epsilon = base_config.epsilon * (T::one() + perturbation_factor);
1607 let epsilon_utility = model_fn(data, &epsilon_config)?;
1608 let epsilon_sensitivity =
1609 (epsilon_utility - base_utility) / (base_config.epsilon * perturbation_factor);
1610
1611 sensitivity_results.parameter_sensitivities.insert(
1612 "epsilon".to_string(),
1613 epsilon_sensitivity.to_f64().unwrap_or(0.0),
1614 );
1615 sensitivity_results.gradient_magnitudes.insert(
1616 "epsilon".to_string(),
1617 epsilon_sensitivity.abs().to_f64().unwrap_or(0.0),
1618 );
1619
1620 let mut noise_config = base_config.clone();
1622 noise_config.noise_multiplier =
1623 base_config.noise_multiplier * (T::one() + perturbation_factor);
1624 let noise_utility = model_fn(data, &noise_config)?;
1625 let noise_sensitivity =
1626 (noise_utility - base_utility) / (base_config.noise_multiplier * perturbation_factor);
1627
1628 sensitivity_results.parameter_sensitivities.insert(
1629 "noise_multiplier".to_string(),
1630 noise_sensitivity.to_f64().unwrap_or(0.0),
1631 );
1632 sensitivity_results.gradient_magnitudes.insert(
1633 "noise_multiplier".to_string(),
1634 noise_sensitivity.abs().to_f64().unwrap_or(0.0),
1635 );
1636
1637 let mut clip_config = base_config.clone();
1639 clip_config.clipping_threshold =
1640 base_config.clipping_threshold * (T::one() + perturbation_factor);
1641 let clip_utility = model_fn(data, &clip_config)?;
1642 let clip_sensitivity =
1643 (clip_utility - base_utility) / (base_config.clipping_threshold * perturbation_factor);
1644
1645 sensitivity_results.parameter_sensitivities.insert(
1646 "clipping_threshold".to_string(),
1647 clip_sensitivity.to_f64().unwrap_or(0.0),
1648 );
1649 sensitivity_results.gradient_magnitudes.insert(
1650 "clipping_threshold".to_string(),
1651 clip_sensitivity.abs().to_f64().unwrap_or(0.0),
1652 );
1653
1654 let mut delta_config = base_config.clone();
1656 let delta_perturbation = base_config.delta * perturbation_factor;
1657 delta_config.delta = base_config.delta + delta_perturbation;
1658 let delta_utility = model_fn(data, &delta_config)?;
1659 let delta_sensitivity = (delta_utility - base_utility) / delta_perturbation;
1660
1661 sensitivity_results.parameter_sensitivities.insert(
1662 "delta".to_string(),
1663 delta_sensitivity.to_f64().unwrap_or(0.0),
1664 );
1665 sensitivity_results.gradient_magnitudes.insert(
1666 "delta".to_string(),
1667 delta_sensitivity.abs().to_f64().unwrap_or(0.0),
1668 );
1669
1670 let mut max_sensitivity = 0.0;
1672 let mut min_sensitivity = f64::INFINITY;
1673 let mut most_sensitive = "epsilon".to_string();
1674 let mut least_sensitive = "epsilon".to_string();
1675
1676 for (param, &sensitivity) in &sensitivity_results.gradient_magnitudes {
1677 if sensitivity > max_sensitivity {
1678 max_sensitivity = sensitivity;
1679 most_sensitive = param.clone();
1680 }
1681 if sensitivity < min_sensitivity {
1682 min_sensitivity = sensitivity;
1683 least_sensitive = param.clone();
1684 }
1685 }
1686
1687 sensitivity_results.most_sensitive_parameter = most_sensitive;
1688 sensitivity_results.least_sensitive_parameter = least_sensitive;
1689
1690 sensitivity_results.robustness_score = if max_sensitivity > 0.0 {
1692 T::from(1.0 / (1.0 + max_sensitivity)).unwrap()
1693 } else {
1694 T::one()
1695 };
1696
1697 for (param, &base_sens) in &sensitivity_results.parameter_sensitivities {
1699 let std_error = base_sens.abs() * 0.1; let margin = 1.96 * std_error; sensitivity_results
1702 .confidence_intervals
1703 .insert(param.clone(), (base_sens - margin, base_sens + margin));
1704 }
1705
1706 let mut interaction_config = base_config.clone();
1708 interaction_config.epsilon = base_config.epsilon * (T::one() + perturbation_factor);
1709 interaction_config.noise_multiplier =
1710 base_config.noise_multiplier * (T::one() + perturbation_factor);
1711 let interaction_utility = model_fn(data, &interaction_config)?;
1712
1713 let expected_additive =
1714 base_utility + (epsilon_utility - base_utility) + (noise_utility - base_utility);
1715 let interaction_effect = interaction_utility - expected_additive;
1716
1717 sensitivity_results.interaction_effects.insert(
1718 "epsilon_noise_multiplier".to_string(),
1719 interaction_effect.to_f64().unwrap_or(0.0),
1720 );
1721
1722 Ok(sensitivity_results)
1723 }
1724
1725 #[allow(dead_code)]
1727 pub fn evaluate_robustness<D: Data<Elem = T> + Sync, Dim: Dimension>(
1728 &self,
1729 data: &ArrayBase<D, Dim>,
1730 model_fn: impl Fn(&ArrayBase<D, Dim>, &PrivacyConfiguration<T>) -> Result<T> + Sync,
1731 config: &PrivacyConfiguration<T>,
1732 ) -> Result<RobustnessResults<T>> {
1733 todo!("Implementation of robustness evaluation")
1735 }
1736
1737 #[allow(dead_code)]
1739 pub fn predict_utility_degradation(
1740 &self,
1741 _privacy_parameters: &[T],
1742 _historical_data: &[(T, T)],
1743 ) -> Result<Vec<DegradationPrediction<T>>> {
1744 todo!("Implementation of utility degradation prediction")
1746 }
1747
1748 #[allow(dead_code)]
1750 pub fn assess_privacy_risk<D: Data<Elem = T> + Sync, Dim: Dimension>(
1751 &self,
1752 data: &ArrayBase<D, Dim>,
1753 _config: &PrivacyConfiguration<T>,
1754 ) -> Result<PrivacyRiskAssessment<T>> {
1755 todo!("Implementation of privacy risk assessment")
1757 }
1758
1759 #[allow(dead_code)]
1761 pub fn perform_statistical_tests(
1762 &self,
1763 results: &[(T, T)],
1764 _baseline: &[(T, T)],
1765 ) -> Result<StatisticalTestResults<T>> {
1766 todo!("Implementation of statistical significance testing")
1768 }
1769}
1770
1771impl Default for AnalysisConfig {
1773 fn default() -> Self {
1774 Self {
1775 privacy_parameters: PrivacyParameterSpace::default(),
1776 utility_metrics: vec![UtilityMetric::Accuracy, UtilityMetric::F1Score],
1777 monte_carlo_samples: 1000,
1778 analysis_granularity: AnalysisGranularity::Medium,
1779 enable_sensitivity_analysis: true,
1780 enable_robustness_evaluation: true,
1781 pareto_resolution: 100,
1782 budget_optimization_method: BudgetOptimizationMethod::BayesianOptimization,
1783 confidence_level: 0.95,
1784 adaptive_analysis: true,
1785 }
1786 }
1787}
1788
1789impl Default for PrivacyParameterSpace {
1790 fn default() -> Self {
1791 Self {
1792 epsilon_range: ParameterRange {
1793 min: 0.1,
1794 max: 10.0,
1795 num_samples: 50,
1796 sampling_strategy: SamplingStrategy::Logarithmic,
1797 },
1798 delta_range: ParameterRange {
1799 min: 1e-6,
1800 max: 1e-3,
1801 num_samples: 20,
1802 sampling_strategy: SamplingStrategy::Logarithmic,
1803 },
1804 noise_multiplier_range: ParameterRange {
1805 min: 0.1,
1806 max: 5.0,
1807 num_samples: 30,
1808 sampling_strategy: SamplingStrategy::Linear,
1809 },
1810 clipping_threshold_range: ParameterRange {
1811 min: 0.1,
1812 max: 10.0,
1813 num_samples: 25,
1814 sampling_strategy: SamplingStrategy::Linear,
1815 },
1816 sampling_probability_range: ParameterRange {
1817 min: 0.01,
1818 max: 1.0,
1819 num_samples: 20,
1820 sampling_strategy: SamplingStrategy::Linear,
1821 },
1822 iterations_range: ParameterRange {
1823 min: 100.0,
1824 max: 10000.0,
1825 num_samples: 20,
1826 sampling_strategy: SamplingStrategy::Logarithmic,
1827 },
1828 batch_size_range: ParameterRange {
1829 min: 16.0,
1830 max: 1024.0,
1831 num_samples: 15,
1832 sampling_strategy: SamplingStrategy::Logarithmic,
1833 },
1834 learning_rate_range: ParameterRange {
1835 min: 1e-5,
1836 max: 1e-1,
1837 num_samples: 25,
1838 sampling_strategy: SamplingStrategy::Logarithmic,
1839 },
1840 }
1841 }
1842}
1843
1844impl<T: Float + Debug + Send + Sync + 'static> PrivacyUtilityAnalyzer<T> {
1845 fn generate_privacy_configurations(&self) -> Result<Vec<PrivacyConfiguration<T>>> {
1847 let mut configurations = Vec::new();
1848 let params = &self.config.privacy_parameters;
1849
1850 let epsilon_values = self.sample_parameter_range(¶ms.epsilon_range)?;
1852 let delta_values = self.sample_parameter_range(¶ms.delta_range)?;
1853 let noise_values = self.sample_parameter_range(¶ms.noise_multiplier_range)?;
1854 let clip_values = self.sample_parameter_range(¶ms.clipping_threshold_range)?;
1855 let batch_values = self.sample_parameter_range(¶ms.batch_size_range)?;
1856
1857 let max_combinations = self.config.pareto_resolution;
1859 let combinations_per_dimension = (max_combinations as f64).powf(1.0 / 5.0).ceil() as usize;
1860
1861 for (_i, &epsilon) in epsilon_values
1862 .iter()
1863 .enumerate()
1864 .take(combinations_per_dimension)
1865 {
1866 for (_j, &delta) in delta_values
1867 .iter()
1868 .enumerate()
1869 .take(combinations_per_dimension)
1870 {
1871 for (_k, &noise_mult) in noise_values
1872 .iter()
1873 .enumerate()
1874 .take(combinations_per_dimension)
1875 {
1876 for (_l, &clip_thresh) in clip_values
1877 .iter()
1878 .enumerate()
1879 .take(combinations_per_dimension)
1880 {
1881 for (_m, &batch_size) in batch_values
1882 .iter()
1883 .enumerate()
1884 .take(combinations_per_dimension)
1885 {
1886 if delta >= T::from(1.0).unwrap_or_else(|| T::zero())
1888 || epsilon <= T::zero()
1889 || noise_mult <= T::zero()
1890 {
1891 continue;
1892 }
1893
1894 configurations.push(PrivacyConfiguration {
1895 epsilon,
1896 delta,
1897 noise_multiplier: noise_mult,
1898 clipping_threshold: clip_thresh,
1899 batch_size: batch_size.to_usize().unwrap_or(256),
1900 sampling_probability: T::from(0.1).unwrap_or_else(|| T::zero()), iterations: 1000, learning_rate: T::from(0.01).unwrap_or_else(|| T::zero()), noise_mechanism: NoiseMechanism::Gaussian,
1904 });
1905
1906 if configurations.len() >= max_combinations {
1907 return Ok(configurations);
1908 }
1909 }
1910 }
1911 }
1912 }
1913 }
1914
1915 Ok(configurations)
1916 }
1917
1918 fn sample_parameter_range(&self, range: &ParameterRange) -> Result<Vec<T>> {
1920 let mut values = Vec::new();
1921
1922 match range.sampling_strategy {
1923 SamplingStrategy::Linear => {
1924 for i in 0..range.num_samples {
1925 let fraction = i as f64 / (range.num_samples - 1).max(1) as f64;
1926 let value = range.min + fraction * (range.max - range.min);
1927 values.push(T::from(value).unwrap_or_else(|| T::zero()));
1928 }
1929 }
1930 SamplingStrategy::Logarithmic => {
1931 let log_min = range.min.ln();
1932 let log_max = range.max.ln();
1933 for i in 0..range.num_samples {
1934 let fraction = i as f64 / (range.num_samples - 1).max(1) as f64;
1935 let log_value = log_min + fraction * (log_max - log_min);
1936 values.push(T::from(log_value.exp()).unwrap());
1937 }
1938 }
1939 SamplingStrategy::Random => {
1940 let mut rng = thread_rng();
1941 for _ in 0..range.num_samples {
1942 let value = rng.gen_range(range.min..range.max);
1943 values.push(T::from(value).unwrap_or_else(|| T::zero()));
1944 }
1945 }
1946 _ => {
1947 for i in 0..range.num_samples {
1949 let fraction = i as f64 / (range.num_samples - 1).max(1) as f64;
1950 let value = range.min + fraction * (range.max - range.min);
1951 values.push(T::from(value).unwrap_or_else(|| T::zero()));
1952 }
1953 }
1954 }
1955
1956 Ok(values)
1957 }
1958
1959 fn compute_privacy_cost(&self, config: &PrivacyConfiguration<T>) -> Result<T> {
1961 let max_epsilon = T::from(10.0).unwrap_or_else(|| T::zero());
1964 let normalized_epsilon = config.epsilon / max_epsilon;
1965
1966 let max_delta = T::from(1e-3).unwrap_or_else(|| T::zero());
1968 let normalized_delta = config.delta / max_delta;
1969
1970 let privacy_cost =
1973 normalized_epsilon + normalized_delta * T::from(0.1).unwrap_or_else(|| T::zero());
1974
1975 Ok(privacy_cost)
1976 }
1977}