pumpkin_core/engine/variables/
literal.rs1use std::ops::Not;
2
3use enumset::EnumSet;
4use pumpkin_checking::CheckerVariable;
5use pumpkin_checking::IntExt;
6use pumpkin_checking::VariableState;
7
8use super::DomainId;
9use super::IntegerVariable;
10use super::TransformableVariable;
11use crate::engine::Assignments;
12use crate::engine::notifications::DomainEvent;
13use crate::engine::notifications::OpaqueDomainEvent;
14use crate::engine::notifications::Watchers;
15use crate::engine::predicates::predicate::Predicate;
16use crate::engine::predicates::predicate_constructor::PredicateConstructor;
17use crate::engine::variables::AffineView;
18use crate::propagation::EventDispatcher;
19use crate::propagation::EventTarget;
20use crate::propagation::LocalId;
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
23pub struct Literal {
24 integer_variable: AffineView<DomainId>,
25}
26
27impl Literal {
28 pub fn new(domain_id: DomainId) -> Literal {
32 Literal {
33 integer_variable: domain_id.scaled(1),
34 }
35 }
36
37 pub fn get_integer_variable(&self) -> AffineView<DomainId> {
38 self.integer_variable
39 }
40
41 pub fn get_true_predicate(&self) -> Predicate {
42 self.lower_bound_predicate(1)
43 }
44
45 pub fn get_false_predicate(&self) -> Predicate {
46 self.upper_bound_predicate(0)
47 }
48}
49
50impl Not for Literal {
51 type Output = Literal;
52
53 fn not(self) -> Self::Output {
54 Literal {
55 integer_variable: self.integer_variable.scaled(-1).offset(1),
56 }
57 }
58}
59
60macro_rules! forward {
62 (
63 $field:ident,
64 fn $(<$($lt:lifetime),+>)? $name:ident(
65 & $($lt_self:lifetime)? self,
66 $($param_name:ident : $param_type:ty),*
67 ) -> $return_type:ty
68 $(where $($where_clause:tt)*)?
69 ) => {
70 fn $name$(<$($lt),+>)?(
71 & $($lt_self)? self,
72 $($param_name: $param_type),*
73 ) -> $return_type $(where $($where_clause)*)? {
74 self.$field.$name($($param_name),*)
75 }
76 }
77}
78
79impl EventTarget for Literal {
80 fn register(
81 &self,
82 registration: &mut impl EventDispatcher,
83 events: EnumSet<DomainEvent>,
84 local_id: LocalId,
85 ) {
86 self.integer_variable
87 .register(registration, events, local_id);
88 }
89}
90
91impl CheckerVariable<Predicate> for Literal {
92 forward!(integer_variable, fn does_atomic_constrain_self(&self, atomic: &Predicate) -> bool);
93 forward!(integer_variable, fn atomic_less_than(&self, value: i32) -> Predicate);
94 forward!(integer_variable, fn atomic_greater_than(&self, value: i32) -> Predicate);
95 forward!(integer_variable, fn atomic_not_equal(&self, value: i32) -> Predicate);
96 forward!(integer_variable, fn atomic_equal(&self, value: i32) -> Predicate);
97
98 forward!(integer_variable, fn induced_lower_bound(&self, variable_state: &VariableState<Predicate>) -> IntExt);
99 forward!(integer_variable, fn induced_upper_bound(&self, variable_state: &VariableState<Predicate>) -> IntExt);
100 forward!(integer_variable, fn induced_fixed_value(&self, variable_state: &VariableState<Predicate>) -> Option<i32>);
101 forward!(integer_variable, fn induced_domain_contains(&self, variable_state: &VariableState<Predicate>, value: i32) -> bool);
102 forward!(
103 integer_variable,
104 fn <'this, 'state> induced_holes(
105 &'this self,
106 variable_state: &'state VariableState<Predicate>
107 ) -> impl Iterator<Item = i32> + 'state
108 where
109 'this: 'state,
110 );
111 forward!(
112 integer_variable,
113 fn <'this, 'state> iter_induced_domain(
114 &'this self,
115 variable_state: &'state VariableState<Predicate>
116 ) -> Option<impl Iterator<Item = i32> + 'state>
117 where
118 'this: 'state,
119 );
120}
121
122impl IntegerVariable for Literal {
123 type AffineView = AffineView<Self>;
124
125 fn lower_bound(&self, assignment: &Assignments) -> i32 {
130 self.integer_variable.lower_bound(assignment)
131 }
132
133 fn lower_bound_at_trail_position(
134 &self,
135 assignment: &Assignments,
136 trail_position: usize,
137 ) -> i32 {
138 self.integer_variable
139 .lower_bound_at_trail_position(assignment, trail_position)
140 }
141
142 fn upper_bound(&self, assignment: &Assignments) -> i32 {
147 self.integer_variable.upper_bound(assignment)
148 }
149
150 fn upper_bound_at_trail_position(
151 &self,
152 assignment: &Assignments,
153 trail_position: usize,
154 ) -> i32 {
155 self.integer_variable
156 .upper_bound_at_trail_position(assignment, trail_position)
157 }
158
159 fn contains(&self, assignment: &Assignments, value: i32) -> bool {
165 self.integer_variable.contains(assignment, value)
166 }
167
168 fn contains_at_trail_position(
169 &self,
170 assignment: &Assignments,
171 value: i32,
172 trail_position: usize,
173 ) -> bool {
174 self.integer_variable
175 .contains_at_trail_position(assignment, value, trail_position)
176 }
177
178 fn iterate_domain(&self, assignment: &Assignments) -> impl Iterator<Item = i32> {
179 self.integer_variable.iterate_domain(assignment)
180 }
181
182 fn unwatch_all(&self, watchers: &mut Watchers<'_>) {
183 self.integer_variable.unwatch_all(watchers)
184 }
185
186 fn unpack_event(&self, event: OpaqueDomainEvent) -> DomainEvent {
187 self.integer_variable.unpack_event(event)
188 }
189
190 fn watch_all_backtrack(&self, watchers: &mut Watchers<'_>, events: EnumSet<DomainEvent>) {
191 self.integer_variable.watch_all_backtrack(watchers, events)
192 }
193
194 fn get_holes_at_current_checkpoint(
195 &self,
196 assignments: &Assignments,
197 ) -> impl Iterator<Item = i32> {
198 self.integer_variable
199 .get_holes_at_current_checkpoint(assignments)
200 }
201
202 fn get_holes(&self, assignments: &Assignments) -> impl Iterator<Item = i32> {
203 self.integer_variable.get_holes(assignments)
204 }
205}
206
207impl PredicateConstructor for Literal {
208 type Value = i32;
209
210 fn lower_bound_predicate(&self, bound: Self::Value) -> Predicate {
211 self.integer_variable.lower_bound_predicate(bound)
212 }
213
214 fn upper_bound_predicate(&self, bound: Self::Value) -> Predicate {
215 self.integer_variable.upper_bound_predicate(bound)
216 }
217
218 fn equality_predicate(&self, bound: Self::Value) -> Predicate {
219 self.integer_variable.equality_predicate(bound)
220 }
221
222 fn disequality_predicate(&self, bound: Self::Value) -> Predicate {
223 self.integer_variable.disequality_predicate(bound)
224 }
225}
226
227impl TransformableVariable<AffineView<Literal>> for Literal {
228 fn scaled(&self, scale: i32) -> AffineView<Literal> {
229 AffineView::new(*self, scale, 0)
230 }
231
232 fn offset(&self, offset: i32) -> AffineView<Literal> {
233 AffineView::new(*self, 1, offset)
234 }
235}