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::pumpkin_assert_simple;
16
17#[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}