1use crate::{Lit, LitSet, LitVec};
2use ahash::AHasher;
3use std::hash::{Hash, Hasher};
4use std::slice;
5use std::{
6 cmp::Ordering,
7 fmt::{self, Display},
8 ops::{Deref, DerefMut},
9};
10
11#[derive(Debug, Default, Clone)]
12pub struct LitOrdVec {
13 cube: LitVec,
14 sign: u128,
15 hash: u64,
16}
17
18impl Deref for LitOrdVec {
19 type Target = LitVec;
20
21 #[inline]
22 fn deref(&self) -> &Self::Target {
23 &self.cube
24 }
25}
26
27impl DerefMut for LitOrdVec {
28 #[inline]
29 fn deref_mut(&mut self) -> &mut Self::Target {
30 &mut self.cube
31 }
32}
33
34impl PartialEq for LitOrdVec {
35 #[inline]
36 fn eq(&self, other: &Self) -> bool {
37 if self.hash != other.hash || self.sign != other.sign || self.len() != other.len() {
38 return false;
39 }
40 for i in 0..self.cube.len() {
41 if self[i] != other[i] {
42 return false;
43 }
44 }
45 true
46 }
47}
48
49impl Eq for LitOrdVec {}
50
51impl PartialOrd for LitOrdVec {
52 #[inline]
53 fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
54 Some(self.cmp(other))
55 }
56}
57
58impl Ord for LitOrdVec {
59 #[inline]
60 fn cmp(&self, other: &Self) -> Ordering {
61 self.cube.cmp(&other.cube)
62 }
63}
64
65impl LitOrdVec {
66 #[inline]
67 pub fn new(mut cube: LitVec) -> Self {
68 cube.sort();
69 let mut sign = 0;
70 for l in cube.iter() {
71 sign |= 1 << (Into::<u32>::into(*l) % u128::BITS);
72 }
73 let mut hasher = AHasher::default();
74 cube.hash(&mut hasher);
75 Self {
76 cube,
77 sign,
78 hash: hasher.finish(),
79 }
80 }
81
82 #[inline]
83 pub fn cube(&self) -> &LitVec {
84 &self.cube
85 }
86
87 #[inline]
88 fn var_sign(&self) -> u128 {
89 ((self.sign >> 1) | self.sign) & 113427455640312821154458202477256070485_u128
90 }
91
92 #[inline]
93 pub fn subsume(&self, other: &LitOrdVec) -> bool {
94 if self.cube.len() > other.cube.len() {
95 return false;
96 }
97 if self.sign & other.sign != self.sign {
98 return false;
99 }
100 self.cube.ordered_subsume(&other.cube)
101 }
102
103 #[inline]
104 pub fn subsume_execpt_one(&self, other: &LitOrdVec) -> (bool, Option<Lit>) {
105 if self.cube.len() > other.cube.len() {
106 return (false, None);
107 }
108 let ss = self.var_sign();
109 if ss & other.var_sign() != ss {
110 return (false, None);
111 }
112 self.cube.ordered_subsume_execpt_one(&other.cube)
113 }
114
115 #[inline]
116 pub fn subsume_set(&self, other: &LitOrdVec, other_lits: &LitSet) -> bool {
117 if self.cube.len() > other.cube.len() {
118 return false;
119 }
120 if self.sign & other.sign != self.sign {
121 return false;
122 }
123 for l in self.iter() {
124 if !other_lits.has(*l) {
125 return false;
126 }
127 }
128 true
129 }
130}
131
132impl Hash for LitOrdVec {
133 #[inline]
134 fn hash<H: Hasher>(&self, state: &mut H) {
135 self.hash.hash(state);
136 }
137}
138
139impl Display for LitOrdVec {
140 #[inline]
141 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
142 Display::fmt(&self.cube, f)
143 }
144}
145
146pub fn lemmas_subsume_simplify(mut lemmas: Vec<LitOrdVec>) -> Vec<LitOrdVec> {
147 lemmas.sort_by_key(|l| l.len());
148 let mut i = 0;
149 while i < lemmas.len() {
150 if lemmas[i].is_empty() {
151 i += 1;
152 continue;
153 }
154 let mut update = false;
155 for j in i + 1..lemmas.len() {
156 if lemmas[j].is_empty() {
157 continue;
158 }
159 let (res, diff) = lemmas[i].subsume_execpt_one(&lemmas[j]);
160 if res {
161 lemmas[j] = Default::default();
162 continue;
163 } else if let Some(diff) = diff {
164 if lemmas[i].len() == lemmas[j].len() {
165 update = true;
166 let mut cube = lemmas[i].cube().clone();
167 cube.retain(|l| *l != diff);
168 lemmas[i] = LitOrdVec::new(cube);
169 lemmas[j] = Default::default();
170 } else {
171 let mut cube = lemmas[j].cube().clone();
172 cube.retain(|l| *l != !diff);
173 lemmas[j] = LitOrdVec::new(cube);
174 }
175 }
176 }
177 if !update {
178 i += 1;
179 }
180 }
181 lemmas.retain(|l| !l.is_empty());
182 lemmas
183}
184
185impl IntoIterator for LitOrdVec {
186 type Item = Lit;
187 type IntoIter = std::vec::IntoIter<Lit>;
188
189 #[inline]
190 fn into_iter(self) -> Self::IntoIter {
191 self.cube.clone().into_iter()
192 }
193}
194
195impl<'a> IntoIterator for &'a LitOrdVec {
196 type Item = &'a Lit;
197 type IntoIter = slice::Iter<'a, Lit>;
198
199 #[inline]
200 fn into_iter(self) -> Self::IntoIter {
201 self.cube.iter()
202 }
203}