use alloc::vec::Vec;
mod models;
mod solver;
pub use models::{Models, all_models, models, models_upto};
use solver::Solver;
pub type Var = u32;
#[derive(Clone, Copy, PartialEq, Eq, Debug)]
pub struct SatLit(u32);
impl SatLit {
pub fn new(var: Var, positive: bool) -> Self {
SatLit((var << 1) | (!positive as u32))
}
pub fn positive(var: Var) -> Self {
Self::new(var, true)
}
pub fn negative(var: Var) -> Self {
Self::new(var, false)
}
pub fn var(self) -> Var {
self.0 >> 1
}
pub fn is_negative(self) -> bool {
self.0 & 1 == 1
}
pub fn negate(self) -> SatLit {
SatLit(self.0 ^ 1)
}
fn code(self) -> usize {
self.0 as usize
}
}
#[derive(Clone, Debug, Default)]
pub struct Cnf {
pub num_vars: usize,
pub clauses: Vec<Vec<SatLit>>,
}
impl Cnf {
pub fn new(num_vars: usize) -> Self {
Cnf {
num_vars,
clauses: Vec::new(),
}
}
pub fn add_clause(&mut self, lits: Vec<SatLit>) {
self.clauses.push(lits);
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Solved {
Sat(Vec<bool>),
Unsat(Vec<SatLit>),
}
pub fn solve_assuming(cnf: &Cnf, assumptions: &[SatLit]) -> Solved {
let mut s = Solver::new(cnf);
s.assumptions = assumptions.to_vec();
match s.run() {
Ok(()) => Solved::Sat(s.model()),
Err(core) => Solved::Unsat(core),
}
}
pub fn solve(cnf: &Cnf) -> Option<Vec<bool>> {
match solve_assuming(cnf, &[]) {
Solved::Sat(model) => Some(model),
Solved::Unsat(_) => None,
}
}