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)]
65pub struct Clause(pub Vec<i32>);
66
67#[derive(Debug, Clone, Eq, PartialEq)]
69pub struct Formula(pub Vec<Clause>);
70
71#[derive(Debug, Clone, Eq, PartialEq)]
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
178impl IntoIterator for Clause {
179 type Item = i32;
180 type IntoIter = IntoIter<i32>;
181
182 fn into_iter(self) -> Self::IntoIter {
183 self.0.into_iter()
184 }
185}
186
187impl Formula {
188 pub fn empty() -> Formula {
190 Formula(vec![])
191 }
192
193 pub fn new(clauses: Vec<Clause>) -> Formula {
195 Formula(clauses)
196 }
197
198 pub fn add(&mut self, clause: Clause) {
200 self.0.push(clause);
201 }
202
203 pub fn filter_clauses(&self, model: &Model) -> Formula {
205 Formula(self.0.iter().map(|c| c.filter_vars(model)).collect())
206 }
207
208 fn find_implicant_helper(self) -> HashSet<i32> {
209 let mut vset = HashSet::new();
210 let mut clauses: Vec<_> = self.0;
211
212 loop {
213 let begin_sz = vset.len();
214 let mut kept_clauses = vec![];
215 for clause in clauses.into_iter() {
216 if clause.0.iter().any(|&i| vset.contains(&i)) {
221 continue;
222 }
223 if clause.0.len() == 1 {
224 vset.insert(clause.0[0]);
225 } else {
226 kept_clauses.push(clause);
227 }
228 }
229 clauses = kept_clauses;
230 if clauses.is_empty() {
231 break;
232 }
233 if begin_sz == vset.len() {
234 let c = clauses.pop().unwrap();
236 vset.insert(c.0[0]);
237 }
238 }
239
240 vset
241 }
242
243 pub fn find_implicant(&self, model: &Model) -> HashSet<i32> {
245 self.filter_clauses(model).find_implicant_helper()
246 }
247
248 pub fn iter(&self) -> impl Iterator<Item = &Clause> {
249 self.0.iter()
250 }
251
252 pub fn concat(&self, clause: &Clause) -> Self {
253 let mut f = self.clone();
254 f.concat_mut(clause);
255 f
256 }
257
258 pub fn concat_mut(&mut self, clause: &Clause) -> &mut Self {
259 for c in self.0.iter_mut() {
260 c.concat_mut(clause);
261 }
262 self
263 }
264
265 pub fn distribute(&self, formula: &Formula) -> Self {
266 Formula::new(formula.iter().flat_map(|c| self.concat(c)).collect())
267 }
268
269 pub fn distribute_mut(&mut self, formula: &Formula) -> &mut Self {
270 self.0 = self.distribute(formula).0;
271 self
272 }
273}
274
275impl IntoIterator for Formula {
276 type Item = Clause;
277 type IntoIter = IntoIter<Clause>;
278
279 fn into_iter(self) -> Self::IntoIter {
280 self.0.into_iter()
281 }
282}
283
284impl Model {
285 pub fn get_model<F>(vn: usize, f: F) -> Model
287 where
288 F: FnMut(usize) -> bool,
289 {
290 Model((1..vn + 1).map(f).collect())
291 }
292
293 pub fn negate(&self) -> Clause {
295 Clause(
296 self.0
297 .iter()
298 .enumerate()
299 .map(|(idx, v)| {
300 if *v {
301 -(idx as i32 + 1)
302 } else {
303 idx as i32 + 1
304 }
305 })
306 .collect(),
307 )
308 }
309}