use crate::core::VisibilityGraph;
use std::cell::RefCell;
use std::collections::HashMap;
#[derive(Debug)]
pub struct LazyMetrics {
clustering_coefficient: RefCell<Option<f64>>,
diameter: RefCell<Option<usize>>,
avg_path_length: RefCell<Option<f64>>,
density: RefCell<Option<f64>>,
betweenness_centrality: RefCell<HashMap<usize, f64>>,
}
impl LazyMetrics {
pub fn new() -> Self {
Self {
clustering_coefficient: RefCell::new(None),
diameter: RefCell::new(None),
avg_path_length: RefCell::new(None),
density: RefCell::new(None),
betweenness_centrality: RefCell::new(HashMap::new()),
}
}
pub fn clear(&self) {
*self.clustering_coefficient.borrow_mut() = None;
*self.diameter.borrow_mut() = None;
*self.avg_path_length.borrow_mut() = None;
*self.density.borrow_mut() = None;
self.betweenness_centrality.borrow_mut().clear();
}
}
impl Default for LazyMetrics {
fn default() -> Self {
Self::new()
}
}
impl<T> VisibilityGraph<T> {
pub fn with_lazy_metrics(self) -> Self {
self
}
}
pub struct LazyFeatureBuilder<T> {
series: Vec<Option<T>>,
computed_features: RefCell<HashMap<(usize, String), Option<T>>>,
}
impl<T: Copy> LazyFeatureBuilder<T> {
pub fn new(series: Vec<Option<T>>) -> Self {
Self {
series,
computed_features: RefCell::new(HashMap::new()),
}
}
pub fn get_feature<F>(&self, node: usize, name: &str, compute_fn: F) -> Option<T>
where
F: FnOnce(&[Option<T>], usize) -> Option<T>,
{
let key = (node, name.to_string());
if let Some(&value) = self.computed_features.borrow().get(&key) {
return value;
}
let value = compute_fn(&self.series, node);
self.computed_features.borrow_mut().insert(key, value);
value
}
pub fn clear_cache(&self) {
self.computed_features.borrow_mut().clear();
}
pub fn cache_size(&self) -> usize {
self.computed_features.borrow().len()
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_lazy_feature_caching() {
let series = vec![Some(1.0), Some(2.0), Some(3.0)];
let builder = LazyFeatureBuilder::new(series);
let mut compute_count = 0;
let _val1 = builder.get_feature(1, "test", |s, i| {
compute_count += 1;
s[i]
});
assert_eq!(compute_count, 1);
let _val2 = builder.get_feature(1, "test", |s, i| {
compute_count += 1;
s[i]
});
assert_eq!(compute_count, 1);
assert_eq!(builder.cache_size(), 1);
}
}