mod build;
mod conflict;
mod search;
mod stage;
mod validate;
pub use self::{
build::SatSolverIF,
search::SolveIF,
stage::StageManager,
validate::ValidateIF,
};
use crate::{assign::AssignStack, cdb::ClauseDB, state::*, types::*};
#[derive(Debug, Eq, PartialEq)]
pub enum Certificate {
SAT(Vec<i32>),
UNSAT,
}
pub type SolverResult = Result<Certificate, SolverError>;
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum SolverEvent {
Assert(VarId),
Conflict,
Eliminate(VarId),
Instantiate,
NewVar,
Restart,
#[cfg(feature = "clause_vivification")]
Vivify(bool),
}
#[derive(Clone, Debug, Default)]
pub struct Solver {
pub asg: AssignStack,
pub cdb: ClauseDB,
pub state: State,
}
impl<V: AsRef<[i32]>> TryFrom<Vec<V>> for Certificate {
type Error = SolverError;
fn try_from(vec: Vec<V>) -> SolverResult {
Solver::try_from((Config::default(), vec.as_ref())).map_or_else(
|e: SolverResult| match e {
Ok(cert) => Ok(cert),
Err(SolverError::EmptyClause) => Ok(Certificate::UNSAT),
Err(e) => Err(e),
},
|mut solver| solver.solve(),
)
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::assign;
#[cfg_attr(not(feature = "no_IO"), test)]
fn test_solver() {
let config = Config::from("cnfs/sample.cnf");
if let Ok(s) = Solver::build(&config) {
assert_eq!(s.asg.derefer(assign::property::Tusize::NumVar), 250);
assert_eq!(
s.asg.derefer(assign::property::Tusize::NumUnassertedVar),
250
);
} else {
panic!("failed to build a solver for cnfs/sample.cnf");
}
}
macro_rules! run {
($vec: expr) => {
println!(
"{:>46} =| {:?}",
format!("{:?}", $vec),
match Solver::try_from((Config::default(), $vec.as_ref())).map(|mut s| s.solve()) {
Err(e) => e,
Ok(Ok(u @ Certificate::UNSAT)) => Ok(u),
Ok(s) => s,
}
);
};
}
macro_rules! sat {
($vec: expr, $should_be: pat) => {
println!("{:>46} =| ", format!("{:?}", $vec));
let result = Certificate::try_from($vec);
println!("{:?}", result);
assert!(matches!(result, $should_be));
};
($vec: expr) => {
println!(
"{:>46} =| {:?}",
format!("{:?}", $vec),
Certificate::try_from($vec)
);
};
}
#[test]
fn test_on_memory_solving() {
let mut v: Vec<Vec<i32>> = Vec::new();
run!(v);
v.push(Vec::new());
run!(v);
run!(vec![vec![1]]);
run!(vec![vec![1], vec![-1]]);
run!(vec![vec![1, 2], vec![-1, 3], vec![1, -3], vec![-1, 2]]);
run!(vec![
vec![1, 2],
vec![-1, 3],
vec![1, -3],
vec![-1, -2],
vec![-2, -3]
]);
run!(vec![
vec![1, 2],
vec![-1, 3],
vec![-1, -3],
vec![-1, -2],
vec![1, -2]
]);
let (v1, v2, v3, v4, v5) = (vec![1, 2], vec![-1, 3], vec![1, -3], vec![-1, 2], vec![-3]);
run!(vec![&v1, &v2, &v3, &v4, &v5]); run!([&v1, &v2, &v3, &v4, &v5]);
let v0: Vec<Vec<i32>> = vec![];
sat!(v0, Ok(Certificate::SAT(_)));
let v1: Vec<Vec<i32>> = vec![vec![]];
sat!(v1, Ok(Certificate::UNSAT));
sat!(vec![vec![1i32]], Ok(Certificate::SAT(_)));
sat!(vec![vec![1i32], vec![-1]], Ok(Certificate::UNSAT));
sat!(vec![vec![1i32, 2], vec![-1, 3], vec![1, -3], vec![-1, 2]]);
sat!(vec![
vec![1i32, 2],
vec![-1, 3],
vec![1, -3],
vec![-1, -2],
vec![-2, -3]
]);
sat!(vec![
vec![1i32, 2],
vec![-1, 3],
vec![-1, -3],
vec![-1, -2],
vec![1, -2]
]);
let (v1, v2, v3, v4, v5) = (
vec![1i32, 2],
vec![-1i32, 3],
vec![1i32, -3],
vec![-1i32, 2],
vec![-3i32],
);
sat!(vec![&v1, &v2, &v3, &v4, &v5]); }
}