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