Reactive Agent Pattern
The Reactive Agent Pattern creates agents that respond immediately to environmental changes without complex planning, focusing on stimulus-response behavior.
Pattern Overview
This pattern implements agents that react to environmental stimuli through condition-action rules, enabling fast response times and simple decision-making.
Structure
use std::collections::HashMap;
// Environmental stimulus
#[derive(Debug, Clone)]
pub struct Stimulus {
pub sensor: String,
pub value: f64,
pub timestamp: u64,
}
// Agent response/action
#[derive(Debug, Clone)]
pub struct Response {
pub action: String,
pub parameters: HashMap<String, String>,
}
// Condition-action rule
pub struct Rule {
pub condition: fn(&Stimulus) -> bool,
pub action: fn(&Stimulus) -> Response,
pub priority: u8,
}
// Reactive agent implementation
pub struct ReactiveAgent {
id: String,
rules: Vec<Rule>,
sensors: Vec<String>,
}
impl ReactiveAgent {
pub fn new(id: &str) -> Self {
Self {
id: id.to_string(),
rules: Vec::new(),
sensors: Vec::new(),
}
}
pub fn add_sensor(&mut self, sensor: String) {
self.sensors.push(sensor);
}
pub fn add_rule(&mut self, rule: Rule) {
self.rules.push(rule);
}
pub fn sense_and_act(&self, stimuli: &[Stimulus]) -> Vec<Response> {
let mut responses = Vec::new();
for stimulus in stimuli {
// Check if this agent can sense this stimulus
if self.sensors.contains(&stimulus.sensor) {
// Find matching rules and execute highest priority
let mut matching_rules: Vec<&Rule> = self.rules
.iter()
.filter(|rule| (rule.condition)(stimulus))
.collect();
// Sort by priority (highest first)
matching_rules.sort_by(|a, b| b.priority.cmp(&a.priority));
if let Some(rule) = matching_rules.first() {
let response = (rule.action)(stimulus);
responses.push(response);
}
}
}
responses
}
}
// Example condition functions
pub fn temperature_high(stimulus: &Stimulus) -> bool {
stimulus.sensor == "temperature" && stimulus.value > 25.0
}
pub fn pressure_low(stimulus: &Stimulus) -> bool {
stimulus.sensor == "pressure" && stimulus.value < 10.0
}
pub fn motion_detected(stimulus: &Stimulus) -> bool {
stimulus.sensor == "motion" && stimulus.value > 0.0
}
// Example action functions
pub fn activate_cooling(stimulus: &Stimulus) -> Response {
let mut params = HashMap::new();
params.insert("intensity".to_string(), stimulus.value.to_string());
Response {
action: "activate_cooling".to_string(),
parameters: params,
}
}
pub fn increase_pressure(stimulus: &Stimulus) -> Response {
Response {
action: "increase_pressure".to_string(),
parameters: HashMap::new(),
}
}
pub fn trigger_alert(stimulus: &Stimulus) -> Response {
let mut params = HashMap::new();
params.insert("location".to_string(), "facility_a".to_string());
Response {
action: "security_alert".to_string(),
parameters: params,
}
}Usage Example
let mut agent = ReactiveAgent::new("SecurityAgent");
// Add sensors
agent.add_sensor("motion".to_string());
agent.add_sensor("temperature".to_string());
// Add rules
agent.add_rule(Rule {
condition: motion_detected,
action: trigger_alert,
priority: 9,
});
agent.add_rule(Rule {
condition: temperature_high,
action: activate_cooling,
priority: 5,
});
// Create stimuli
let stimuli = vec![
Stimulus {
sensor: "motion".to_string(),
value: 1.0,
timestamp: 12345,
},
Stimulus {
sensor: "temperature".to_string(),
value: 28.0,
timestamp: 12346,
},
];
// Agent reacts to stimuli
let responses = agent.sense_and_act(&stimuli);Benefits
- Fast Response: Immediate reaction to environmental changes
- Simplicity: Easy to understand and implement
- Robustness: Continues functioning even with partial sensor failures
- Real-time: Suitable for time-critical applications
Use Cases
- IoT device monitoring and control
- Real-time anomaly detection
- Emergency response systems
- Automated trading based on market signals