use crate::mu::oracle::r#trait::MuOracle;
use pounce_common::types::Number;
pub struct LoqoMuOracle {
pub mu_min: Number,
pub mu_max: Number,
pub avrg_compl: Number,
pub centrality_xi: Number,
}
impl Default for LoqoMuOracle {
fn default() -> Self {
Self {
mu_min: 1e-11,
mu_max: 1e5,
avrg_compl: 1.0,
centrality_xi: 1.0,
}
}
}
impl LoqoMuOracle {
pub fn new() -> Self {
Self::default()
}
pub fn loqo_mu(avrg_compl: Number, centrality_xi: Number) -> Number {
let factor: Number = 0.05;
let xi = centrality_xi.max(Number::MIN_POSITIVE);
let bracket = (factor * (1.0 - xi) / xi).min(2.0);
let sigma = 0.1 * bracket.powi(3);
sigma * avrg_compl
}
}
impl MuOracle for LoqoMuOracle {
fn calculate_mu(&mut self) -> Option<Number> {
let raw = Self::loqo_mu(self.avrg_compl, self.centrality_xi);
Some(raw.clamp(self.mu_min, self.mu_max))
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn loqo_at_uniform_complementarity_is_zero() {
assert_eq!(LoqoMuOracle::loqo_mu(1.0, 1.0), 0.0);
}
#[test]
fn loqo_caps_bracket_at_two() {
let m = LoqoMuOracle::loqo_mu(0.5, 1e-10);
assert!((m - 0.4).abs() < 1e-13);
}
#[test]
fn loqo_intermediate_xi() {
let m = LoqoMuOracle::loqo_mu(1.0, 0.5);
assert!((m - 1.25e-5).abs() < 1e-15);
}
#[test]
fn calculate_mu_clamps_to_band() {
let mut o = LoqoMuOracle {
mu_min: 1.0,
mu_max: 2.0,
avrg_compl: 1.0,
centrality_xi: 1.0, };
assert_eq!(o.calculate_mu(), Some(1.0));
}
}