Skip to main content

pumpkin_core/engine/variables/
domain_id.rs

1use enumset::EnumSet;
2use pumpkin_checking::CheckerVariable;
3
4use super::TransformableVariable;
5use crate::containers::StorageKey;
6use crate::engine::Assignments;
7use crate::engine::notifications::DomainEvent;
8use crate::engine::notifications::OpaqueDomainEvent;
9use crate::engine::notifications::Watchers;
10use crate::engine::variables::AffineView;
11use crate::engine::variables::IntegerVariable;
12use crate::predicates::Predicate;
13use crate::predicates::PredicateConstructor;
14use crate::predicates::PredicateType;
15use crate::pumpkin_assert_simple;
16
17/// A structure which represents the most basic [`IntegerVariable`]; it is simply the id which links
18/// to a domain (hence the name).
19#[derive(Clone, PartialEq, Eq, Copy, Hash, PartialOrd, Ord)]
20pub struct DomainId {
21    id: u32,
22}
23
24impl DomainId {
25    pub fn new(id: u32) -> Self {
26        pumpkin_assert_simple!(id >> 30 == 0, "The first two bits are used as flags");
27        DomainId { id }
28    }
29
30    pub fn id(&self) -> u32 {
31        self.id
32    }
33}
34
35impl CheckerVariable<Predicate> for DomainId {
36    fn does_atomic_constrain_self(&self, atomic: &Predicate) -> bool {
37        atomic.get_domain() == *self
38    }
39
40    fn atomic_less_than(&self, value: i32) -> Predicate {
41        use crate::predicate;
42
43        predicate![self <= value]
44    }
45
46    fn atomic_greater_than(&self, value: i32) -> Predicate {
47        use crate::predicate;
48
49        predicate![self >= value]
50    }
51
52    fn atomic_equal(&self, value: i32) -> Predicate {
53        use crate::predicate;
54
55        predicate![self == value]
56    }
57
58    fn atomic_not_equal(&self, value: i32) -> Predicate {
59        use crate::predicate;
60
61        predicate![self != value]
62    }
63
64    fn induced_lower_bound(
65        &self,
66        variable_state: &pumpkin_checking::VariableState<Predicate>,
67    ) -> pumpkin_checking::IntExt {
68        variable_state.lower_bound(self)
69    }
70
71    fn induced_upper_bound(
72        &self,
73        variable_state: &pumpkin_checking::VariableState<Predicate>,
74    ) -> pumpkin_checking::IntExt {
75        variable_state.upper_bound(self)
76    }
77
78    fn induced_fixed_value(
79        &self,
80        variable_state: &pumpkin_checking::VariableState<Predicate>,
81    ) -> Option<i32> {
82        variable_state.fixed_value(self)
83    }
84
85    fn induced_domain_contains(
86        &self,
87        variable_state: &pumpkin_checking::VariableState<Predicate>,
88        value: i32,
89    ) -> bool {
90        variable_state.contains(self, value)
91    }
92
93    fn induced_holes<'this, 'state>(
94        &'this self,
95        variable_state: &'state pumpkin_checking::VariableState<Predicate>,
96    ) -> impl Iterator<Item = i32> + 'state
97    where
98        'this: 'state,
99    {
100        variable_state.holes(self)
101    }
102
103    fn iter_induced_domain<'this, 'state>(
104        &'this self,
105        variable_state: &'state pumpkin_checking::VariableState<Predicate>,
106    ) -> Option<impl Iterator<Item = i32> + 'state>
107    where
108        'this: 'state,
109    {
110        variable_state.iter_domain(self)
111    }
112}
113
114impl IntegerVariable for DomainId {
115    type AffineView = AffineView<Self>;
116
117    fn lower_bound(&self, assignment: &Assignments) -> i32 {
118        assignment.get_lower_bound(*self)
119    }
120
121    fn lower_bound_at_trail_position(
122        &self,
123        assignment: &Assignments,
124        trail_position: usize,
125    ) -> i32 {
126        assignment.get_lower_bound_at_trail_position(*self, trail_position)
127    }
128
129    fn upper_bound(&self, assignment: &Assignments) -> i32 {
130        assignment.get_upper_bound(*self)
131    }
132
133    fn upper_bound_at_trail_position(
134        &self,
135        assignment: &Assignments,
136        trail_position: usize,
137    ) -> i32 {
138        assignment.get_upper_bound_at_trail_position(*self, trail_position)
139    }
140
141    fn contains(&self, assignment: &Assignments, value: i32) -> bool {
142        assignment.is_value_in_domain(*self, value)
143    }
144
145    fn contains_at_trail_position(
146        &self,
147        assignment: &Assignments,
148        value: i32,
149        trail_position: usize,
150    ) -> bool {
151        assignment.is_value_in_domain_at_trail_position(*self, value, trail_position)
152    }
153
154    fn iterate_domain(&self, assignment: &Assignments) -> impl Iterator<Item = i32> {
155        assignment.get_domain_iterator(*self)
156    }
157
158    fn watch_all(&self, watchers: &mut Watchers<'_>, events: EnumSet<DomainEvent>) {
159        watchers.watch_all(*self, events);
160    }
161
162    fn unwatch_all(&self, watchers: &mut Watchers<'_>) {
163        watchers.unwatch_all(*self);
164    }
165
166    fn watch_all_backtrack(&self, watchers: &mut Watchers<'_>, events: EnumSet<DomainEvent>) {
167        watchers.watch_all_backtrack(*self, events);
168    }
169
170    fn unpack_event(&self, event: OpaqueDomainEvent) -> DomainEvent {
171        event.unwrap()
172    }
173
174    fn get_holes_at_current_checkpoint(
175        &self,
176        assignments: &Assignments,
177    ) -> impl Iterator<Item = i32> {
178        assignments.get_holes_at_current_checkpoint(*self)
179    }
180
181    fn get_holes(&self, assignments: &Assignments) -> impl Iterator<Item = i32> {
182        assignments.get_holes(*self)
183    }
184}
185
186impl TransformableVariable<AffineView<DomainId>> for DomainId {
187    fn scaled(&self, scale: i32) -> AffineView<DomainId> {
188        AffineView::new(*self, scale, 0)
189    }
190
191    fn offset(&self, offset: i32) -> AffineView<DomainId> {
192        AffineView::new(*self, 1, offset)
193    }
194}
195
196impl PredicateConstructor for DomainId {
197    type Value = i32;
198
199    fn equality_predicate(&self, bound: Self::Value) -> Predicate {
200        Predicate::new(*self, PredicateType::Equal, bound)
201    }
202
203    fn lower_bound_predicate(&self, bound: Self::Value) -> Predicate {
204        Predicate::new(*self, PredicateType::LowerBound, bound)
205    }
206
207    fn upper_bound_predicate(&self, bound: Self::Value) -> Predicate {
208        Predicate::new(*self, PredicateType::UpperBound, bound)
209    }
210
211    fn disequality_predicate(&self, bound: Self::Value) -> Predicate {
212        Predicate::new(*self, PredicateType::NotEqual, bound)
213    }
214}
215
216impl StorageKey for DomainId {
217    fn index(&self) -> usize {
218        self.id as usize
219    }
220
221    fn create_from_index(index: usize) -> Self {
222        DomainId { id: index as u32 }
223    }
224}
225
226impl std::fmt::Display for DomainId {
227    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
228        write!(f, "x{}", self.id)
229    }
230}
231
232impl std::fmt::Debug for DomainId {
233    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
234        write!(f, "x{}", self.id)
235    }
236}