pumpkin_core/engine/variables/
literal.rs

1use std::ops::Not;
2
3use enumset::EnumSet;
4
5use super::DomainId;
6use super::IntegerVariable;
7use super::TransformableVariable;
8use crate::engine::notifications::DomainEvent;
9use crate::engine::notifications::OpaqueDomainEvent;
10use crate::engine::notifications::Watchers;
11use crate::engine::predicates::predicate::Predicate;
12use crate::engine::predicates::predicate_constructor::PredicateConstructor;
13use crate::engine::variables::AffineView;
14use crate::engine::Assignments;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
17pub struct Literal {
18    integer_variable: AffineView<DomainId>,
19}
20
21impl Literal {
22    pub(crate) fn new(domain_id: DomainId) -> Literal {
23        Literal {
24            integer_variable: domain_id.scaled(1),
25        }
26    }
27
28    #[cfg(test)]
29    pub fn test_new(domain_id: DomainId) -> Literal {
30        Literal {
31            integer_variable: domain_id.scaled(1),
32        }
33    }
34
35    pub fn get_integer_variable(&self) -> AffineView<DomainId> {
36        self.integer_variable
37    }
38
39    pub fn get_true_predicate(&self) -> Predicate {
40        self.lower_bound_predicate(1)
41    }
42
43    pub fn get_false_predicate(&self) -> Predicate {
44        self.upper_bound_predicate(0)
45    }
46}
47
48impl Not for Literal {
49    type Output = Literal;
50
51    fn not(self) -> Self::Output {
52        Literal {
53            integer_variable: self.integer_variable.scaled(-1).offset(1),
54        }
55    }
56}
57
58impl IntegerVariable for Literal {
59    type AffineView = AffineView<Self>;
60
61    /// Returns the lower bound represented as a 0-1 value.
62    /// Literals that evaluate to true have a lower bound of 1.
63    /// Literal that evaluate to false have a lower bound of 0.
64    /// Unassigned literals have a lower bound of 0.
65    fn lower_bound(&self, assignment: &Assignments) -> i32 {
66        self.integer_variable.lower_bound(assignment)
67    }
68
69    fn lower_bound_at_trail_position(
70        &self,
71        assignment: &Assignments,
72        trail_position: usize,
73    ) -> i32 {
74        self.integer_variable
75            .lower_bound_at_trail_position(assignment, trail_position)
76    }
77
78    /// Returns the upper bound represented as a 0-1 value.
79    /// Literals that evaluate to true have an upper bound of 1.
80    /// Literal that evaluate to false have a upper bound of 0.
81    /// Unassigned literals have a upper bound of 1.
82    fn upper_bound(&self, assignment: &Assignments) -> i32 {
83        self.integer_variable.upper_bound(assignment)
84    }
85
86    fn upper_bound_at_trail_position(
87        &self,
88        assignment: &Assignments,
89        trail_position: usize,
90    ) -> i32 {
91        self.integer_variable
92            .upper_bound_at_trail_position(assignment, trail_position)
93    }
94
95    /// Returns whether the input value, when interpreted as a bool,
96    /// can be considered for the literal.
97    /// Literals that evaluate to true only contain value 1.
98    /// Literals that evaluate to false only contain value 0.
99    /// Unassigned literals contain both values 0 and 1.
100    fn contains(&self, assignment: &Assignments, value: i32) -> bool {
101        self.integer_variable.contains(assignment, value)
102    }
103
104    fn contains_at_trail_position(
105        &self,
106        assignment: &Assignments,
107        value: i32,
108        trail_position: usize,
109    ) -> bool {
110        self.integer_variable
111            .contains_at_trail_position(assignment, value, trail_position)
112    }
113
114    fn iterate_domain(&self, assignment: &Assignments) -> impl Iterator<Item = i32> {
115        self.integer_variable.iterate_domain(assignment)
116    }
117
118    fn watch_all(&self, watchers: &mut Watchers<'_>, events: EnumSet<DomainEvent>) {
119        self.integer_variable.watch_all(watchers, events)
120    }
121
122    fn unpack_event(&self, event: OpaqueDomainEvent) -> DomainEvent {
123        self.integer_variable.unpack_event(event)
124    }
125
126    fn watch_all_backtrack(&self, watchers: &mut Watchers<'_>, events: EnumSet<DomainEvent>) {
127        self.integer_variable.watch_all_backtrack(watchers, events)
128    }
129
130    fn get_holes_on_current_decision_level(
131        &self,
132        assignments: &Assignments,
133    ) -> impl Iterator<Item = i32> {
134        self.integer_variable
135            .get_holes_on_current_decision_level(assignments)
136    }
137
138    fn get_holes(&self, assignments: &Assignments) -> impl Iterator<Item = i32> {
139        self.integer_variable.get_holes(assignments)
140    }
141}
142
143impl PredicateConstructor for Literal {
144    type Value = i32;
145
146    fn lower_bound_predicate(&self, bound: Self::Value) -> Predicate {
147        self.integer_variable.lower_bound_predicate(bound)
148    }
149
150    fn upper_bound_predicate(&self, bound: Self::Value) -> Predicate {
151        self.integer_variable.upper_bound_predicate(bound)
152    }
153
154    fn equality_predicate(&self, bound: Self::Value) -> Predicate {
155        self.integer_variable.equality_predicate(bound)
156    }
157
158    fn disequality_predicate(&self, bound: Self::Value) -> Predicate {
159        self.integer_variable.disequality_predicate(bound)
160    }
161}
162
163impl TransformableVariable<AffineView<Literal>> for Literal {
164    fn scaled(&self, scale: i32) -> AffineView<Literal> {
165        AffineView::new(*self, scale, 0)
166    }
167
168    fn offset(&self, offset: i32) -> AffineView<Literal> {
169        AffineView::new(*self, 1, offset)
170    }
171}