Skip to content

Commit

Permalink
Support consequences API (#302)
Browse files Browse the repository at this point in the history
Add consequences, allowing you to derive implied propositions from a set of assumed propositions.
  • Loading branch information
VadeveSi committed Aug 7, 2024
1 parent 42bae5f commit 045bd2e
Show file tree
Hide file tree
Showing 2 changed files with 64 additions and 0 deletions.
35 changes: 35 additions & 0 deletions z3/src/solver.rs
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,41 @@ impl<'ctx> Solver<'ctx> {
unsat_core
}

/// Retrieve consequences from the solver given a set of assumptions.
pub fn get_consequences(&self,
assumptions: &[ast::Bool<'ctx>],
variables: &[ast::Bool<'ctx>],
) -> Vec<ast::Bool<'ctx>> {
unsafe {
let _assumptions = Z3_mk_ast_vector(self.ctx.z3_ctx);
Z3_ast_vector_inc_ref(self.ctx.z3_ctx, _assumptions);
assumptions.iter().for_each(|x| {
Z3_ast_vector_push(self.ctx.z3_ctx, _assumptions, x.z3_ast.clone());
});

let _variables = Z3_mk_ast_vector(self.ctx.z3_ctx);
Z3_ast_vector_inc_ref(self.ctx.z3_ctx, _variables);
variables.iter().for_each(|x| {
Z3_ast_vector_push(self.ctx.z3_ctx, _variables, x.z3_ast.clone());
});
let consequences = Z3_mk_ast_vector(self.ctx.z3_ctx);
Z3_ast_vector_inc_ref(self.ctx.z3_ctx, consequences);

Z3_solver_get_consequences(self.ctx.z3_ctx,
self.z3_slv,
_assumptions,
_variables,
consequences);
let mut cons = vec!();
for i in 0..Z3_ast_vector_size(self.ctx.z3_ctx, consequences) {
let val = Z3_ast_vector_get(self.ctx.z3_ctx, consequences, i);
cons.push(ast::Bool::wrap(self.ctx, val));
}
cons
}
}


/// Create a backtracking point.
///
/// The solver contains a stack of assertions.
Expand Down
29 changes: 29 additions & 0 deletions z3/tests/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1892,3 +1892,32 @@ fn get_version() {
println!("Z3 version: {:?}", z3::version());
println!("Z3 full version string: {}", z3::full_version());
}

#[test]
fn test_consequences() {
let cfg = Config::new();
let ctx = &Context::new(&cfg);
let solver = Solver::new(ctx);
let a = Bool::new_const(&ctx, "a");
let b = Bool::new_const(&ctx, "b");
let c = Bool::new_const(&ctx, "c");
let d = Bool::new_const(&ctx, "d");
solver.assert(&a.implies(&b));
solver.assert(&b.implies(&c));

let assumptions = vec!(a.clone());
let variables = vec!(b.clone(), c.clone(), d.clone());
let mut cons = solver.get_consequences(&assumptions, &variables);
assert!(cons.len() == 2);
assert!(cons.pop().unwrap().to_string() == "(=> a c)");
assert!(cons.pop().unwrap().to_string() == "(=> a b)");

let assumptions = vec!(c.not(), d.clone());
let variables = vec!(a, b, c, d);
let mut cons = solver.get_consequences(&assumptions, &variables);
assert!(cons.len() == 4);
assert!(cons.pop().unwrap().to_string() == "(=> (not c) (not a))");
assert!(cons.pop().unwrap().to_string() == "(=> (not c) (not b))");
assert!(cons.pop().unwrap().to_string() == "(=> (not c) (not c))");
assert!(cons.pop().unwrap().to_string() == "(=> d d)");
}

0 comments on commit 045bd2e

Please sign in to comment.