3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-10 19:27:06 +00:00
This commit is contained in:
Christoph M. Wintersteiger 2016-07-28 19:52:56 +01:00
commit 5f449b5c0d
7 changed files with 201 additions and 13 deletions

View file

@ -35,6 +35,7 @@ set(Z3_VERSION_MAJOR 4)
set(Z3_VERSION_MINOR 4)
set(Z3_VERSION_PATCH 2)
set(Z3_VERSION_TWEAK 1)
set(Z3_FULL_VERSION 0)
set(Z3_VERSION "${Z3_VERSION_MAJOR}.${Z3_VERSION_MINOR}.${Z3_VERSION_PATCH}.${Z3_VERSION_TWEAK}")
message(STATUS "Z3 version ${Z3_VERSION}")

View file

@ -413,4 +413,42 @@ extern "C" {
Z3_CATCH_RETURN(Z3_L_UNDEF);
}
Z3_lbool Z3_API Z3_solver_get_consequences(Z3_context c,
Z3_solver s,
Z3_ast_vector assumptions,
Z3_ast_vector variables,
Z3_ast_vector consequences) {
Z3_TRY;
LOG_Z3_solver_get_consequences(c, s, assumptions, variables, consequences);
ast_manager& m = mk_c(c)->m();
RESET_ERROR_CODE();
CHECK_SEARCHING(c);
init_solver(c, s);
expr_ref_vector _assumptions(m), _consequences(m), _variables(m);
ast_ref_vector const& __assumptions = to_ast_vector_ref(assumptions);
unsigned sz = __assumptions.size();
for (unsigned i = 0; i < sz; ++i) {
if (!is_expr(__assumptions[i])) {
SET_ERROR_CODE(Z3_INVALID_USAGE);
return Z3_L_UNDEF;
}
_assumptions.push_back(to_expr(__assumptions[i]));
}
ast_ref_vector const& __variables = to_ast_vector_ref(variables);
sz = __variables.size();
for (unsigned i = 0; i < sz; ++i) {
if (!is_expr(__variables[i])) {
SET_ERROR_CODE(Z3_INVALID_USAGE);
return Z3_L_UNDEF;
}
_variables.push_back(to_expr(__variables[i]));
}
lbool result = to_solver_ref(s)->get_consequences(_assumptions, _variables, _consequences);
for (unsigned i = 0; i < _consequences.size(); ++i) {
to_ast_vector_ref(consequences).push_back(_consequences[i].get());
}
return static_cast<Z3_lbool>(result);
Z3_CATCH_RETURN(Z3_L_UNDEF);
}
};

View file

@ -18,6 +18,7 @@ Notes:
--*/
using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
namespace Microsoft.Z3
@ -212,12 +213,34 @@ namespace Microsoft.Z3
r = (Z3_lbool)Native.Z3_solver_check(Context.nCtx, NativeObject);
else
r = (Z3_lbool)Native.Z3_solver_check_assumptions(Context.nCtx, NativeObject, (uint)assumptions.Length, AST.ArrayToNative(assumptions));
switch (r)
{
case Z3_lbool.Z3_L_TRUE: return Status.SATISFIABLE;
case Z3_lbool.Z3_L_FALSE: return Status.UNSATISFIABLE;
default: return Status.UNKNOWN;
}
return lboolToStatus(r);
}
/// <summary>
/// Retrieve fixed assignments to the set of variables in the form of consequences.
/// Each consequence is an implication of the form
///
/// relevant-assumptions Implies variable = value
///
/// where the relevant assumptions is a subset of the assumptions that are passed in
/// and the equality on the right side of the implication indicates how a variable
/// is fixed.
/// </summary>
/// <remarks>
/// <seealso cref="Model"/>
/// <seealso cref="UnsatCore"/>
/// <seealso cref="Proof"/>
/// </remarks>
public Status Consequences(IEnumerable<BoolExpr> assumptions, IEnumerable<Expr> variables, out BoolExpr[] consequences)
{
ASTVector result = new ASTVector(Context);
ASTVector asms = new ASTVector(Context);
ASTVector vars = new ASTVector(Context);
foreach (var asm in assumptions) asms.Push(asm);
foreach (var v in variables) vars.Push(v);
Z3_lbool r = (Z3_lbool)Native.Z3_solver_get_consequences(Context.nCtx, NativeObject, asms.NativeObject, vars.NativeObject, result.NativeObject);
consequences = result.ToBoolExprArray();
return lboolToStatus(r);
}
/// <summary>
@ -295,7 +318,7 @@ namespace Microsoft.Z3
/// </summary>
public Solver Translate(Context ctx)
{
Contract.Requires(ctx != null);
Contract.Requires(ctx != null);
Contract.Ensures(Contract.Result<Solver>() != null);
return new Solver(ctx, Native.Z3_solver_translate(Context.nCtx, NativeObject, ctx.nCtx));
}
@ -355,6 +378,17 @@ namespace Microsoft.Z3
Context.Solver_DRQ.Add(o);
base.DecRef(o);
}
private Status lboolToStatus(Z3_lbool r)
{
switch (r)
{
case Z3_lbool.Z3_L_TRUE: return Status.SATISFIABLE;
case Z3_lbool.Z3_L_FALSE: return Status.UNSATISFIABLE;
default: return Status.UNKNOWN;
}
}
#endregion
}
}

View file

