Skip to main content

pumpkin_checking/
variable.rs

1use std::fmt::Debug;
2
3use crate::AtomicConstraint;
4use crate::Comparison;
5use crate::IntExt;
6use crate::TestAtomic;
7use crate::VariableState;
8
9/// A variable in a constraint satisfaction problem.
10pub trait CheckerVariable<Atomic: AtomicConstraint>: Debug + Clone {
11    /// Tests whether the given atomic is a statement over the variable `self`.
12    fn does_atomic_constrain_self(&self, atomic: &Atomic) -> bool;
13
14    /// Get the atomic constraint `[self <= value]`.
15    fn atomic_less_than(&self, value: i32) -> Atomic;
16
17    /// Get the atomic constraint `[self <= value]`.
18    fn atomic_greater_than(&self, value: i32) -> Atomic;
19
20    /// Get the atomic constraint `[self == value]`.
21    fn atomic_equal(&self, value: i32) -> Atomic;
22
23    /// Get the atomic constraint `[self != value]`.
24    fn atomic_not_equal(&self, value: i32) -> Atomic;
25
26    /// Get the lower bound of the domain.
27    fn induced_lower_bound(&self, variable_state: &VariableState<Atomic>) -> IntExt;
28
29    /// Get the upper bound of the domain.
30    fn induced_upper_bound(&self, variable_state: &VariableState<Atomic>) -> IntExt;
31
32    /// Get the value the variable is fixed to, if the variable is fixed.
33    fn induced_fixed_value(&self, variable_state: &VariableState<Atomic>) -> Option<i32>;
34
35    /// Returns whether the value is in the domain.
36    fn induced_domain_contains(&self, variable_state: &VariableState<Atomic>, value: i32) -> bool;
37
38    /// Get the holes in the domain.
39    fn induced_holes<'this, 'state>(
40        &'this self,
41        variable_state: &'state VariableState<Atomic>,
42    ) -> impl Iterator<Item = i32> + 'state
43    where
44        'this: 'state;
45
46    /// Iterate the domain of the variable.
47    ///
48    /// The order of the values is unspecified.
49    fn iter_induced_domain<'this, 'state>(
50        &'this self,
51        variable_state: &'state VariableState<Atomic>,
52    ) -> Option<impl Iterator<Item = i32> + 'state>
53    where
54        'this: 'state;
55}
56
57impl CheckerVariable<TestAtomic> for &'static str {
58    fn does_atomic_constrain_self(&self, atomic: &TestAtomic) -> bool {
59        &atomic.name == self
60    }
61
62    fn atomic_less_than(&self, value: i32) -> TestAtomic {
63        TestAtomic {
64            name: self,
65            comparison: Comparison::LessEqual,
66            value,
67        }
68    }
69
70    fn atomic_greater_than(&self, value: i32) -> TestAtomic {
71        TestAtomic {
72            name: self,
73            comparison: Comparison::GreaterEqual,
74            value,
75        }
76    }
77
78    fn atomic_equal(&self, value: i32) -> TestAtomic {
79        TestAtomic {
80            name: self,
81            comparison: Comparison::Equal,
82            value,
83        }
84    }
85
86    fn atomic_not_equal(&self, value: i32) -> TestAtomic {
87        TestAtomic {
88            name: self,
89            comparison: Comparison::NotEqual,
90            value,
91        }
92    }
93
94    fn induced_lower_bound(&self, variable_state: &VariableState<TestAtomic>) -> IntExt {
95        variable_state.lower_bound(self)
96    }
97
98    fn induced_upper_bound(&self, variable_state: &VariableState<TestAtomic>) -> IntExt {
99        variable_state.upper_bound(self)
100    }
101
102    fn induced_fixed_value(&self, variable_state: &VariableState<TestAtomic>) -> Option<i32> {
103        variable_state.fixed_value(self)
104    }
105
106    fn induced_domain_contains(
107        &self,
108        variable_state: &VariableState<TestAtomic>,
109        value: i32,
110    ) -> bool {
111        variable_state.contains(self, value)
112    }
113
114    fn induced_holes<'this, 'state>(
115        &'this self,
116        variable_state: &'state VariableState<TestAtomic>,
117    ) -> impl Iterator<Item = i32> + 'state
118    where
119        'this: 'state,
120    {
121        variable_state.holes(self)
122    }
123
124    fn iter_induced_domain<'this, 'state>(
125        &'this self,
126        variable_state: &'state VariableState<TestAtomic>,
127    ) -> Option<impl Iterator<Item = i32> + 'state>
128    where
129        'this: 'state,
130    {
131        variable_state.iter_domain(self)
132    }
133}