1use crate::{Lit, Var};
2use giputils::hash::GHashSet;
3use std::{
4 cmp::Ordering,
5 fmt::{self, Debug, Display},
6 ops::{Deref, DerefMut, Not},
7 slice,
8};
9
10#[derive(Clone, Hash, PartialEq, Eq)]
11pub struct LitVec {
12 lits: Vec<Lit>,
13}
14
15impl LitVec {
16 #[inline]
17 pub fn new() -> Self {
18 LitVec { lits: Vec::new() }
19 }
20
21 #[inline]
22 pub fn new_with(c: usize) -> Self {
23 LitVec {
24 lits: Vec::with_capacity(c),
25 }
26 }
27
28 #[inline]
29 pub fn last(&self) -> Lit {
30 #[cfg(debug_assertions)]
31 {
32 self.lits.last().copied().unwrap()
33 }
34 #[cfg(not(debug_assertions))]
35 unsafe {
36 self.lits.last().copied().unwrap_unchecked()
37 }
38 }
39
40 #[inline]
41 pub fn cls_simp(&mut self) {
42 self.sort();
43 self.dedup();
44 for i in 1..self.len() {
45 if self[i] == !self[i - 1] {
46 self.clear();
47 return;
48 }
49 }
50 }
51
52 #[inline]
53 pub fn subsume(&self, o: &[Lit]) -> bool {
54 if self.len() > o.len() {
55 return false;
56 }
57 'n: for x in self.iter() {
58 for y in o.iter() {
59 if x == y {
60 continue 'n;
61 }
62 }
63 return false;
64 }
65 true
66 }
67
68 pub fn subsume_execpt_one(&self, o: &[Lit]) -> (bool, Option<Lit>) {
69 if self.len() > o.len() {
70 return (false, None);
71 }
72 let mut diff = None;
73 'n: for x in self.iter() {
74 for y in o.iter() {
75 if x == y {
76 continue 'n;
77 }
78 if diff.is_none() && x.var() == y.var() {
79 diff = Some(*x);
80 continue 'n;
81 }
82 }
83 return (false, None);
84 }
85
86 (diff.is_none(), diff)
87 }
88
89 #[inline]
90 pub fn ordered_subsume(&self, cube: &LitVec) -> bool {
91 debug_assert!(self.is_sorted());
92 debug_assert!(cube.is_sorted());
93 if self.len() > cube.len() {
94 return false;
95 }
96 let mut j = 0;
97 for i in 0..self.len() {
98 while j < cube.len() && self[i].0 > cube[j].0 {
99 j += 1;
100 }
101 if j == cube.len() || self[i] != cube[j] {
102 return false;
103 }
104 }
105 true
106 }
107
108 #[inline]
109 pub fn ordered_subsume_execpt_one(&self, cube: &LitVec) -> (bool, Option<Lit>) {
110 debug_assert!(self.is_sorted());
111 debug_assert!(cube.is_sorted());
112 let mut diff = None;
113 if self.len() > cube.len() {
114 return (false, None);
115 }
116 let mut j = 0;
117 for i in 0..self.len() {
118 while j < cube.len() && self[i].var() > cube[j].var() {
119 j += 1;
120 }
121 if j == cube.len() {
122 return (false, None);
123 }
124 if self[i] != cube[j] {
125 if diff.is_none() && self[i].var() == cube[j].var() {
126 diff = Some(self[i]);
127 } else {
128 return (false, None);
129 }
130 }
131 }
132 (diff.is_none(), diff)
133 }
134
135 #[inline]
136 pub fn intersection(&self, cube: &LitVec) -> LitVec {
137 let x_lit_set = self.iter().collect::<GHashSet<&Lit>>();
138 let y_lit_set = cube.iter().collect::<GHashSet<&Lit>>();
139 Self {
140 lits: x_lit_set
141 .intersection(&y_lit_set)
142 .copied()
143 .copied()
144 .collect(),
145 }
146 }
147
148 #[inline]
149 pub fn ordered_intersection(&self, cube: &LitVec) -> LitVec {
150 debug_assert!(self.is_sorted());
151 debug_assert!(cube.is_sorted());
152 let mut res = LitVec::new();
153 let mut i = 0;
154 for l in self.iter() {
155 while i < cube.len() && cube[i] < *l {
156 i += 1;
157 }
158 if i == cube.len() {
159 break;
160 }
161 if *l == cube[i] {
162 res.push(*l);
163 }
164 }
165 res
166 }
167
168 #[inline]
169 pub fn resolvent(&self, other: &LitVec, v: Var) -> Option<LitVec> {
170 let (x, y) = if self.len() < other.len() {
171 (self, other)
172 } else {
173 (other, self)
174 };
175 let mut new = LitVec::new();
176 'n: for x in x.iter() {
177 if x.var() != v {
178 for y in y.iter() {
179 if x.var() == y.var() {
180 if *x == !*y {
181 return None;
182 } else {
183 continue 'n;
184 }
185 }
186 }
187 new.push(*x);
188 }
189 }
190 new.extend(y.iter().filter(|l| l.var() != v).copied());
191 Some(new)
192 }
193
194 #[inline]
195 pub fn ordered_resolvent(&self, other: &LitVec, v: Var) -> Option<LitVec> {
196 debug_assert!(self.is_sorted());
197 debug_assert!(other.is_sorted());
198 let (x, y) = if self.len() < other.len() {
199 (self, other)
200 } else {
201 (other, self)
202 };
203 let mut new = LitVec::new_with(self.len() + other.len());
204 let (mut i, mut j) = (0, 0);
205 while i < x.len() {
206 if x[i].var() == v {
207 i += 1;
208 continue;
209 }
210 while j < y.len() && y[j].var() < x[i].var() {
211 j += 1;
212 }
213 if j < y.len() && x[i].var() == y[j].var() {
214 if x[i] == !y[j] {
215 return None;
216 }
217 } else {
218 new.push(x[i]);
219 }
220 i += 1;
221 }
222 new.extend(y.iter().filter(|l| l.var() != v).copied());
223 Some(new)
224 }
225
226 #[inline]
227 pub fn map(&self, f: impl Fn(Lit) -> Lit) -> LitVec {
228 let mut new = LitVec::new_with(self.len());
229 for l in self.iter() {
230 new.push(f(*l));
231 }
232 new
233 }
234}
235
236impl Default for LitVec {
237 fn default() -> Self {
238 Self::new()
239 }
240}
241
242impl Deref for LitVec {
243 type Target = Vec<Lit>;
244
245 #[inline]
246 fn deref(&self) -> &Self::Target {
247 &self.lits
248 }
249}
250
251impl DerefMut for LitVec {
252 #[inline]
253 fn deref_mut(&mut self) -> &mut Self::Target {
254 &mut self.lits
255 }
256}
257
258impl PartialOrd for LitVec {
259 #[inline]
260 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
261 Some(self.cmp(other))
262 }
263}
264
265impl Ord for LitVec {
266 #[inline]
267 fn cmp(&self, other: &Self) -> Ordering {
268 debug_assert!(self.is_sorted());
269 debug_assert!(other.is_sorted());
270 let min_index = self.len().min(other.len());
271 for i in 0..min_index {
272 match self[i].0.cmp(&other[i].0) {
273 Ordering::Less => return Ordering::Less,
274 Ordering::Equal => {}
275 Ordering::Greater => return Ordering::Greater,
276 }
277 }
278 self.len().cmp(&other.len())
279 }
280}
281
282impl Not for LitVec {
283 type Output = LitVec;
284
285 #[inline]
286 fn not(self) -> Self::Output {
287 let lits = self.lits.iter().map(|lit| !*lit).collect();
288 LitVec { lits }
289 }
290}
291
292impl Not for &LitVec {
293 type Output = LitVec;
294
295 #[inline]
296 fn not(self) -> Self::Output {
297 let lits = self.lits.iter().map(|lit| !*lit).collect();
298 LitVec { lits }
299 }
300}
301
302impl<const N: usize> From<[Lit; N]> for LitVec {
303 #[inline]
304 fn from(s: [Lit; N]) -> Self {
305 Self { lits: Vec::from(s) }
306 }
307}
308
309impl From<Lit> for LitVec {
310 #[inline]
311 fn from(l: Lit) -> Self {
312 Self { lits: vec![l] }
313 }
314}
315
316impl From<&[Lit]> for LitVec {
317 #[inline]
318 fn from(s: &[Lit]) -> Self {
319 Self { lits: Vec::from(s) }
320 }
321}
322
323impl From<LitVec> for Vec<Lit> {
324 #[inline]
325 fn from(val: LitVec) -> Self {
326 val.lits
327 }
328}
329
330impl FromIterator<Lit> for LitVec {
331 #[inline]
332 fn from_iter<T: IntoIterator<Item = Lit>>(iter: T) -> Self {
333 Self {
334 lits: Vec::from_iter(iter),
335 }
336 }
337}
338
339impl IntoIterator for LitVec {
340 type Item = Lit;
341 type IntoIter = std::vec::IntoIter<Lit>;
342
343 #[inline]
344 fn into_iter(self) -> Self::IntoIter {
345 self.lits.into_iter()
346 }
347}
348
349impl<'a> IntoIterator for &'a LitVec {
350 type Item = &'a Lit;
351 type IntoIter = slice::Iter<'a, Lit>;
352
353 #[inline]
354 fn into_iter(self) -> Self::IntoIter {
355 self.lits.iter()
356 }
357}
358
359impl AsRef<[Lit]> for LitVec {
360 #[inline]
361 fn as_ref(&self) -> &[Lit] {
362 self.as_slice()
363 }
364}
365
366impl Display for LitVec {
367 #[inline]
368 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
369 self.lits.fmt(f)
370 }
371}
372
373impl Debug for LitVec {
374 #[inline]
375 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
376 self.lits.fmt(f)
377 }
378}