1use crate::rete::alpha::AlphaNode;
2pub fn build_rete_ul_from_condition_group(group: &crate::rete::auto_network::ConditionGroup) -> ReteUlNode {
4 use crate::rete::auto_network::ConditionGroup;
5 match group {
6 ConditionGroup::Single(cond) => {
7 ReteUlNode::UlAlpha(AlphaNode {
8 field: cond.field.clone(),
9 operator: cond.operator.clone(),
10 value: cond.value.clone(),
11 })
12 }
13 ConditionGroup::Compound { left, operator, right } => {
14 match operator.as_str() {
15 "AND" => ReteUlNode::UlAnd(
16 Box::new(build_rete_ul_from_condition_group(left)),
17 Box::new(build_rete_ul_from_condition_group(right)),
18 ),
19 "OR" => ReteUlNode::UlOr(
20 Box::new(build_rete_ul_from_condition_group(left)),
21 Box::new(build_rete_ul_from_condition_group(right)),
22 ),
23 _ => ReteUlNode::UlAnd(
24 Box::new(build_rete_ul_from_condition_group(left)),
25 Box::new(build_rete_ul_from_condition_group(right)),
26 ),
27 }
28 }
29 ConditionGroup::Not(inner) => {
30 ReteUlNode::UlNot(Box::new(build_rete_ul_from_condition_group(inner)))
31 }
32 ConditionGroup::Exists(inner) => {
33 ReteUlNode::UlExists(Box::new(build_rete_ul_from_condition_group(inner)))
34 }
35 ConditionGroup::Forall(inner) => {
36 ReteUlNode::UlForall(Box::new(build_rete_ul_from_condition_group(inner)))
37 }
38 }
39}
40use std::collections::HashMap;
41
42pub fn evaluate_rete_ul_node(node: &ReteUlNode, facts: &HashMap<String, String>) -> bool {
44 match node {
45 ReteUlNode::UlAlpha(alpha) => {
46 let val = if alpha.field.contains('.') {
47 let parts: Vec<&str> = alpha.field.split('.').collect();
48 if parts.len() == 2 {
49 let prefix = parts[0];
50 let suffix = parts[1];
51 facts.get(&format!("{}.{}", prefix, suffix)).or_else(|| facts.get(&format!("{}:{}", prefix, suffix)))
52 } else {
53 facts.get(&alpha.field)
54 }
55 } else {
56 facts.get(&alpha.field)
57 };
58 if let Some(val) = val {
59 match alpha.operator.as_str() {
60 "==" => val == &alpha.value,
61 "!=" => val != &alpha.value,
62 ">" => val.parse::<f64>().unwrap_or(0.0) > alpha.value.parse::<f64>().unwrap_or(0.0),
63 "<" => val.parse::<f64>().unwrap_or(0.0) < alpha.value.parse::<f64>().unwrap_or(0.0),
64 ">=" => val.parse::<f64>().unwrap_or(0.0) >= alpha.value.parse::<f64>().unwrap_or(0.0),
65 "<=" => val.parse::<f64>().unwrap_or(0.0) <= alpha.value.parse::<f64>().unwrap_or(0.0),
66 _ => false,
67 }
68 } else {
69 false
70 }
71 }
72 ReteUlNode::UlAnd(left, right) => {
73 evaluate_rete_ul_node(left, facts) && evaluate_rete_ul_node(right, facts)
74 }
75 ReteUlNode::UlOr(left, right) => {
76 evaluate_rete_ul_node(left, facts) || evaluate_rete_ul_node(right, facts)
77 }
78 ReteUlNode::UlNot(inner) => {
79 !evaluate_rete_ul_node(inner, facts)
80 }
81 ReteUlNode::UlExists(inner) => {
82 let target_field = match &**inner {
83 ReteUlNode::UlAlpha(alpha) => alpha.field.clone(),
84 _ => "".to_string(),
85 };
86 if target_field.contains('.') {
87 let parts: Vec<&str> = target_field.split('.').collect();
88 if parts.len() == 2 {
89 let prefix = parts[0];
90 let suffix = parts[1];
91 let filtered: Vec<_> = facts.iter()
92 .filter(|(k, _)| k.starts_with(prefix) && k.ends_with(suffix))
93 .collect();
94 filtered.iter().any(|(_, value)| {
95 let mut sub_facts = HashMap::new();
96 sub_facts.insert(target_field.clone(), (*value).clone());
97 evaluate_rete_ul_node(inner, &sub_facts)
98 })
99 } else {
100 facts.iter().any(|(field, value)| {
101 let mut sub_facts = HashMap::new();
102 sub_facts.insert(field.clone(), value.clone());
103 evaluate_rete_ul_node(inner, &sub_facts)
104 })
105 }
106 } else {
107 facts.iter().any(|(field, value)| {
108 let mut sub_facts = HashMap::new();
109 sub_facts.insert(field.clone(), value.clone());
110 evaluate_rete_ul_node(inner, &sub_facts)
111 })
112 }
113 }
114 ReteUlNode::UlForall(inner) => {
115 let target_field = match &**inner {
116 ReteUlNode::UlAlpha(alpha) => alpha.field.clone(),
117 _ => "".to_string(),
118 };
119 if target_field.contains('.') {
120 let parts: Vec<&str> = target_field.split('.').collect();
121 if parts.len() == 2 {
122 let prefix = parts[0];
123 let suffix = parts[1];
124 let filtered: Vec<_> = facts.iter()
125 .filter(|(k, _)| k.starts_with(prefix) && k.ends_with(suffix))
126 .collect();
127 if filtered.is_empty() {
128 return true; }
130 filtered.iter().all(|(_, value)| {
131 let mut sub_facts = HashMap::new();
132 sub_facts.insert(target_field.clone(), (*value).clone());
133 evaluate_rete_ul_node(inner, &sub_facts)
134 })
135 } else {
136 facts.iter().all(|(field, value)| {
137 let mut sub_facts = HashMap::new();
138 sub_facts.insert(field.clone(), value.clone());
139 evaluate_rete_ul_node(inner, &sub_facts)
140 })
141 }
142 } else {
143 facts.iter().all(|(field, value)| {
144 let mut sub_facts = HashMap::new();
145 sub_facts.insert(field.clone(), value.clone());
146 evaluate_rete_ul_node(inner, &sub_facts)
147 })
148 }
149 }
150 ReteUlNode::UlTerminal(_) => true }
152}
153
154#[derive(Debug, Clone)]
156pub enum ReteUlNode {
157 UlAlpha(AlphaNode),
158 UlAnd(Box<ReteUlNode>, Box<ReteUlNode>),
159 UlOr(Box<ReteUlNode>, Box<ReteUlNode>),
160 UlNot(Box<ReteUlNode>),
161 UlExists(Box<ReteUlNode>),
162 UlForall(Box<ReteUlNode>),
163 UlTerminal(String), }
165
166impl ReteUlNode {
167 pub fn evaluate_typed(&self, facts: &super::facts::TypedFacts) -> bool {
169 evaluate_rete_ul_node_typed(self, facts)
170 }
171}
172
173pub struct ReteUlRule {
175 pub name: String,
176 pub node: ReteUlNode,
177 pub priority: i32,
178 pub no_loop: bool,
179 pub action: Box<dyn FnMut(&mut std::collections::HashMap<String, String>)>,
180}
181
182pub fn fire_rete_ul_rules(
185 rules: &mut [(String, ReteUlNode, Box<dyn FnMut(&mut std::collections::HashMap<String, String>)>)],
186 facts: &mut std::collections::HashMap<String, String>,
187) -> Vec<String> {
188 let mut fired_rules = Vec::new();
189 let mut changed = true;
190 while changed {
191 changed = false;
192 for (rule_name, node, action) in rules.iter_mut() {
193 let fired_flag = format!("{}_fired", rule_name);
194 if facts.get(&fired_flag) == Some(&"true".to_string()) {
195 continue;
196 }
197 if evaluate_rete_ul_node(node, facts) {
198 action(facts);
199 facts.insert(fired_flag.clone(), "true".to_string());
200 fired_rules.push(rule_name.clone());
201 changed = true;
202 }
203 }
204 }
205 fired_rules
206}
207
208pub fn fire_rete_ul_rules_with_agenda(
210 rules: &mut [ReteUlRule],
211 facts: &mut std::collections::HashMap<String, String>,
212) -> Vec<String> {
213 let mut fired_rules = Vec::new();
214 let mut fired_flags = std::collections::HashSet::new();
215 let max_iterations = 100; let mut iterations = 0;
217
218 loop {
219 iterations += 1;
220 if iterations > max_iterations {
221 eprintln!("Warning: RETE engine reached max iterations ({})", max_iterations);
222 break;
223 }
224
225 let mut agenda: Vec<usize> = rules
227 .iter()
228 .enumerate()
229 .filter(|(_, rule)| {
230 if fired_flags.contains(&rule.name) {
232 return false;
233 }
234 evaluate_rete_ul_node(&rule.node, facts)
236 })
237 .map(|(i, _)| i)
238 .collect();
239
240 if agenda.is_empty() {
242 break;
243 }
244
245 agenda.sort_by_key(|&i| -rules[i].priority);
247
248 for &i in &agenda {
250 let rule = &mut rules[i];
251
252 (rule.action)(facts);
254
255 fired_rules.push(rule.name.clone());
257 fired_flags.insert(rule.name.clone());
258
259 let fired_flag = format!("{}_fired", rule.name);
260 facts.insert(fired_flag, "true".to_string());
261 }
262
263 if rules.iter().all(|r| r.no_loop) {
265 break;
266 }
267 }
268
269 fired_rules
270}
271
272pub struct ReteUlEngine {
275 rules: Vec<ReteUlRule>,
276 facts: std::collections::HashMap<String, String>,
277}
278
279impl ReteUlEngine {
280 pub fn new() -> Self {
282 Self {
283 rules: Vec::new(),
284 facts: std::collections::HashMap::new(),
285 }
286 }
287
288 pub fn add_rule_with_action<F>(
290 &mut self,
291 name: String,
292 node: ReteUlNode,
293 priority: i32,
294 no_loop: bool,
295 action: F,
296 ) where
297 F: FnMut(&mut std::collections::HashMap<String, String>) + 'static,
298 {
299 self.rules.push(ReteUlRule {
300 name,
301 node,
302 priority,
303 no_loop,
304 action: Box::new(action),
305 });
306 }
307
308 pub fn add_rule_from_definition(
310 &mut self,
311 rule: &crate::rete::auto_network::Rule,
312 priority: i32,
313 no_loop: bool,
314 ) {
315 let node = build_rete_ul_from_condition_group(&rule.conditions);
316 let rule_name = rule.name.clone();
317
318 let action = Box::new(move |facts: &mut std::collections::HashMap<String, String>| {
320 facts.insert(format!("{}_executed", rule_name), "true".to_string());
321 }) as Box<dyn FnMut(&mut std::collections::HashMap<String, String>)>;
322
323 self.rules.push(ReteUlRule {
324 name: rule.name.clone(),
325 node,
326 priority,
327 no_loop,
328 action,
329 });
330 }
331
332 pub fn set_fact(&mut self, key: String, value: String) {
334 self.facts.insert(key, value);
335 }
336
337 pub fn get_fact(&self, key: &str) -> Option<&String> {
339 self.facts.get(key)
340 }
341
342 pub fn remove_fact(&mut self, key: &str) -> Option<String> {
344 self.facts.remove(key)
345 }
346
347 pub fn get_all_facts(&self) -> &std::collections::HashMap<String, String> {
349 &self.facts
350 }
351
352 pub fn clear_facts(&mut self) {
354 self.facts.clear();
355 }
356
357 pub fn fire_all(&mut self) -> Vec<String> {
359 fire_rete_ul_rules_with_agenda(&mut self.rules, &mut self.facts)
360 }
361
362 pub fn matches(&self, rule_name: &str) -> bool {
364 self.rules
365 .iter()
366 .find(|r| r.name == rule_name)
367 .map(|r| evaluate_rete_ul_node(&r.node, &self.facts))
368 .unwrap_or(false)
369 }
370
371 pub fn get_matching_rules(&self) -> Vec<&str> {
373 self.rules
374 .iter()
375 .filter(|r| evaluate_rete_ul_node(&r.node, &self.facts))
376 .map(|r| r.name.as_str())
377 .collect()
378 }
379
380 pub fn reset_fired_flags(&mut self) {
382 let keys_to_remove: Vec<_> = self.facts
383 .keys()
384 .filter(|k| k.ends_with("_fired") || k.ends_with("_executed"))
385 .cloned()
386 .collect();
387 for key in keys_to_remove {
388 self.facts.remove(&key);
389 }
390 }
391}
392
393use super::facts::{FactValue, TypedFacts};
398
399pub fn evaluate_rete_ul_node_typed(node: &ReteUlNode, facts: &TypedFacts) -> bool {
401 match node {
402 ReteUlNode::UlAlpha(alpha) => {
403 alpha.matches_typed(facts)
404 }
405 ReteUlNode::UlAnd(left, right) => {
406 evaluate_rete_ul_node_typed(left, facts) && evaluate_rete_ul_node_typed(right, facts)
407 }
408 ReteUlNode::UlOr(left, right) => {
409 evaluate_rete_ul_node_typed(left, facts) || evaluate_rete_ul_node_typed(right, facts)
410 }
411 ReteUlNode::UlNot(inner) => {
412 !evaluate_rete_ul_node_typed(inner, facts)
413 }
414 ReteUlNode::UlExists(inner) => {
415 let target_field = match &**inner {
416 ReteUlNode::UlAlpha(alpha) => alpha.field.clone(),
417 _ => "".to_string(),
418 };
419 if target_field.contains('.') {
420 let parts: Vec<&str> = target_field.split('.').collect();
421 if parts.len() == 2 {
422 let prefix = parts[0];
423 let suffix = parts[1];
424 let filtered: Vec<_> = facts.get_all().iter()
425 .filter(|(k, _)| k.starts_with(prefix) && k.ends_with(suffix))
426 .collect();
427 filtered.iter().any(|(_, _)| {
428 evaluate_rete_ul_node_typed(inner, facts)
429 })
430 } else {
431 evaluate_rete_ul_node_typed(inner, facts)
432 }
433 } else {
434 evaluate_rete_ul_node_typed(inner, facts)
435 }
436 }
437 ReteUlNode::UlForall(inner) => {
438 let target_field = match &**inner {
439 ReteUlNode::UlAlpha(alpha) => alpha.field.clone(),
440 _ => "".to_string(),
441 };
442 if target_field.contains('.') {
443 let parts: Vec<&str> = target_field.split('.').collect();
444 if parts.len() == 2 {
445 let prefix = parts[0];
446 let suffix = parts[1];
447 let filtered: Vec<_> = facts.get_all().iter()
448 .filter(|(k, _)| k.starts_with(prefix) && k.ends_with(suffix))
449 .collect();
450 if filtered.is_empty() {
451 return true; }
453 filtered.iter().all(|(_, _)| {
454 evaluate_rete_ul_node_typed(inner, facts)
455 })
456 } else {
457 if facts.get_all().is_empty() {
458 return true; }
460 evaluate_rete_ul_node_typed(inner, facts)
461 }
462 } else {
463 if facts.get_all().is_empty() {
464 return true; }
466 evaluate_rete_ul_node_typed(inner, facts)
467 }
468 }
469 ReteUlNode::UlTerminal(_) => true
470 }
471}
472
473pub struct TypedReteUlRule {
475 pub name: String,
476 pub node: ReteUlNode,
477 pub priority: i32,
478 pub no_loop: bool,
479 pub action: Box<dyn FnMut(&mut TypedFacts)>,
480}
481
482pub struct TypedReteUlEngine {
485 rules: Vec<TypedReteUlRule>,
486 facts: TypedFacts,
487}
488
489impl TypedReteUlEngine {
490 pub fn new() -> Self {
492 Self {
493 rules: Vec::new(),
494 facts: TypedFacts::new(),
495 }
496 }
497
498 pub fn add_rule_with_action<F>(
500 &mut self,
501 name: String,
502 node: ReteUlNode,
503 priority: i32,
504 no_loop: bool,
505 action: F,
506 ) where
507 F: FnMut(&mut TypedFacts) + 'static,
508 {
509 self.rules.push(TypedReteUlRule {
510 name,
511 node,
512 priority,
513 no_loop,
514 action: Box::new(action),
515 });
516 }
517
518 pub fn add_rule_from_definition(
520 &mut self,
521 rule: &crate::rete::auto_network::Rule,
522 priority: i32,
523 no_loop: bool,
524 ) {
525 let node = build_rete_ul_from_condition_group(&rule.conditions);
526 let rule_name = rule.name.clone();
527
528 let action = Box::new(move |facts: &mut TypedFacts| {
529 facts.set(format!("{}_executed", rule_name), true);
530 }) as Box<dyn FnMut(&mut TypedFacts)>;
531
532 self.rules.push(TypedReteUlRule {
533 name: rule.name.clone(),
534 node,
535 priority,
536 no_loop,
537 action,
538 });
539 }
540
541 pub fn set_fact<K: Into<String>, V: Into<FactValue>>(&mut self, key: K, value: V) {
543 self.facts.set(key, value);
544 }
545
546 pub fn get_fact(&self, key: &str) -> Option<&FactValue> {
548 self.facts.get(key)
549 }
550
551 pub fn remove_fact(&mut self, key: &str) -> Option<FactValue> {
553 self.facts.remove(key)
554 }
555
556 pub fn get_all_facts(&self) -> &TypedFacts {
558 &self.facts
559 }
560
561 pub fn clear_facts(&mut self) {
563 self.facts.clear();
564 }
565
566 pub fn fire_all(&mut self) -> Vec<String> {
568 let mut fired_rules = Vec::new();
569 let mut agenda: Vec<usize>;
570 let mut changed = true;
571 let mut fired_flags = std::collections::HashSet::new();
572
573 while changed {
574 changed = false;
575
576 agenda = self.rules.iter().enumerate()
578 .filter(|(_, rule)| {
579 let fired_flag = format!("{}_fired", rule.name);
580 let already_fired = fired_flags.contains(&rule.name) ||
581 self.facts.get(&fired_flag).and_then(|v| v.as_boolean()) == Some(true);
582 !rule.no_loop || !already_fired
583 })
584 .filter(|(_, rule)| evaluate_rete_ul_node_typed(&rule.node, &self.facts))
585 .map(|(i, _)| i)
586 .collect();
587
588 agenda.sort_by_key(|&i| -self.rules[i].priority);
590
591 for &i in &agenda {
592 let rule = &mut self.rules[i];
593 let fired_flag = format!("{}_fired", rule.name);
594 let already_fired = fired_flags.contains(&rule.name) ||
595 self.facts.get(&fired_flag).and_then(|v| v.as_boolean()) == Some(true);
596
597 if rule.no_loop && already_fired {
598 continue;
599 }
600
601 (rule.action)(&mut self.facts);
602 fired_rules.push(rule.name.clone());
603 fired_flags.insert(rule.name.clone());
604 self.facts.set(fired_flag, true);
605 changed = true;
606 }
607 }
608
609 fired_rules
610 }
611
612 pub fn matches(&self, rule_name: &str) -> bool {
614 self.rules
615 .iter()
616 .find(|r| r.name == rule_name)
617 .map(|r| evaluate_rete_ul_node_typed(&r.node, &self.facts))
618 .unwrap_or(false)
619 }
620
621 pub fn get_matching_rules(&self) -> Vec<&str> {
623 self.rules
624 .iter()
625 .filter(|r| evaluate_rete_ul_node_typed(&r.node, &self.facts))
626 .map(|r| r.name.as_str())
627 .collect()
628 }
629
630 pub fn reset_fired_flags(&mut self) {
632 let keys_to_remove: Vec<_> = self.facts.get_all()
633 .keys()
634 .filter(|k| k.ends_with("_fired") || k.ends_with("_executed"))
635 .cloned()
636 .collect();
637 for key in keys_to_remove {
638 self.facts.remove(&key);
639 }
640 }
641}
642
643impl Default for TypedReteUlEngine {
644 fn default() -> Self {
645 Self::new()
646 }
647}
648