pounce_algorithm/mu/oracle/
loqo.rs1use crate::mu::oracle::r#trait::MuOracle;
16use pounce_common::types::Number;
17
18pub struct LoqoMuOracle {
19 pub mu_min: Number,
20 pub mu_max: Number,
21 pub avrg_compl: Number,
26 pub centrality_xi: Number,
27}
28
29impl Default for LoqoMuOracle {
30 fn default() -> Self {
31 Self {
32 mu_min: 1e-11,
33 mu_max: 1e5,
34 avrg_compl: 1.0,
35 centrality_xi: 1.0,
36 }
37 }
38}
39
40impl LoqoMuOracle {
41 pub fn new() -> Self {
42 Self::default()
43 }
44
45 pub fn loqo_mu(avrg_compl: Number, centrality_xi: Number) -> Number {
49 let factor: Number = 0.05;
50 let xi = centrality_xi.max(Number::MIN_POSITIVE);
51 let bracket = (factor * (1.0 - xi) / xi).min(2.0);
52 let sigma = 0.1 * bracket.powi(3);
53 sigma * avrg_compl
54 }
55}
56
57impl MuOracle for LoqoMuOracle {
58 fn calculate_mu(&mut self) -> Option<Number> {
59 let raw = Self::loqo_mu(self.avrg_compl, self.centrality_xi);
60 Some(raw.clamp(self.mu_min, self.mu_max))
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use super::*;
67
68 #[test]
69 fn loqo_at_uniform_complementarity_is_zero() {
70 assert_eq!(LoqoMuOracle::loqo_mu(1.0, 1.0), 0.0);
72 }
73
74 #[test]
75 fn loqo_caps_bracket_at_two() {
76 let m = LoqoMuOracle::loqo_mu(0.5, 1e-10);
79 assert!((m - 0.4).abs() < 1e-13);
80 }
81
82 #[test]
83 fn loqo_intermediate_xi() {
84 let m = LoqoMuOracle::loqo_mu(1.0, 0.5);
87 assert!((m - 1.25e-5).abs() < 1e-15);
88 }
89
90 #[test]
91 fn calculate_mu_clamps_to_band() {
92 let mut o = LoqoMuOracle {
93 mu_min: 1.0,
94 mu_max: 2.0,
95 avrg_compl: 1.0,
96 centrality_xi: 1.0, };
98 assert_eq!(o.calculate_mu(), Some(1.0));
99 }
100}