Skip to main content

dtrees_rs/algorithms/optimal/rules/
manager.rs

1use crate::algorithms::optimal::rules::core::{Rule, RuleContext, RuleResult};
2
3/// An ordered set of rules, evaluated by decreasing priority.
4pub struct RuleManager {
5    rules: Vec<Box<dyn Rule>>,
6}
7
8impl Default for RuleManager {
9    fn default() -> Self {
10        Self::new()
11    }
12}
13
14impl RuleManager {
15    /// An empty set of rules.
16    pub fn new() -> Self {
17        Self { rules: Vec::new() }
18    }
19
20    /// Activates every rule.
21    pub fn activate_all(&mut self) {
22        for rule in self.rules.iter_mut() {
23            rule.activate();
24        }
25    }
26
27    /// Adds a rule, keeping the set sorted by priority.
28    pub fn add_rule(&mut self, rule: Box<dyn Rule>) {
29        self.rules.push(rule);
30        self.rules
31            .sort_by_key(|rule| std::cmp::Reverse(rule.priority()));
32    }
33
34    /// Relaxes every rule before a new pass.
35    pub fn relax_all(&mut self) {
36        for rule in self.rules.iter_mut() {
37            rule.relax();
38        }
39    }
40
41    /// Resets every rule.
42    pub fn reset_all(&mut self) {
43        for rule in self.rules.iter_mut() {
44            rule.reset();
45        }
46    }
47
48    pub fn len(&self) -> usize {
49        self.rules.len()
50    }
51
52    pub fn is_empty(&self) -> bool {
53        self.rules.is_empty()
54    }
55
56    /// Removes every rule.
57    pub fn clear_rules(&mut self) {
58        self.rules.clear();
59    }
60
61    /// Whether some relaxable rule is still active, i.e. whether the search
62    /// may still be restricted.
63    pub fn is_active(&self) -> bool {
64        for rule in &self.rules {
65            if rule.is_relaxable() && rule.is_active() {
66                return true;
67            }
68        }
69        false
70    }
71
72    /// Evaluates the rules in order and returns the first one that stops the
73    /// search, or a result that lets it continue.
74    pub fn evaluate(&self, context: &RuleContext) -> RuleResult {
75        for rule in &self.rules {
76            let result = rule.evaluate(context);
77            if !result.continue_search {
78                return result;
79            }
80        }
81        RuleResult::continue_search()
82    }
83
84    /// `(description, state)` of every rule.
85    pub fn get_rule_states(&self) -> Vec<(String, String)> {
86        self.rules
87            .iter()
88            .map(|rule| (rule.description(), format!("{}", rule.state())))
89            .collect()
90    }
91
92    /// The first rule of type `T`, if any.
93    pub fn get_rule_mut<T: 'static>(&mut self) -> Option<&mut T> {
94        for rule in &mut self.rules {
95            if let Some(concrete_rule) = rule.as_any_mut().downcast_mut::<T>() {
96                return Some(concrete_rule);
97            }
98        }
99        None
100    }
101}