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::pumpkin_assert_simple;
14
15/// A structure which represents the most basic [`IntegerVariable`]; it is simply the id which links
16/// to a domain (hence the name).
17#[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}