Skip to main content

agentic_evolve_core/collective/
decay.rs

1//! DecayManager — manages confidence decay of unused patterns.
2
3use crate::types::pattern::Pattern;
4
5/// Configuration for decay behavior.
6#[derive(Debug, Clone)]
7pub struct DecayConfig {
8    pub half_life_days: f64,
9    pub min_confidence: f64,
10    pub usage_boost: f64,
11    pub success_boost: f64,
12}
13
14impl Default for DecayConfig {
15    fn default() -> Self {
16        Self {
17            half_life_days: 30.0,
18            min_confidence: 0.1,
19            usage_boost: 0.05,
20            success_boost: 0.1,
21        }
22    }
23}
24
25/// Manages confidence decay of patterns over time.
26#[derive(Debug)]
27pub struct DecayManager {
28    config: DecayConfig,
29}
30
31impl DecayManager {
32    pub fn new(config: DecayConfig) -> Self {
33        Self { config }
34    }
35
36    pub fn apply_decay(&self, pattern: &mut Pattern) -> f64 {
37        let now = chrono::Utc::now().timestamp();
38        let days_since_use = (now - pattern.last_used) as f64 / 86400.0;
39
40        if days_since_use <= 0.0 {
41            return pattern.confidence;
42        }
43
44        let decay_factor = 0.5_f64.powf(days_since_use / self.config.half_life_days);
45        let new_confidence = (pattern.confidence * decay_factor).max(self.config.min_confidence);
46        pattern.confidence = new_confidence;
47        new_confidence
48    }
49
50    pub fn apply_usage_boost(&self, pattern: &mut Pattern, success: bool) -> f64 {
51        let boost = if success {
52            self.config.usage_boost + self.config.success_boost
53        } else {
54            self.config.usage_boost
55        };
56        pattern.confidence = (pattern.confidence + boost).min(1.0);
57        pattern.confidence
58    }
59
60    pub fn should_prune(&self, pattern: &Pattern) -> bool {
61        let now = chrono::Utc::now().timestamp();
62        let days_since_use = (now - pattern.last_used) as f64 / 86400.0;
63        pattern.confidence <= self.config.min_confidence
64            && days_since_use > self.config.half_life_days * 3.0
65            && pattern.usage_count < 3
66    }
67
68    pub fn decay_report(&self, patterns: &[&Pattern]) -> DecayReport {
69        let mut healthy = 0;
70        let mut decaying = 0;
71        let mut critical = 0;
72        let mut prunable = 0;
73
74        for pattern in patterns {
75            if pattern.confidence > 0.7 {
76                healthy += 1;
77            } else if pattern.confidence > 0.3 {
78                decaying += 1;
79            } else {
80                critical += 1;
81            }
82            if self.should_prune(pattern) {
83                prunable += 1;
84            }
85        }
86
87        DecayReport {
88            total: patterns.len(),
89            healthy,
90            decaying,
91            critical,
92            prunable,
93        }
94    }
95}
96
97impl Default for DecayManager {
98    fn default() -> Self {
99        Self::new(DecayConfig::default())
100    }
101}
102
103/// Report on pattern decay status.
104#[derive(Debug, Clone)]
105pub struct DecayReport {
106    pub total: usize,
107    pub healthy: usize,
108    pub decaying: usize,
109    pub critical: usize,
110    pub prunable: usize,
111}