Incremental Solving

Incremental solving means changing and re-solving a formula multiple times, without starting the search from scratch. This can save a lot of time, when many related formulas that differ only slightly have to be solved.

Varisat supports two features that enable incremental solving. These are incremental clause additions and solving under assumptions.

Incremental Clause Additions

Incremental clause additions simply means that further calls to Solver::add_clause, Solver::add_formula or Solver::add_dimacs_cnf are allowed after Solver::solve returned. The new clauses are added to the clauses that were already present prior to the last solve call.


# #![allow(unused_variables)]
#fn main() {
# extern crate varisat;
use varisat::{ExtendFormula, Solver};

let mut solver = Solver::new();

let (x, y, z) = solver.new_lits();

solver.add_clause(&[!x, y]);
solver.add_clause(&[!y, z]);
assert_eq!(solver.solve().unwrap(), true);

solver.add_clause(&[!z, x]);
assert_eq!(solver.solve().unwrap(), true);

solver.add_clause(&[!z, !y]);
solver.add_clause(&[z, y]);
assert_eq!(solver.solve().unwrap(), false);
#}

Solving Under Assumptions

Once clauses are added to the solver they cannot be removed anymore. Instead assumptions can be used to limit the search to a subset of solutions. Assumptions fix the values of certain variables. This is equivalent to adding some unit clauses to the formula, with the difference that assumptions can be removed again.

Assumptions are set by calling Solver::assume, which replaces any previous assumptions.

Using additional helper variables, assumptions can be used to emulate removable clauses:


# #![allow(unused_variables)]
#fn main() {
# extern crate varisat;
use varisat::{ExtendFormula, Solver};

let mut solver = Solver::new();

let (x, y, z) = solver.new_lits();
let ignore_clauses = solver.new_lit();

solver.add_clause(&[!x, y]);
solver.add_clause(&[!y, z]);
assert_eq!(solver.solve().unwrap(), true);

solver.add_clause(&[!z, x]);
assert_eq!(solver.solve().unwrap(), true);

solver.add_clause(&[ignore_clauses, !z, !y]);
solver.add_clause(&[ignore_clauses, z, y]);

solver.assume(&[!ignore_clauses]);
assert_eq!(solver.solve().unwrap(), false);

solver.assume(&[]); // Clears assumptions
solver.add_clause(&[ignore_clauses]);

assert_eq!(solver.solve().unwrap(), true);
#}

When a formula is unsatisfiable under multiple assumptions, Varisat may be able to find a smaller set of assumptions that is sufficient for unsatisfiability. Such a sufficient subset of assumptions can be retrieved using Solver::failed_core.