Basic Solving
To solve a formula, we start with creating a SAT solver object.
# #![allow(unused_variables)] #fn main() { # extern crate varisat; use varisat::solver::Solver; let mut solver = Solver::new(); #}
Loading a Formula
We can load a formula by adding individual clauses:
# #![allow(unused_variables)] #fn main() { # extern crate varisat; # use varisat::solver::Solver; # let mut solver = Solver::new(); use varisat::lit::Lit; let (x, y, z) = (Lit::from_dimacs(1), Lit::from_dimacs(2), Lit::from_dimacs(3)); solver.add_clause(&[x, y, z]); solver.add_clause(&[!x, !y]); solver.add_clause(&[!y, !z]); #}
By adding a formula:
# #![allow(unused_variables)] #fn main() { # extern crate varisat; # use varisat::solver::Solver; # use varisat::lit::Lit; # let mut solver = Solver::new(); # let (x, y, z) = (Lit::from_dimacs(1), Lit::from_dimacs(2), Lit::from_dimacs(3)); use varisat::cnf::CnfFormula; let mut formula = CnfFormula::new(); formula.add_clause(&[x, y, z]); formula.add_clause(&[!x, !y]); formula.add_clause(&[!y, !z]); solver.add_formula(&formula); #}
Or by directly loading a DIMACS CNF from anything that implements
std::io::Read
. This uses incremental parsing, making it more efficient than
reading the whole formula into a CnfFormula
.
# #![allow(unused_variables)] #fn main() { # extern crate varisat; # use varisat::solver::Solver; # let mut solver = Solver::new(); let dimacs_cnf = b"1 2 3 0\n-1 -2 0\n-2 -3 0\n"; solver.add_dimacs_cnf(&dimacs_cnf[..]).expect("parse error"); #}
Finding a Solution
After loading a formula, we can ask the solver to find a solution:
# #![allow(unused_variables)] #fn main() { # extern crate varisat; # use varisat::solver::Solver; # let mut solver = Solver::new(); # let dimacs_cnf = b"1 2 3 0\n-1 -2 0\n-2 -3 0\n"; # solver.add_dimacs_cnf(&dimacs_cnf[..]).expect("parse error"); let solution = solver.solve().unwrap(); assert_eq!(solution, true); // satisfiable #}
While the solve method returns a Result
, in the default configuration it
cannot fail. This means it is safe to unwrap the result here.
We might not only be interested in whether the formula is satisfiable, but also
want to know a satisfying assignment. With the Solver::model
method, we can
query the solver for a set of assignments that make all clauses true.
# #![allow(unused_variables)] #fn main() { # extern crate varisat; # use varisat::solver::Solver; # use varisat::lit::Lit; # let mut solver = Solver::new(); # let (x, y, z) = (Lit::from_dimacs(1), Lit::from_dimacs(2), Lit::from_dimacs(3)); # let dimacs_cnf = b"1 2 3 0\n-1 -2 0\n-2 -3 0\n"; # solver.add_dimacs_cnf(&dimacs_cnf[..]).expect("parse error"); # let solution = solver.solve().unwrap(); let model = solver.model().unwrap(); // None if solve didn't return Ok(true) assert!(model.contains(&x) || model.contains(&y) || model.contains(&z)); assert!(model.contains(&!x) || model.contains(&!y)); assert!(model.contains(&!y) || model.contains(&!z)); #}