@@ -26,12 +26,13 @@ pub mod traits;
26
26
#[ cfg( test) ]
27
27
pub mod test_tools {
28
28
use rand:: Rng ;
29
+ use statrs:: distribution:: { ChiSquared , ContinuousCDF } ;
29
30
30
31
pub use crate :: core_crypto:: algorithms:: misc:: {
31
32
modular_distance, modular_distance_custom_mod, torus_modular_diff,
32
33
} ;
33
34
use crate :: core_crypto:: commons:: ciphertext_modulus:: CiphertextModulus ;
34
- use crate :: core_crypto:: commons:: dispersion:: { DispersionParameter , Variance } ;
35
+ use crate :: core_crypto:: commons:: dispersion:: { DispersionParameter , StandardDev , Variance } ;
35
36
use crate :: core_crypto:: commons:: generators:: {
36
37
EncryptionRandomGenerator , SecretRandomGenerator ,
37
38
} ;
@@ -45,14 +46,64 @@ pub mod test_tools {
45
46
use crate :: core_crypto:: commons:: traits:: * ;
46
47
use tfhe_csprng:: seeders:: Seed ;
47
48
49
+ pub fn arithmetic_mean ( samples : & [ f64 ] ) -> f64 {
50
+ samples. iter ( ) . copied ( ) . sum :: < f64 > ( ) / samples. len ( ) as f64
51
+ }
52
+
48
53
pub fn variance ( samples : & [ f64 ] ) -> Variance {
49
54
let num_samples = samples. len ( ) ;
50
- let mean = samples . iter ( ) . sum :: < f64 > ( ) / ( num_samples as f64 ) ;
55
+ let mean = arithmetic_mean ( samples ) ;
51
56
Variance (
52
57
samples. iter ( ) . map ( |x| ( x - mean) . powi ( 2 ) ) . sum :: < f64 > ( ) / ( ( num_samples - 1 ) as f64 ) ,
53
58
)
54
59
}
55
60
61
+ #[ derive( Debug , Clone , Copy ) ]
62
+ pub struct VarianceConfidenceInterval {
63
+ lower_bound : Variance ,
64
+ upper_bound : Variance ,
65
+ }
66
+
67
+ impl VarianceConfidenceInterval {
68
+ pub fn variance_is_in_interval ( & self , variance_to_check : Variance ) -> bool {
69
+ self . lower_bound <= variance_to_check && self . upper_bound >= variance_to_check
70
+ }
71
+
72
+ pub fn lower_bound ( & self ) -> Variance {
73
+ self . lower_bound
74
+ }
75
+
76
+ pub fn upper_bound ( & self ) -> Variance {
77
+ self . upper_bound
78
+ }
79
+ }
80
+
81
+ /// Note that the confidence_level is the probability to be in the interval to be computed.
82
+ pub fn variance_confidence_interval (
83
+ sample_count : f64 ,
84
+ measured_variance : Variance ,
85
+ confidence_level : f64 ,
86
+ ) -> VarianceConfidenceInterval {
87
+ assert ! ( confidence_level >= 0.0 ) ;
88
+ assert ! ( confidence_level <= 1.0 ) ;
89
+ let alpha = 1.0 - confidence_level;
90
+ let degrees_of_freedom = sample_count - 1.0 ;
91
+ let chi2 = ChiSquared :: new ( degrees_of_freedom) . unwrap ( ) ;
92
+ let chi2_lower = chi2. inverse_cdf ( alpha / 2.0 ) ;
93
+ let chi2_upper = chi2. inverse_cdf ( 1.0 - alpha / 2.0 ) ;
94
+
95
+ // Lower bound is divided by chi2_upper, upper bound divided by chi2_lower
96
+ let lower_bound = Variance ( degrees_of_freedom * measured_variance. 0 / chi2_upper) ;
97
+ let upper_bound = Variance ( degrees_of_freedom * measured_variance. 0 / chi2_lower) ;
98
+
99
+ assert ! ( lower_bound <= upper_bound) ;
100
+
101
+ VarianceConfidenceInterval {
102
+ lower_bound,
103
+ upper_bound,
104
+ }
105
+ }
106
+
56
107
pub fn new_random_generator ( ) -> RandomGenerator < DefaultRandomGenerator > {
57
108
RandomGenerator :: new ( random_seed ( ) )
58
109
}
@@ -346,4 +397,45 @@ pub mod test_tools {
346
397
assert_eq ! ( distance, -0.25 ) ;
347
398
}
348
399
}
400
+
401
+ #[ test]
402
+ fn test_confidence_interval ( ) {
403
+ // https://stats.libretexts.org/Bookshelves/Introductory_Statistics/
404
+ // Inferential_Statistics_and_Probability_-_A_Holistic_Approach_(Geraghty)/
405
+ // 09%3A_Point_Estimation_and_Confidence_Intervals/9.03%3A_Confidence_Intervals
406
+
407
+ // In performance measurement of investments, standard deviation is a measure of volatility
408
+ // or risk. Twenty monthly returns from a mutual fund show an average monthly return of
409
+ // 1 percent and a sample standard deviation of 5 percent.
410
+ // Find a 95% confidence interval for the monthly standard deviation of the mutual fund.
411
+
412
+ // The Chi‐square distribution will have 20‐1 =19 degrees of freedom. Using technology,
413
+ // we find that the two critical values are chi2_left=8.90655
414
+ // and chi2_right=32.8523
415
+ // Formula for confidence interval for sigma
416
+ // is: sqrt(19 * 5^2 / 32.8523) sqrt(19 * 5^2 / 8.90655) = (3.8,7.3)
417
+
418
+ // One can say with 95% confidence that the standard deviation for this mutual fund is
419
+ // between 3.8 and 7.3 percent per month.
420
+
421
+ let measured_std_dev = StandardDev ( 0.05 ) ;
422
+ let measured_variance = measured_std_dev. get_variance ( ) ;
423
+
424
+ let confidence_level = 0.95 ;
425
+
426
+ let confidence_interval =
427
+ variance_confidence_interval ( 20. , measured_variance, confidence_level) ;
428
+
429
+ let lower_bound = confidence_interval. lower_bound ( ) ;
430
+ let upper_bound = confidence_interval. upper_bound ( ) ;
431
+
432
+ let approx_expected_lower_bound = StandardDev ( 0.038 ) . get_variance ( ) ;
433
+ let approx_expected_upper_bound = StandardDev ( 0.073 ) . get_variance ( ) ;
434
+
435
+ let lower_bound_abs_diff = ( lower_bound. 0 - approx_expected_lower_bound. 0 ) . abs ( ) ;
436
+ let upper_bound_abs_diff = ( upper_bound. 0 - approx_expected_upper_bound. 0 ) . abs ( ) ;
437
+
438
+ assert ! ( lower_bound_abs_diff / approx_expected_lower_bound. 0 < 0.01 ) ;
439
+ assert ! ( upper_bound_abs_diff / approx_expected_upper_bound. 0 < 0.01 ) ;
440
+ }
349
441
}
0 commit comments