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;
18
19#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
20pub struct Literal {
21 integer_variable: AffineView<DomainId>,
22}
23
24impl Literal {
25 pub fn new(domain_id: DomainId) -> Literal {
29 Literal {
30 integer_variable: domain_id.scaled(1),
31 }
32 }
33
34 pub fn get_integer_variable(&self) -> AffineView<DomainId> {
35 self.integer_variable
36 }
37
38 pub fn get_true_predicate(&self) -> Predicate {
39 self.lower_bound_predicate(1)
40 }
41
42 pub fn get_false_predicate(&self) -> Predicate {
43 self.upper_bound_predicate(0)
44 }
45}
46
47impl Not for Literal {
48 type Output = Literal;
49
50 fn not(self) -> Self::Output {
51 Literal {
52 integer_variable: self.integer_variable.scaled(-1).offset(1),
53 }
54 }
55}
56
57macro_rules! forward {
59 (
60 $field:ident,
61 fn $(<$($lt:lifetime),+>)? $name:ident(
62 & $($lt_self:lifetime)? self,
63 $($param_name:ident : $param_type:ty),*
64 ) -> $return_type:ty
65 $(where $($where_clause:tt)*)?
66 ) => {
67 fn $name$(<$($lt),+>)?(
68 & $($lt_self)? self,
69 $($param_name: $param_type),*
70 ) -> $return_type $(where $($where_clause)*)? {
71 self.$field.$name($($param_name),*)
72 }
73 }
74}
75
76impl CheckerVariable<Predicate> for Literal {
77 forward!(integer_variable, fn does_atomic_constrain_self(&self, atomic: &Predicate) -> bool);
78 forward!(integer_variable, fn atomic_less_than(&self, value: i32) -> Predicate);
79 forward!(integer_variable, fn atomic_greater_than(&self, value: i32) -> Predicate);
80 forward!(integer_variable, fn atomic_not_equal(&self, value: i32) -> Predicate);
81 forward!(integer_variable, fn atomic_equal(&self, value: i32) -> Predicate);
82
83 forward!(integer_variable, fn induced_lower_bound(&self, variable_state: &VariableState<Predicate>) -> IntExt);
84 forward!(integer_variable, fn induced_upper_bound(&self, variable_state: &VariableState<Predicate>) -> IntExt);
85 forward!(integer_variable, fn induced_fixed_value(&self, variable_state: &VariableState<Predicate>) -> Option<i32>);
86 forward!(integer_variable, fn induced_domain_contains(&self, variable_state: &VariableState<Predicate>, value: i32) -> bool);
87 forward!(
88 integer_variable,
89 fn <'this, 'state> induced_holes(
90 &'this self,
91 variable_state: &'state VariableState<Predicate>
92 ) -> impl Iterator<Item = i32> + 'state
93 where
94 'this: 'state,
95 );
96 forward!(
97 integer_variable,
98 fn <'this, 'state> iter_induced_domain(
99 &'this self,
100 variable_state: &'state VariableState<Predicate>
101 ) -> Option<impl Iterator<Item = i32> + 'state>
102 where
103 'this: 'state,
104 );
105}
106
107impl IntegerVariable for Literal {
108 type AffineView = AffineView<Self>;
109
110 fn lower_bound(&self, assignment: &Assignments) -> i32 {
115 self.integer_variable.lower_bound(assignment)
116 }
117
118 fn lower_bound_at_trail_position(
119 &self,
120 assignment: &Assignments,
121 trail_position: usize,
122 ) -> i32 {
123 self.integer_variable
124 .lower_bound_at_trail_position(assignment, trail_position)
125 }
126
127 fn upper_bound(&self, assignment: &Assignments) -> i32 {
132 self.integer_variable.upper_bound(assignment)
133 }
134
135 fn upper_bound_at_trail_position(
136 &self,
137 assignment: &Assignments,
138 trail_position: usize,
139 ) -> i32 {
140 self.integer_variable
141 .upper_bound_at_trail_position(assignment, trail_position)
142 }
143
144 fn contains(&self, assignment: &Assignments, value: i32) -> bool {
150 self.integer_variable.contains(assignment, value)
151 }
152
153 fn contains_at_trail_position(
154 &self,
155 assignment: &Assignments,
156 value: i32,
157 trail_position: usize,
158 ) -> bool {
159 self.integer_variable
160 .contains_at_trail_position(assignment, value, trail_position)
161 }
162
163 fn iterate_domain(&self, assignment: &Assignments) -> impl Iterator<Item = i32> {
164 self.integer_variable.iterate_domain(assignment)
165 }
166
167 fn watch_all(&self, watchers: &mut Watchers<'_>, events: EnumSet<DomainEvent>) {
168 self.integer_variable.watch_all(watchers, events)
169 }
170
171 fn unwatch_all(&self, watchers: &mut Watchers<'_>) {
172 self.integer_variable.unwatch_all(watchers)
173 }
174
175 fn unpack_event(&self, event: OpaqueDomainEvent) -> DomainEvent {
176 self.integer_variable.unpack_event(event)
177 }
178
179 fn watch_all_backtrack(&self, watchers: &mut Watchers<'_>, events: EnumSet<DomainEvent>) {
180 self.integer_variable.watch_all_backtrack(watchers, events)
181 }
182
183 fn get_holes_at_current_checkpoint(
184 &self,
185 assignments: &Assignments,
186 ) -> impl Iterator<Item = i32> {
187 self.integer_variable
188 .get_holes_at_current_checkpoint(assignments)
189 }
190
191 fn get_holes(&self, assignments: &Assignments) -> impl Iterator<Item = i32> {
192 self.integer_variable.get_holes(assignments)
193 }
194}
195
196impl PredicateConstructor for Literal {
197 type Value = i32;
198
199 fn lower_bound_predicate(&self, bound: Self::Value) -> Predicate {
200 self.integer_variable.lower_bound_predicate(bound)
201 }
202
203 fn upper_bound_predicate(&self, bound: Self::Value) -> Predicate {
204 self.integer_variable.upper_bound_predicate(bound)
205 }
206
207 fn equality_predicate(&self, bound: Self::Value) -> Predicate {
208 self.integer_variable.equality_predicate(bound)
209 }
210
211 fn disequality_predicate(&self, bound: Self::Value) -> Predicate {
212 self.integer_variable.disequality_predicate(bound)
213 }
214}
215
216impl TransformableVariable<AffineView<Literal>> for Literal {
217 fn scaled(&self, scale: i32) -> AffineView<Literal> {
218 AffineView::new(*self, scale, 0)
219 }
220
221 fn offset(&self, offset: i32) -> AffineView<Literal> {
222 AffineView::new(*self, 1, offset)
223 }
224}