use crate::{
clause::{lbool, Lit, Var},
theory::{self, Theory},
};
pub trait SolverInterface {
fn num_vars(&self) -> u32;
fn num_clauses(&self) -> u64;
fn num_conflicts(&self) -> u64;
fn num_propagations(&self) -> u64;
fn num_decisions(&self) -> u64;
fn num_restarts(&self) -> u64;
fn is_ok(&self) -> bool;
fn reset(&mut self);
fn print_stats(&self);
fn new_var(&mut self, upol: lbool, dvar: bool) -> Var;
fn new_var_default(&mut self) -> Var;
fn var_of_int(&mut self, i: u32) -> Var;
fn add_clause_reuse(&mut self, clause: &mut Vec<Lit>) -> bool;
#[inline(always)]
fn simplify(&mut self) -> bool {
self.simplify_th(&mut theory::EmptyTheory::new())
}
fn simplify_th<Th: Theory>(&mut self, th: &mut Th) -> bool;
fn solve_limited(&mut self, assumps: &[Lit]) -> lbool {
self.solve_limited_th(&mut theory::EmptyTheory::new(), assumps)
}
fn solve_limited_th<Th: Theory>(&mut self, th: &mut Th, assumps: &[Lit]) -> lbool {
let res = self.solve_limited_preserving_trail_th(th, assumps);
self.pop_model(th);
res
}
fn solve_limited_preserving_trail_th<Th: Theory>(
&mut self,
th: &mut Th,
assumps: &[Lit],
) -> lbool;
fn pop_model<Th: Theory>(&mut self, th: &mut Th);
fn raw_value_lit(&self, l: Lit) -> lbool;
fn solve_limited_th_full<'a, Th: Theory>(
&'a mut self,
th: &'a mut Th,
assumps: &[Lit],
) -> SolveResult<'a, Self, Th> {
let res = self.solve_limited_preserving_trail_th(th, assumps);
if res == lbool::FALSE {
self.pop_model(th);
return SolveResult::Unsat(self.unsat_core());
}
let model = SolverModel {
solver: self,
theory: th,
};
if res == lbool::TRUE {
SolveResult::Sat(model)
} else {
SolveResult::Unknown(model)
}
}
fn proved_at_lvl_0(&self) -> &[Lit];
fn get_model(&self) -> &[lbool];
fn value_var(&self, v: Var) -> lbool;
fn value_lit(&self, lit: Lit) -> lbool;
fn value_lvl_0(&self, lit: Lit) -> lbool;
fn unsat_core(&self) -> &[Lit];
fn unsat_core_contains_lit(&self, lit: Lit) -> bool;
fn unsat_core_contains_var(&self, v: Var) -> bool;
}
pub enum SolveResult<'a, S: SolverInterface + ?Sized + 'a, Th: Theory + 'a> {
Unsat(&'a [Lit]),
Sat(SolverModel<'a, S, Th>),
Unknown(SolverModel<'a, S, Th>),
}
pub struct SolverModel<'a, S: SolverInterface + ?Sized + 'a, Th: Theory + 'a> {
solver: &'a mut S,
theory: &'a mut Th,
}
impl<'a, S: SolverInterface + ?Sized + 'a, Th: Theory + 'a> Drop for SolverModel<'a, S, Th> {
fn drop(&mut self) {
self.solver.pop_model(self.theory)
}
}
impl<'a, S: SolverInterface + ?Sized + 'a, Th: Theory + 'a> SolverModel<'a, S, Th> {
pub fn theory(&self) -> &Th {
&self.theory
}
pub fn value_lit(&self, l: Lit) -> lbool {
self.solver.raw_value_lit(l)
}
}
#[cfg(test)]
mod test {
use crate::*;
#[test]
fn test_reg7() {
let mut solver: Solver<callbacks::Basic> =
Solver::new(Default::default(), Default::default());
let a = Lit::new(solver.new_var_default(), false);
let b = Lit::new(solver.new_var_default(), false);
assert!(solver.add_clause_reuse(&mut vec![a, b]));
assert_eq!(solver.solve_limited(&[!b]), lbool::TRUE);
assert!(solver.add_clause_reuse(&mut vec![!a, b]));
assert!(solver.add_clause_reuse(&mut vec![!a, !b]));
assert_eq!(solver.solve_limited(&[]), lbool::TRUE);
assert_eq!(solver.solve_limited(&[a]), lbool::FALSE);
}
}