@ -6126,6 +6126,28 @@ class Solver(Z3PPObject):
"""
return AstVector(Z3_solver_get_unsat_core(self.ctx.ref(), self.solver), self.ctx)
def consequences(self, assumptions, variables):
"""Determine fixed values for the variables based on the solver state and assumptions.
documentation TBD
"""
if isinstance(assumptions, list):
_asms = AstVector(None, self.ctx)
for a in assumptions:
_asms.push(a)
assumptions = _asms
if isinstance(variables, list):
_vars = AstVector(None, self.ctx)
for a in variables:
_vars.push(a)
variables = _vars
_z3_assert(isinstance(assumptions, AstVector), "ast vector expected")
_z3_assert(isinstance(variables, AstVector), "ast vector expected")
consequences = AstVector(None, self.ctx)
r = Z3_solver_get_consequences(self.ctx.ref(), self.solver, assumptions.vector, variables.vector, consequences.vector)
sz = len(consequences)
consequences = [ consequences[i] for i in range(sz) ]
return CheckSatResult(r), consequences
def proof(self):
"""Return a proof for the last `check()`. Proof construction must be enabled."""
return _to_expr_ref(Z3_solver_get_proof(self.ctx.ref(), self.solver), self.ctx)

View file

@ -5894,6 +5894,17 @@ extern "C" {
Z3_ast const terms[],
unsigned class_ids[]);
/**
\brief retrieve consequences from solver that determine values of the supplied function symbols.
def_API('Z3_solver_get_consequences', INT, (_in(CONTEXT), _in(SOLVER), _in(AST_VECTOR), _in(AST_VECTOR), _in(AST_VECTOR)))
*/
Z3_lbool Z3_API Z3_solver_get_consequences(Z3_context c,
Z3_solver s,
Z3_ast_vector assumptions,
Z3_ast_vector variables,
Z3_ast_vector consequences);
/**
\brief Retrieve the model for the last #Z3_solver_check or #Z3_solver_check_assumptions

View file

@ -17,6 +17,8 @@ Notes:
--*/
#include"solver.h"
#include"model_evaluator.h"
#include"ast_util.h"
unsigned solver::get_num_assertions() const {
NOT_IMPLEMENTED_YET();
@ -38,3 +40,82 @@ void solver::get_assertions(expr_ref_vector& fmls) const {
fmls.push_back(get_assertion(i));
}
}
struct scoped_assumption_push {
expr_ref_vector& m_vec;
scoped_assumption_push(expr_ref_vector& v, expr* e): m_vec(v) { v.push_back(e); }
~scoped_assumption_push() { m_vec.pop_back(); }
};
lbool solver::get_consequences(expr_ref_vector const& asms, expr_ref_vector const& vars, expr_ref_vector& consequences) {
ast_manager& m = asms.get_manager();
lbool is_sat = check_sat(asms);
if (is_sat != l_true) {
return is_sat;
}
model_ref model;
get_model(model);
expr_ref tmp(m), nlit(m), lit(m), val(m);
expr_ref_vector asms1(asms);
model_evaluator eval(*model.get());
unsigned k = 0;
for (unsigned i = 0; i < vars.size(); ++i) {
expr_ref_vector core(m);
tmp = vars[i];
val = eval(tmp);
if (!m.is_value(val)) {
continue;
}
if (m.is_bool(tmp) && is_uninterp_const(tmp)) {
if (m.is_true(val)) {
nlit = m.mk_not(tmp);
lit = tmp;
}
else if (m.is_false(val)) {
nlit = tmp;
lit = m.mk_not(tmp);
}
else {
continue;
}
scoped_assumption_push _scoped_push(asms1, nlit);
is_sat = check_sat(asms1);
switch (is_sat) {
case l_undef:
return is_sat;
case l_true:
break;
case l_false:
get_unsat_core(core);
k = 0;
for (unsigned j = 0; j < core.size(); ++j) {
if (core[j].get() != nlit) {
core[k] = core[j].get();
++k;
}
}
core.resize(k);
consequences.push_back(m.mk_implies(mk_and(core), lit));
break;
}
}
else {
lit = m.mk_eq(tmp, val);
nlit = m.mk_not(lit);
scoped_push _scoped_push(*this);
assert_expr(nlit);
is_sat = check_sat(asms);
switch (is_sat) {
case l_undef:
return is_sat;
case l_true:
break;
case l_false:
get_unsat_core(core);
consequences.push_back(m.mk_implies(mk_and(core), lit));
break;
}
}
}
return l_true;
}

View file

@ -150,12 +150,13 @@ public:
virtual expr * get_assumption(unsigned idx) const = 0;
/**
\brief under assumptions, asms, retrieve set of consequences that fix values for expressions that can be
built from fns. For functions that take 0 arguments, we require that the function returns all consequences
that mention these functions. The consequences are clauses whose first literal constrain one of the
functions from fns and the other literals are negations of literals from asms.
*/
//virtual lbool get_consequences(expr_ref_vector const& asms, func_ref_vector const& fns, expr_ref_vector& consequences);
\brief under assumptions, asms, retrieve set of consequences that
fix values for expressions that can be built from vars.
The consequences are clauses whose first literal constrain one of the
functions from vars and the other literals are negations of literals from asms.
*/
virtual lbool get_consequences(expr_ref_vector const& asms, expr_ref_vector const& vars, expr_ref_vector& consequences);
/**
\brief Display the content of this solver.