strange_loop/nano_agent/
agents.rs

1//! Example nano-agents
2
3use super::{NanoAgent, NanoBus, Message, TickResult, spin};
4use super::bus::MessageData;
5// use crate::TemporalLeadPredictor; // Module not implemented yet
6use crate::quantum_container::QuantumContainer;
7use crate::self_modifying::SelfModifyingLoop;
8
9// Note: Some advanced agents are disabled due to module dependencies
10
11/// Sensor agent that generates periodic signals
12pub struct SensorAgent {
13    counter: u64,
14    period_ticks: u32,
15    current_tick: u32,
16}
17
18impl SensorAgent {
19    pub fn new(period_ticks: u32) -> Self {
20        Self {
21            counter: 0,
22            period_ticks,
23            current_tick: 0,
24        }
25    }
26}
27
28impl NanoAgent for SensorAgent {
29    fn name(&self) -> &'static str { "sensor" }
30
31    #[inline(always)]
32    fn tick(&mut self, now_ns: u128, bus: &NanoBus) -> TickResult {
33        self.current_tick = self.current_tick.wrapping_add(1);
34
35        let mut messages_sent = 0;
36
37        if self.current_tick % self.period_ticks == 0 {
38            self.counter = self.counter.wrapping_add(1);
39            bus.publish(Message {
40                topic: "sensor:data",
41                data: MessageData::U64(self.counter),
42                timestamp_ns: now_ns,
43            });
44            messages_sent = 1;
45        }
46
47        TickResult {
48            cycles: 100, // Minimal cycles
49            messages_sent,
50            messages_recv: 0,
51            budget_used_ns: 50,
52        }
53    }
54
55    fn budget_ns(&self) -> u128 { 1000 } // 1 microsecond
56}
57
58/// Debouncer agent that filters noisy signals
59pub struct DebounceAgent {
60    last_value: u64,
61    stable_count: u32,
62    stability_threshold: u32,
63    spin_cycles: u32,
64}
65
66impl DebounceAgent {
67    pub fn new(stability_threshold: u32) -> Self {
68        Self {
69            last_value: 0,
70            stable_count: 0,
71            stability_threshold,
72            spin_cycles: 16,
73        }
74    }
75}
76
77impl NanoAgent for DebounceAgent {
78    fn name(&self) -> &'static str { "debouncer" }
79
80    #[inline(always)]
81    fn tick(&mut self, now_ns: u128, bus: &NanoBus) -> TickResult {
82        let mut messages_recv = 0;
83        let mut messages_sent = 0;
84        let mut changed = None;
85
86        // Process up to 8 messages
87        for _ in 0..8 {
88            if let Some(msg) = bus.try_recv() {
89                messages_recv += 1;
90
91                if msg.topic == "sensor:data" {
92                    if let MessageData::U64(value) = msg.data {
93                        if value == self.last_value {
94                            self.stable_count += 1;
95                        } else {
96                            self.stable_count = 0;
97                            self.last_value = value;
98                        }
99
100                        if self.stable_count >= self.stability_threshold {
101                            changed = Some(self.last_value);
102                            self.stable_count = 0;
103                        }
104                    }
105                }
106            } else {
107                break;
108            }
109        }
110
111        // Publish stable signal
112        if let Some(value) = changed {
113            bus.publish(Message {
114                topic: "signal:stable",
115                data: MessageData::U64(value),
116                timestamp_ns: now_ns,
117            });
118            messages_sent = 1;
119        }
120
121        // Controlled spin to maintain timing
122        for _ in 0..self.spin_cycles {
123            spin();
124        }
125
126        TickResult {
127            cycles: 200,
128            messages_sent,
129            messages_recv,
130            budget_used_ns: 100,
131        }
132    }
133
134    fn budget_ns(&self) -> u128 { 2000 } // 2 microseconds
135}
136
137/// Quantum decision-making agent
138pub struct QuantumDecisionAgent {
139    quantum_state: QuantumContainer,
140    decision_count: u64,
141}
142
143impl QuantumDecisionAgent {
144    pub fn new() -> Self {
145        Self {
146            quantum_state: QuantumContainer::new(3), // 8 possible decisions
147            decision_count: 0,
148        }
149    }
150}
151
152impl NanoAgent for QuantumDecisionAgent {
153    fn name(&self) -> &'static str { "quantum_decision" }
154
155    fn tick(&mut self, now_ns: u128, bus: &NanoBus) -> TickResult {
156        let mut messages_sent = 0;
157
158        // Make quantum decision periodically
159        if self.decision_count % 100 == 0 {
160            // Create superposition of decisions
161            let amplitude = crate::types::QuantumAmplitude::new(
162                1.0 / (8.0_f64).sqrt(), 0.0
163            );
164            for i in 0..8 {
165                self.quantum_state.set_superposition_state(i, amplitude);
166            }
167
168            // Collapse to decision
169            let decision = self.quantum_state.measure();
170
171            bus.publish(Message {
172                topic: "quantum:decision",
173                data: MessageData::U64(decision as u64),
174                timestamp_ns: now_ns,
175            });
176            messages_sent = 1;
177        }
178
179        self.decision_count += 1;
180
181        TickResult {
182            cycles: 500,
183            messages_sent,
184            messages_recv: 0,
185            budget_used_ns: 300,
186        }
187    }
188
189    fn budget_ns(&self) -> u128 { 5000 } // 5 microseconds
190}
191
192/// Temporal prediction agent
193pub struct TemporalPredictorAgent {
194    // predictor: TemporalLeadPredictor, // Module not implemented yet
195    prediction_count: u64,
196}
197
198impl TemporalPredictorAgent {
199    pub fn new() -> Self {
200        Self {
201            // predictor: TemporalLeadPredictor::new(100_000, 50), // Module not implemented
202            prediction_count: 0,
203        }
204    }
205}
206
207impl NanoAgent for TemporalPredictorAgent {
208    fn name(&self) -> &'static str { "temporal_predictor" }
209
210    fn tick(&mut self, now_ns: u128, bus: &NanoBus) -> TickResult {
211        let mut messages_recv = 0;
212        let mut messages_sent = 0;
213
214        // Collect sensor data for prediction
215        for _ in 0..4 {
216            if let Some(msg) = bus.try_recv() {
217                messages_recv += 1;
218
219                if msg.topic == "sensor:data" {
220                    if let MessageData::U64(value) = msg.data {
221                        // Feed to predictor
222                        let state = vec![value as f64];
223                        // let future = self.predictor.predict_future(state); // Module not implemented
224                        let future = 0.5; // Placeholder prediction
225
226                        // Publish prediction
227                        if self.prediction_count % 10 == 0 {
228                            bus.publish(Message {
229                                topic: "prediction:future",
230                                data: MessageData::F64(future),
231                                timestamp_ns: now_ns,
232                            });
233                            messages_sent = 1;
234                        }
235                    }
236                }
237            } else {
238                break;
239            }
240        }
241
242        self.prediction_count += 1;
243
244        TickResult {
245            cycles: 1000,
246            messages_sent,
247            messages_recv,
248            budget_used_ns: 500,
249        }
250    }
251
252    fn budget_ns(&self) -> u128 { 10_000 } // 10 microseconds
253}
254
255/// Self-modifying agent that evolves its behavior
256pub struct EvolvingAgent {
257    evolution_loop: SelfModifyingLoop,
258    generation: u64,
259}
260
261impl EvolvingAgent {
262    pub fn new() -> Self {
263        Self {
264            evolution_loop: SelfModifyingLoop::new(0.1),
265            generation: 0,
266        }
267    }
268}
269
270impl NanoAgent for EvolvingAgent {
271    fn name(&self) -> &'static str { "evolving" }
272
273    fn tick(&mut self, now_ns: u128, bus: &NanoBus) -> TickResult {
274        let mut messages_sent = 0;
275
276        // Execute evolved function
277        let input = (self.generation as f64) * 0.01;
278        let output = self.evolution_loop.execute(input);
279
280        // Calculate fitness based on output
281        let target = 1.618033988749; // Golden ratio
282        let fitness = 1.0 / (1.0 + (output - target).abs());
283
284        // Evolve periodically
285        if self.generation % 100 == 0 {
286            self.evolution_loop.evolve(fitness);
287
288            // Publish evolution metrics
289            let metrics = self.evolution_loop.get_metrics();
290            bus.publish(Message {
291                topic: "evolution:fitness",
292                data: MessageData::F64(metrics.current_fitness),
293                timestamp_ns: now_ns,
294            });
295            messages_sent = 1;
296        }
297
298        self.generation += 1;
299
300        TickResult {
301            cycles: 2000,
302            messages_sent,
303            messages_recv: 0,
304            budget_used_ns: 1000,
305        }
306    }
307
308    fn budget_ns(&self) -> u128 { 20_000 } // 20 microseconds
309}