1use std::{hash::Hash, cmp::Ordering, sync::Arc, fmt::Debug};
21use dashmap::{DashMap, mapref::entry::Entry};
22
23use crate::{Dominance, DominanceChecker, DominanceCmpResult, DominanceCheckResult};
24
25#[derive(Debug)]
29struct DominanceEntry<T> {
30 state: Arc<T>,
31 value: isize,
32}
33
34type DominanceMap<K, S> = DashMap<K, Vec<DominanceEntry<S>>, fxhash::FxBuildHasher>;
35
36#[derive(Debug)]
37pub struct SimpleDominanceChecker<D>
38where
39 D: Dominance,
40 D::Key: Eq + PartialEq + Hash,
41{
42 dominance: D,
43 data: Vec<DominanceMap<D::Key, D::State>>,
44}
45
46impl<D> SimpleDominanceChecker<D>
47where
48 D: Dominance,
49 D::Key: Eq + PartialEq + Hash,
50{
51 pub fn new(dominance: D, nb_variables: usize) -> Self {
52 let mut data = vec![];
53 for _ in 0..=nb_variables {
54 data.push(Default::default());
55 }
56 Self { dominance, data }
57 }
58}
59
60impl<D> DominanceChecker for SimpleDominanceChecker<D>
61where
62 D: Dominance,
63 D::Key: Eq + PartialEq + Hash,
64{
65 type State = D::State;
66
67 fn clear_layer(&self, depth: usize) {
68 self.data[depth].clear();
69 }
70
71 fn is_dominated_or_insert(&self, state: Arc<Self::State>, depth: usize, value: isize) -> DominanceCheckResult {
72 if let Some(key) = self.dominance.get_key(state.clone()) {
73 match self.data[depth].entry(key) {
74 Entry::Occupied(mut e) => {
75 let mut dominated = false;
76 let mut threshold = Some(isize::MAX);
77 e.get_mut().retain(|other| {
78 match self.dominance.partial_cmp(state.as_ref(), value, other.state.as_ref(), other.value) {
79 Some(cmp) => match cmp {
80 DominanceCmpResult { ordering: Ordering::Less, only_val_diff} => {
81 dominated = true;
82 if self.dominance.use_value() {
83 if only_val_diff {
84 threshold = threshold.min(Some(other.value.saturating_sub(1)));
85 } else {
86 threshold = threshold.min(Some(other.value));
87 }
88 }
89 true
90 },
91 DominanceCmpResult { ordering: Ordering::Equal, only_val_diff: _ } => false,
92 DominanceCmpResult { ordering: Ordering::Greater, only_val_diff: _ } => false,
93 },
94 None => true,
95 }
96 });
97 if !dominated {
98 threshold = None;
99 e.get_mut().push(DominanceEntry { state, value });
100 }
101 DominanceCheckResult { dominated, threshold }
102 },
103 Entry::Vacant(e) => {
104 e.insert(vec![DominanceEntry { state, value }]);
105 DominanceCheckResult { dominated: false, threshold: None }
106 },
107 }
108 } else {
109 DominanceCheckResult { dominated: false, threshold: None }
110 }
111 }
112
113 fn cmp(&self, a: &Self::State, val_a: isize, b: &Self::State, val_b: isize) -> Ordering {
114 self.dominance.cmp(a, val_a, b, val_b)
115 }
116}
117
118#[cfg(test)]
119mod tests {
120 use std::sync::Arc;
121
122 use crate::{Dominance, SimpleDominanceChecker, DominanceChecker, DominanceCheckResult};
123
124 #[test]
125 fn not_dominated_when_keys_are_different() {
126 let dominance = SimpleDominanceChecker::new(DummyDominanceWithValue, 0);
127
128 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![3, 0]), 0, 3));
129 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![2, 0]), 0, 2));
130 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![1, 0]), 0, 1));
131 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 0]), 0, 0));
132 }
133
134 #[test]
135 fn dominated_when_keys_are_equal() {
136 let dominance = SimpleDominanceChecker::new(DummyDominance, 0);
137
138 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 3]), 0, 0));
139
140 let res = dominance.is_dominated_or_insert(Arc::new(vec![0, 2]), 0, 2);
141 assert!(res.dominated);
142
143 let res = dominance.is_dominated_or_insert(Arc::new(vec![0, 1]), 0, 1);
144 assert!(res.dominated);
145
146 let res = dominance.is_dominated_or_insert(Arc::new(vec![0, 0]), 0, 0);
147 assert!(res.dominated);
148
149 let dominance = SimpleDominanceChecker::new(DummyDominanceWithValue, 0);
150
151 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 0]), 0, 3));
152
153 let res = dominance.is_dominated_or_insert(Arc::new(vec![0, 0]), 0, 2);
154 assert!(res.dominated);
155
156 let res = dominance.is_dominated_or_insert(Arc::new(vec![0, 0]), 0, 1);
157 assert!(res.dominated);
158
159 let res = dominance.is_dominated_or_insert(Arc::new(vec![0, 0]), 0, 0);
160 assert!(res.dominated);
161
162 let res = dominance.is_dominated_or_insert(Arc::new(vec![0, -1]), 0, 3);
163 assert!(res.dominated);
164 }
165
166 #[test]
167 fn not_dominated_when_keys_are_equal() {
168 let dominance = SimpleDominanceChecker::new(DummyDominance, 0);
169
170 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 0, 3]), 0, 3));
171 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 0, 3]), 0, 1));
172 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 1, 1]), 0, 5));
173 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 0, 4]), 0, 3));
174
175 let dominance = SimpleDominanceChecker::new(DummyDominanceWithValue, 0);
176
177 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 0]), 0, 3));
178 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 3]), 0, 0));
179 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 1]), 0, 1));
180 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 0]), 0, 5));
181 }
182
183 #[test]
184 fn pruning_threshold_when_value_is_used() {
185 let dominance = SimpleDominanceChecker::new(DummyDominanceWithValue, 0);
186
187 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 0]), 0, 3));
188 assert_eq!(DominanceCheckResult{ dominated: true, threshold: Some(2) }, dominance.is_dominated_or_insert(Arc::new(vec![0, 0]), 0, 2));
189 assert_eq!(DominanceCheckResult{ dominated: true, threshold: Some(2) }, dominance.is_dominated_or_insert(Arc::new(vec![0, 0]), 0, 1));
190 assert_eq!(DominanceCheckResult{ dominated: true, threshold: Some(3) }, dominance.is_dominated_or_insert(Arc::new(vec![0, -1]), 0, 0));
191 }
192
193 #[test]
194 fn entry_is_added_only_when_dominant() {
195 let dominance = SimpleDominanceChecker::new(DummyDominanceWithValue, 0);
196
197 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 0]), 0, 3));
198 assert!(dominance.data[0].get(&0).is_some());
199 assert_eq!(1, dominance.data[0].get(&0).unwrap().len());
200
201 assert_eq!(DominanceCheckResult{ dominated: true, threshold: Some(2) }, dominance.is_dominated_or_insert(Arc::new(vec![0, 0]), 0, 1));
202 assert_eq!(1, dominance.data[0].get(&0).unwrap().len());
203
204 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 1]), 0, 1));
205 assert_eq!(2, dominance.data[0].get(&0).unwrap().len());
206
207 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, -1]), 0, 5));
208 assert_eq!(3, dominance.data[0].get(&0).unwrap().len());
209 }
210
211 #[test]
212 fn entry_is_removed_when_dominated() {
213 let dominance = SimpleDominanceChecker::new(DummyDominanceWithValue, 0);
214
215 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 0]), 0, 3));
216 assert!(dominance.data[0].get(&0).is_some());
217 assert_eq!(1, dominance.data[0].get(&0).unwrap().len());
218
219 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 1]), 0, 5));
220 assert_eq!(1, dominance.data[0].get(&0).unwrap().len());
221
222 assert_eq!(DominanceCheckResult{ dominated: false, threshold: None }, dominance.is_dominated_or_insert(Arc::new(vec![0, 2]), 0, 7));
223 assert_eq!(1, dominance.data[0].get(&0).unwrap().len());
224 }
225
226 struct DummyDominance;
227 impl Dominance for DummyDominance {
228 type State = Vec<isize>;
229 type Key = isize;
230
231 fn get_key(&self, state: Arc<Self::State>) -> Option<Self::Key> {
232 Some(state[0])
233 }
234
235 fn nb_dimensions(&self, state: &Self::State) -> usize {
236 state.len()
237 }
238
239 fn get_coordinate(&self, state: &Self::State, i: usize) -> isize {
240 state[i]
241 }
242 }
243
244 struct DummyDominanceWithValue;
245 impl Dominance for DummyDominanceWithValue {
246 type State = Vec<isize>;
247 type Key = isize;
248
249 fn get_key(&self, state: Arc<Self::State>) -> Option<Self::Key> {
250 Some(state[0])
251 }
252
253 fn nb_dimensions(&self, state: &Self::State) -> usize {
254 state.len()
255 }
256
257 fn get_coordinate(&self, state: &Self::State, i: usize) -> isize {
258 state[i]
259 }
260
261 fn use_value(&self) -> bool {
262 true
263 }
264 }
265}