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