1#[cfg(feature = "cadical")]
10pub mod cadical;
11pub mod multisolver;
12
13use std::collections::HashSet;
14use std::fmt::{Display, Formatter};
15use std::vec::IntoIter;
16
17pub trait SolverState {
21 fn is_sat(&self) -> bool;
22 fn is_unsat(&self) -> bool;
23 fn is_unknown(&self) -> bool;
24}
25
26pub trait AddConstraints<C> {
28 fn insert(&mut self, constraints: &C);
29}
30
31impl<T, C> AddConstraints<C> for [T]
32where
33 T: AddConstraints<C>,
34{
35 fn insert(&mut self, constraints: &C) {
36 for t in self {
37 t.insert(constraints);
38 }
39 }
40}
41
42pub trait SatSolver: AddConstraints<Clause> + AddConstraints<Formula> {
46 type Status: SolverState;
47
48 fn new() -> Self;
50 fn solve(&mut self) -> Self::Status;
52 fn val(&mut self, lit: i32) -> bool;
56 fn load_model(&mut self) -> Model;
58
59 fn block_model(&mut self);
61}
62
63#[derive(Debug, Clone, Eq, PartialEq, Hash)]
65pub struct Clause(pub Vec<i32>);
66
67#[derive(Debug, Clone, Eq, PartialEq, Hash)]
69pub struct Formula(pub Vec<Clause>);
70
71#[derive(Debug, Clone, Eq, PartialEq, Hash)]
75pub struct Model(pub Vec<bool>);
76
77impl Display for Clause {
78 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
79 f.write_str("[")?;
80 for i in 0..self.0.len() {
81 write!(f, "{}", self.0[i])?;
82 if i < self.0.len() - 1 {
83 f.write_str(", ")?;
84 }
85 }
86 f.write_str("]")
87 }
88}
89
90impl Display for Formula {
91 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
92 f.write_str("[")?;
93 for i in 0..self.0.len() {
94 write!(f, "{}", self.0[i])?;
95 if i < self.0.len() - 1 {
96 f.write_str(";\n")?;
97 }
98 }
99 f.write_str("]")
100 }
101}
102
103impl Clause {
104 pub fn empty() -> Self {
106 Self::new(vec![])
107 }
108
109 pub fn new(lits: Vec<i32>) -> Self {
111 Clause(lits)
112 }
113
114 pub fn single(lit: i32) -> Self {
116 Self::new(vec![lit])
117 }
118
119 pub fn lits(&self) -> &[i32] {
121 &self.0
122 }
123
124 fn filter_by_model<'a, 'b>(&'a self, model: &'b Model) -> impl Iterator<Item = &'a i32> + 'a
125 where
126 'b: 'a,
127 {
128 self.0.iter().filter(|&i| {
129 let idx = (i.abs() - 1) as usize;
130 if *i < 0 { !model.0[idx] } else { model.0[idx] }
131 })
132 }
133
134 pub fn evaluate(&self, model: &Model) -> bool {
136 self.filter_by_model(model).any(|_| true)
137 }
138
139 pub fn find_true_vars(&self, model: &Model) -> Vec<i32> {
141 self.filter_by_model(model).copied().collect()
142 }
143
144 pub fn filter_true_vars(&self, model: &Model, set: &HashSet<i32>) -> Vec<i32> {
146 self.filter_by_model(model)
147 .filter(|&i| !set.contains(i))
148 .copied()
149 .collect()
150 }
151
152 pub fn filter_vars(&self, model: &Model) -> Clause {
156 Clause(self.find_true_vars(model))
157 }
158
159 pub fn iter(&self) -> impl Iterator<Item = &i32> {
161 self.0.iter()
162 }
163
164 pub fn concat(&self, clause: &Clause) -> Self {
166 let mut c = self.clone();
167 c.concat_mut(clause);
168 c
169 }
170
171 pub fn concat_mut(&mut self, clause: &Clause) -> &mut Self {
173 self.0.extend(&clause.0);
174 self
175 }
176
177 pub fn add(&mut self, lit: i32) -> &mut Self {
179 self.0.push(lit);
180 self
181 }
182}
183
184impl IntoIterator for Clause {
185 type Item = i32;
186 type IntoIter = IntoIter<i32>;
187
188 fn into_iter(self) -> Self::IntoIter {
189 self.0.into_iter()
190 }
191}
192
193impl Formula {
194 pub fn empty() -> Formula {
196 Formula(vec![])
197 }
198
199 pub fn new(clauses: Vec<Clause>) -> Formula {
201 Formula(clauses)
202 }
203
204 pub fn add(&mut self, clause: Clause) {
206 self.0.push(clause);
207 }
208
209 pub fn filter_clauses(&self, model: &Model) -> Formula {
211 Formula(self.0.iter().map(|c| c.filter_vars(model)).collect())
212 }
213
214 fn find_implicant_helper(self) -> HashSet<i32> {
215 let mut vset = HashSet::new();
216 let mut clauses: Vec<_> = self.0;
217
218 loop {
219 let begin_sz = vset.len();
220 let mut kept_clauses = vec![];
221 for clause in clauses.into_iter() {
222 if clause.0.iter().any(|&i| vset.contains(&i)) {
227 continue;
228 }
229 if clause.0.len() == 1 {
230 vset.insert(clause.0[0]);
231 } else {
232 kept_clauses.push(clause);
233 }
234 }
235 clauses = kept_clauses;
236 if clauses.is_empty() {
237 break;
238 }
239 if begin_sz == vset.len() {
240 let c = clauses.pop().unwrap();
242 vset.insert(c.0[0]);
243 }
244 }
245
246 vset
247 }
248
249 pub fn find_implicant(&self, model: &Model) -> HashSet<i32> {
251 self.filter_clauses(model).find_implicant_helper()
252 }
253
254 pub fn iter(&self) -> impl Iterator<Item = &Clause> {
255 self.0.iter()
256 }
257
258 pub fn concat(&self, clause: &Clause) -> Self {
259 let mut f = self.clone();
260 f.concat_mut(clause);
261 f
262 }
263
264 pub fn concat_mut(&mut self, clause: &Clause) -> &mut Self {
265 for c in self.0.iter_mut() {
266 c.concat_mut(clause);
267 }
268 self
269 }
270
271 pub fn distribute(&self, formula: &Formula) -> Self {
272 Formula::new(formula.iter().flat_map(|c| self.concat(c)).collect())
273 }
274
275 pub fn distribute_mut(&mut self, formula: &Formula) -> &mut Self {
276 self.0 = self.distribute(formula).0;
277 self
278 }
279}
280
281impl IntoIterator for Formula {
282 type Item = Clause;
283 type IntoIter = IntoIter<Clause>;
284
285 fn into_iter(self) -> Self::IntoIter {
286 self.0.into_iter()
287 }
288}
289
290impl Model {
291 pub fn get_model<F>(vn: usize, f: F) -> Model
293 where
294 F: FnMut(usize) -> bool,
295 {
296 Model((1..vn + 1).map(f).collect())
297 }
298
299 pub fn negate(&self) -> Clause {
301 Clause(
302 self.0
303 .iter()
304 .enumerate()
305 .map(|(idx, v)| {
306 if *v {
307 -(idx as i32 + 1)
308 } else {
309 idx as i32 + 1
310 }
311 })
312 .collect(),
313 )
314 }
315}