agentic_evolve_core/collective/
decay.rs1use crate::types::pattern::Pattern;
4
5#[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#[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#[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}