3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-10 19:27:06 +00:00

Merge branch 'master' of https://github.com/z3prover/z3 into opt

This commit is contained in:
Nikolaj Bjorner 2017-02-25 16:20:33 -08:00
commit e9b49644b2
15 changed files with 255 additions and 28 deletions

View file

@ -223,6 +223,34 @@ extern "C" {
Z3_CATCH_RETURN(0);
}
// get lower value or current approximation
Z3_ast_vector Z3_API Z3_optimize_get_lower_as_vector(Z3_context c, Z3_optimize o, unsigned idx) {
Z3_TRY;
LOG_Z3_optimize_get_lower_as_vector(c, o, idx);
RESET_ERROR_CODE();
expr_ref_vector es(mk_c(c)->m());
to_optimize_ptr(o)->get_lower(idx, es);
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
mk_c(c)->save_object(v);
v->m_ast_vector.append(es.size(), (ast*const*)es.c_ptr());
RETURN_Z3(of_ast_vector(v));
Z3_CATCH_RETURN(0);
}
// get upper or current approximation
Z3_ast_vector Z3_API Z3_optimize_get_upper_as_vector(Z3_context c, Z3_optimize o, unsigned idx) {
Z3_TRY;
LOG_Z3_optimize_get_upper_as_vector(c, o, idx);
RESET_ERROR_CODE();
expr_ref_vector es(mk_c(c)->m());
to_optimize_ptr(o)->get_upper(idx, es);
Z3_ast_vector_ref * v = alloc(Z3_ast_vector_ref, *mk_c(c), mk_c(c)->m());
mk_c(c)->save_object(v);
v->m_ast_vector.append(es.size(), (ast*const*)es.c_ptr());
RETURN_Z3(of_ast_vector(v));
Z3_CATCH_RETURN(0);
}
Z3_string Z3_API Z3_optimize_to_string(Z3_context c, Z3_optimize o) {
Z3_TRY;
LOG_Z3_optimize_to_string(c, o);

View file

@ -435,6 +435,8 @@ namespace z3 {
Z3_ast_kind kind() const { Z3_ast_kind r = Z3_get_ast_kind(ctx(), m_ast); check_error(); return r; }
unsigned hash() const { unsigned r = Z3_get_ast_hash(ctx(), m_ast); check_error(); return r; }
friend std::ostream & operator<<(std::ostream & out, ast const & n);
std::string to_string() const { return std::string(Z3_ast_to_string(ctx(), m_ast)); }
/**
\brief Return true if the ASTs are structurally identical.
@ -757,7 +759,25 @@ namespace z3 {
}
return result;
}
Z3_lbool bool_value() const {
return Z3_get_bool_value(ctx(), m_ast);
}
expr numerator() const {
assert(is_numeral());
Z3_ast r = Z3_get_numerator(ctx(), m_ast);
check_error();
return expr(ctx(),r);
}
expr denominator() const {
assert(is_numeral());
Z3_ast r = Z3_get_denominator(ctx(), m_ast);
check_error();
return expr(ctx(),r);
}
operator Z3_app() const { assert(is_app()); return reinterpret_cast<Z3_app>(m_ast); }
@ -875,13 +895,23 @@ namespace z3 {
friend expr operator*(expr const & a, int b);
friend expr operator*(int a, expr const & b);
/**
\brief Power operator
*/
/* \brief Power operator */
friend expr pw(expr const & a, expr const & b);
friend expr pw(expr const & a, int b);
friend expr pw(int a, expr const & b);
/* \brief mod operator */
friend expr mod(expr const& a, expr const& b);
friend expr mod(expr const& a, int b);
friend expr mod(int a, expr const& b);
/* \brief rem operator */
friend expr rem(expr const& a, expr const& b);
friend expr rem(expr const& a, int b);
friend expr rem(int a, expr const& b);
friend expr is_int(expr const& e);
friend expr operator/(expr const & a, expr const & b);
friend expr operator/(expr const & a, int b);
friend expr operator/(int a, expr const & b);
@ -1012,34 +1042,46 @@ namespace z3 {
};
#define _Z3_MK_BIN_(a, b, binop) \
check_context(a, b); \
Z3_ast r = binop(a.ctx(), a, b); \
a.check_error(); \
return expr(a.ctx(), r); \
inline expr implies(expr const & a, expr const & b) {
check_context(a, b);
assert(a.is_bool() && b.is_bool());
Z3_ast r = Z3_mk_implies(a.ctx(), a, b);
a.check_error();
return expr(a.ctx(), r);
assert(a.is_bool() && b.is_bool());
_Z3_MK_BIN_(a, b, Z3_mk_implies);
}
inline expr implies(expr const & a, bool b) { return implies(a, a.ctx().bool_val(b)); }
inline expr implies(bool a, expr const & b) { return implies(b.ctx().bool_val(a), b); }
inline expr pw(expr const & a, expr const & b) {
assert(a.is_arith() && b.is_arith());
check_context(a, b);
Z3_ast r = Z3_mk_power(a.ctx(), a, b);
a.check_error();
return expr(a.ctx(), r);
}
inline expr pw(expr const & a, expr const & b) { _Z3_MK_BIN_(a, b, Z3_mk_power); }
inline expr pw(expr const & a, int b) { return pw(a, a.ctx().num_val(b, a.get_sort())); }
inline expr pw(int a, expr const & b) { return pw(b.ctx().num_val(a, b.get_sort()), b); }
inline expr mod(expr const& a, expr const& b) { _Z3_MK_BIN_(a, b, Z3_mk_mod); }
inline expr mod(expr const & a, int b) { return mod(a, a.ctx().num_val(b, a.get_sort())); }
inline expr mod(int a, expr const & b) { return mod(b.ctx().num_val(a, b.get_sort()), b); }
inline expr operator!(expr const & a) {
assert(a.is_bool());
Z3_ast r = Z3_mk_not(a.ctx(), a);
a.check_error();
return expr(a.ctx(), r);
}
inline expr rem(expr const& a, expr const& b) { _Z3_MK_BIN_(a, b, Z3_mk_rem); }
inline expr rem(expr const & a, int b) { return rem(a, a.ctx().num_val(b, a.get_sort())); }
inline expr rem(int a, expr const & b) { return rem(b.ctx().num_val(a, b.get_sort()), b); }
#undef _Z3_MK_BIN_
#define _Z3_MK_UN_(a, mkun) \
Z3_ast r = mkun(a.ctx(), a); \
a.check_error(); \
return expr(a.ctx(), r); \
inline expr operator!(expr const & a) { assert(a.is_bool()); _Z3_MK_UN_(a, Z3_mk_not); }
inline expr is_int(expr const& e) { _Z3_MK_UN_(e, Z3_mk_is_int); }
#undef _Z3_MK_UN_
inline expr operator&&(expr const & a, expr const & b) {
check_context(a, b);
@ -1944,6 +1986,8 @@ namespace z3 {
friend tactic repeat(tactic const & t, unsigned max);
friend tactic with(tactic const & t, params const & p);
friend tactic try_for(tactic const & t, unsigned ms);
friend tactic par_or(unsigned n, tactic const* tactics);
friend tactic par_and_then(tactic const& t1, tactic const& t2);
param_descrs get_param_descrs() { return param_descrs(ctx(), Z3_tactic_get_param_descrs(ctx(), m_tactic)); }
};
@ -1977,7 +2021,21 @@ namespace z3 {
t.check_error();
return tactic(t.ctx(), r);
}
inline tactic par_or(unsigned n, tactic const* tactics) {
if (n == 0) {
throw exception("a non-zero number of tactics need to be passed to par_or");
}
array<Z3_tactic> buffer(n);
for (unsigned i = 0; i < n; ++i) buffer[i] = tactics[i];
return tactic(tactics[0].ctx(), Z3_tactic_par_or(tactics[0].ctx(), n, buffer.ptr()));
}
inline tactic par_and_then(tactic const & t1, tactic const & t2) {
check_context(t1, t2);
Z3_tactic r = Z3_tactic_par_and_then(t1.ctx(), t1, t2);
t1.check_error();
return tactic(t1.ctx(), r);
}
class probe : public object {
Z3_probe m_probe;

View file

@ -144,6 +144,23 @@ namespace Microsoft.Z3
{
get { return Lower; }
}
/// <summary>
/// Retrieve a lower bound for the objective handle.
/// </summary>
public ArithExpr[] LowerAsVector
{
get { return opt.GetLowerAsVector(handle); }
}
/// <summary>
/// Retrieve an upper bound for the objective handle.
/// </summary>
public ArithExpr[] UpperAsVector
{
get { return opt.GetUpperAsVector(handle); }
}
}
/// <summary>
@ -255,6 +272,25 @@ namespace Microsoft.Z3
return (ArithExpr)Expr.Create(Context, Native.Z3_optimize_get_upper(Context.nCtx, NativeObject, index));
}
/// <summary>
/// Retrieve a lower bound for the objective handle.
/// </summary>
private ArithExpr[] GetLowerAsVector(uint index)
{
ASTVector v = new ASTVector(Context, Native.Z3_optimize_get_lower_as_vector(Context.nCtx, NativeObject, index));
return v.ToArithExprArray();
}
/// <summary>
/// Retrieve an upper bound for the objective handle.
/// </summary>
private ArithExpr[] GetUpperAsVector(uint index)
{
ASTVector v = new ASTVector(Context, Native.Z3_optimize_get_upper_as_vector(Context.nCtx, NativeObject, index));
return v.ToArithExprArray();
}
/// <summary>
/// Return a string the describes why the last to check returned unknown
/// </summary>

View file

@ -868,6 +868,9 @@ class ExprRef(AstRef):
_args, sz = _to_ast_array((a, b))
return BoolRef(Z3_mk_distinct(self.ctx_ref(), 2, _args), self.ctx)
def params(self):
return self.decl().params()
def decl(self):
"""Return the Z3 function declaration associated with a Z3 application.
@ -6716,12 +6719,24 @@ class OptimizeObjective:
opt = self._opt
return _to_expr_ref(Z3_optimize_get_upper(opt.ctx.ref(), opt.optimize, self._value), opt.ctx)
def lower_values(self):
opt = self._opt
return AstVector(Z3_optimize_get_lower_as_vector(opt.ctx.ref(), opt.optimize, self._value), opt.ctx)
def upper_values(self):
opt = self._opt
return AstVector(Z3_optimize_get_upper_as_vector(opt.ctx.ref(), opt.optimize, self._value), opt.ctx)
def value(self):
if self._is_max:
return self.upper()
else:
return self.lower()
def __str__(self):
return "%s:%s" % (self._value, self._is_max)
class Optimize(Z3PPObject):
"""Optimize API provides methods for solving using objective functions and weighted soft constraints"""
@ -6826,6 +6841,16 @@ class Optimize(Z3PPObject):
raise Z3Exception("Expecting objective handle returned by maximize/minimize")
return obj.upper()
def lower_values(self, obj):
if not isinstance(obj, OptimizeObjective):
raise Z3Exception("Expecting objective handle returned by maximize/minimize")
return obj.lower_values()
def upper_values(self, obj):
if not isinstance(obj, OptimizeObjective):
raise Z3Exception("Expecting objective handle returned by maximize/minimize")
return obj.upper_values()
def from_file(self, filename):
"""Parse assertions and objectives from a file"""
Z3_optimize_from_file(self.ctx.ref(), self.optimize, filename)

View file

@ -678,7 +678,7 @@ class Formatter:
if self.fpa_pretty:
if self.is_infix(k) and n >= 3:
rm = a.arg(0)
if z3.is_fprm_value(rm) and z3._dflt_rm(a.ctx).eq(rm):
if z3.is_fprm_value(rm) and z3.get_default_rounding_mode(a.ctx).eq(rm):
arg1 = to_format(self.pp_expr(a.arg(1), d+1, xs))
arg2 = to_format(self.pp_expr(a.arg(2), d+1, xs))
r = []

View file

@ -186,6 +186,33 @@ extern "C" {
*/
Z3_ast Z3_API Z3_optimize_get_upper(Z3_context c, Z3_optimize o, unsigned idx);
/**
\brief Retrieve lower bound value or approximation for the i'th optimization objective.
The returned vector is of length 3. It always contains numerals.
The three numerals are coefficients a, b, c and encode the result of \c Z3_optimize_get_lower
a * infinity + b + c * epsilon.
\param c - context
\param o - optimization context
\param idx - index of optimization objective
def_API('Z3_optimize_get_lower_as_vector', AST_VECTOR, (_in(CONTEXT), _in(OPTIMIZE), _in(UINT)))
*/
Z3_ast_vector Z3_API Z3_optimize_get_lower_as_vector(Z3_context c, Z3_optimize o, unsigned idx);
/**
\brief Retrieve upper bound value or approximation for the i'th optimization objective.
\param c - context
\param o - optimization context
\param idx - index of optimization objective
def_API('Z3_optimize_get_upper_as_vector', AST_VECTOR, (_in(CONTEXT), _in(OPTIMIZE), _in(UINT)))
*/
Z3_ast_vector Z3_API Z3_optimize_get_upper_as_vector(Z3_context c, Z3_optimize o, unsigned idx);
/**
\brief Print the current context as a string.
\param c - context.

View file

@ -85,7 +85,7 @@ struct enum2bv_rewriter::imp {
void throw_non_fd(expr* e) {
std::stringstream strm;
strm << "unabled nested data-type expression " << mk_pp(e, m);
strm << "unable to handle nested data-type expression " << mk_pp(e, m);
throw rewriter_exception(strm.str().c_str());
}

View file

@ -38,8 +38,16 @@ static bool is_hex_digit(char ch, unsigned& d) {
return false;
}
static bool is_octal_digit(char ch, unsigned& d) {
if ('0' <= ch && ch <= '7') {
d = ch - '0';
return true;
}
return false;
}
static bool is_escape_char(char const *& s, unsigned& result) {
unsigned d1, d2;
unsigned d1, d2, d3;
if (*s != '\\' || *(s + 1) == 0) {
return false;
}
@ -49,6 +57,29 @@ static bool is_escape_char(char const *& s, unsigned& result) {
s += 4;
return true;
}
/* C-standard octal escapes: either 1, 2, or 3 octal digits,
* stopping either at 3 digits or at the first non-digit character.
*/
/* 1 octal digit */
if (is_octal_digit(*(s + 1), d1) && !is_octal_digit(*(s + 2), d2)) {
result = d1;
s += 2;
return true;
}
/* 2 octal digits */
if (is_octal_digit(*(s + 1), d1) && is_octal_digit(*(s + 2), d2) &&
!is_octal_digit(*(s + 3), d3)) {
result = d1 * 8 + d2;
s += 3;
return true;
}
/* 3 octal digits */
if (is_octal_digit(*(s + 1), d1) && is_octal_digit(*(s + 2), d2) &&
is_octal_digit(*(s + 3), d3)) {
result = d1*64 + d2*8 + d3;
s += 4;
return true;
}
switch (*(s + 1)) {
case 'a':
result = '\a';

View file

@ -223,7 +223,7 @@ public:
cmd_context::scoped_watch sw(ctx);
lbool r = l_undef;
try {
r = check_sat(t, g, md, result->labels, pr, core, reason_unknown);
r = check_sat(t, g, md, result->labels, pr, core, reason_unknown);
ctx.display_sat_result(r);
result->set_status(r);
if (r == l_undef) {

View file

@ -1290,6 +1290,15 @@ namespace opt {
return to_expr(get_upper_as_num(idx));
}
void context::to_exprs(inf_eps const& n, expr_ref_vector& es) {
rational inf = n.get_infinity();
rational r = n.get_rational();
rational eps = n.get_infinitesimal();
es.push_back(m_arith.mk_numeral(inf, inf.is_int()));
es.push_back(m_arith.mk_numeral(r, r.is_int()));
es.push_back(m_arith.mk_numeral(eps, eps.is_int()));
}
expr_ref context::to_expr(inf_eps const& n) {
rational inf = n.get_infinity();
rational r = n.get_rational();
@ -1455,9 +1464,10 @@ namespace opt {
void context::validate_maxsat(symbol const& id) {
maxsmt& ms = *m_maxsmts.find(id);
TRACE("opt", tout << "Validate: " << id << "\n";);
for (unsigned i = 0; i < m_objectives.size(); ++i) {
objective const& obj = m_objectives[i];
if (obj.m_id == id) {
if (obj.m_id == id && obj.m_type == O_MAXSMT) {
SASSERT(obj.m_type == O_MAXSMT);
rational value(0);
expr_ref val(m);

View file

@ -207,6 +207,9 @@ namespace opt {
expr_ref get_lower(unsigned idx);
expr_ref get_upper(unsigned idx);
void get_lower(unsigned idx, expr_ref_vector& es) { to_exprs(get_lower_as_num(idx), es); }
void get_upper(unsigned idx, expr_ref_vector& es) { to_exprs(get_upper_as_num(idx), es); }
std::string to_string() const;
@ -238,6 +241,7 @@ namespace opt {
lbool adjust_unknown(lbool r);
bool scoped_lex();
expr_ref to_expr(inf_eps const& n);
void to_exprs(inf_eps const& n, expr_ref_vector& es);
void reset_maxsmts();
void import_scoped_state();

View file

@ -25,6 +25,9 @@ Notes:
#include"filter_model_converter.h"
#include"ast_util.h"
#include"solver2tactic.h"
#include"smt_solver.h"
#include"solver.h"
#include"mus.h"
typedef obj_map<expr, expr *> expr2expr_map;
@ -159,6 +162,8 @@ public:
ref<filter_model_converter> fmc;
if (in->unsat_core_enabled()) {
extract_clauses_and_dependencies(in, clauses, assumptions, bool2dep, fmc);
TRACE("mus", in->display_with_dependencies(tout);
tout << clauses << "\n";);
if (in->proofs_enabled() && !assumptions.empty())
throw tactic_exception("smt tactic does not support simultaneous generation of proofs and unsat cores");
for (unsigned i = 0; i < clauses.size(); ++i) {

View file

@ -89,6 +89,7 @@ struct mus::imp {
lbool get_mus1(expr_ref_vector& mus) {
ptr_vector<expr> unknown(m_lit2expr.size(), m_lit2expr.c_ptr());
ptr_vector<expr> core_exprs;
TRACE("mus", m_solver.display(tout););
while (!unknown.empty()) {
IF_VERBOSE(12, verbose_stream() << "(mus reducing core: " << unknown.size() << " new core: " << mus.size() << ")\n";);
TRACE("mus", display_vec(tout << "core: ", unknown); display_vec(tout << "mus: ", mus););

View file

@ -290,3 +290,5 @@ solver_factory * mk_tactic2solver_factory(tactic * t) {
solver_factory * mk_tactic_factory2solver_factory(tactic_factory * f) {
return alloc(tactic_factory2solver_factory, f);
}

View file

@ -23,7 +23,6 @@ Notes:
#include"model_v2_pp.h"
struct tactic_report::imp {
char const * m_id;
goal const & m_goal;
@ -175,6 +174,7 @@ void exec(tactic & t, goal_ref const & in, goal_ref_buffer & result, model_conve
}
}
lbool check_sat(tactic & t, goal_ref & g, model_ref & md, labels_vec & labels, proof_ref & pr, expr_dependency_ref & core, std::string & reason_unknown) {
bool models_enabled = g->models_enabled();
bool proofs_enabled = g->proofs_enabled();