3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-12 12:08:18 +00:00

add assert_and_track to optimize for #2116

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2019-02-01 14:59:36 -08:00
parent d1877f58a5
commit 6c464f8aec
5 changed files with 69 additions and 35 deletions

View file

@ -79,6 +79,16 @@ extern "C" {
Z3_CATCH; Z3_CATCH;
} }
void Z3_API Z3_optimize_assert_and_track(Z3_context c, Z3_optimize o, Z3_ast a, Z3_ast t) {
Z3_TRY;
LOG_Z3_optimize_assert_and_track(c, o, a, t);
RESET_ERROR_CODE();
CHECK_FORMULA(a,);
CHECK_FORMULA(t,);
to_optimize_ptr(o)->add_hard_constraint(to_expr(a), to_expr(t));
Z3_CATCH;
}
unsigned Z3_API Z3_optimize_assert_soft(Z3_context c, Z3_optimize o, Z3_ast a, Z3_string weight, Z3_symbol id) { unsigned Z3_API Z3_optimize_assert_soft(Z3_context c, Z3_optimize o, Z3_ast a, Z3_string weight, Z3_symbol id) {
Z3_TRY; Z3_TRY;
LOG_Z3_optimize_assert_soft(c, o, a, weight, id); LOG_Z3_optimize_assert_soft(c, o, a, weight, id);

View file

@ -2646,6 +2646,11 @@ namespace z3 {
strm << weight; strm << weight;
return handle(Z3_optimize_assert_soft(ctx(), m_opt, e, strm.str().c_str(), 0)); return handle(Z3_optimize_assert_soft(ctx(), m_opt, e, strm.str().c_str(), 0));
} }
void add(expr const& e, expr const& t) {
assert(e.is_bool());
Z3_optimize_assert_and_track(ctx(), m_opt, e, t);
}
handle add(expr const& e, char const* weight) { handle add(expr const& e, char const* weight) {
assert(e.is_bool()); assert(e.is_bool());
return handle(Z3_optimize_assert_soft(ctx(), m_opt, e, weight, 0)); return handle(Z3_optimize_assert_soft(ctx(), m_opt, e, weight, 0));

View file

@ -7336,6 +7336,36 @@ class Optimize(Z3PPObject):
self.add(fml) self.add(fml)
return self return self
def assert_and_track(self, a, p):
"""Assert constraint `a` and track it in the unsat core using the Boolean constant `p`.
If `p` is a string, it will be automatically converted into a Boolean constant.
>>> x = Int('x')
>>> p3 = Bool('p3')
>>> s = Optimize()
>>> s.set(unsat_core=True)
>>> s.assert_and_track(x > 0, 'p1')
>>> s.assert_and_track(x != 1, 'p2')
>>> s.assert_and_track(x < 0, p3)
>>> print(s.check())
unsat
>>> c = s.unsat_core()
>>> len(c)
2
>>> Bool('p1') in c
True
>>> Bool('p2') in c
False
>>> p3 in c
True
"""
if isinstance(p, str):
p = Bool(p, self.ctx)
_z3_assert(isinstance(a, BoolRef), "Boolean expression expected")
_z3_assert(isinstance(p, BoolRef) and is_const(p), "Boolean expression expected")
Z3_optimize_assert_and_track(self.ctx.ref(), self.optimize, a.as_ast(), p.as_ast())
def add_soft(self, arg, weight = "1", id = None): def add_soft(self, arg, weight = "1", id = None):
"""Add soft constraint with optional weight and optional identifier. """Add soft constraint with optional weight and optional identifier.
If no weight is supplied, then the penalty for violating the soft constraint If no weight is supplied, then the penalty for violating the soft constraint

View file

@ -56,11 +56,23 @@ extern "C" {
\brief Assert hard constraint to the optimization context. \brief Assert hard constraint to the optimization context.
\sa Z3_optimize_assert_soft \sa Z3_optimize_assert_soft
\sa Z3_optimize_assert_and_track
def_API('Z3_optimize_assert', VOID, (_in(CONTEXT), _in(OPTIMIZE), _in(AST))) def_API('Z3_optimize_assert', VOID, (_in(CONTEXT), _in(OPTIMIZE), _in(AST)))
*/ */
void Z3_API Z3_optimize_assert(Z3_context c, Z3_optimize o, Z3_ast a); void Z3_API Z3_optimize_assert(Z3_context c, Z3_optimize o, Z3_ast a);
/**
\brief Assert tracked hard constraint to the optimization context.
\sa Z3_optimize_assert
\sa Z3_optimize_assert_soft
def_API('Z3_optimize_assert_and_track', VOID, (_in(CONTEXT), _in(OPTIMIZE), _in(AST), _in(AST)))
*/
void Z3_API Z3_optimize_assert_and_track(Z3_context c, Z3_optimize o, Z3_ast a, Z3_ast t);
/** /**
\brief Assert soft constraint to the optimization context. \brief Assert soft constraint to the optimization context.
\param c - context \param c - context

View file

@ -76,13 +76,6 @@ namespace sat {
return; return;
} }
#if 0
if (st == status::deleted) (*m_out) << "d ";
for (unsigned i = 0; i < n; ++i) (*m_out) << c[i] << " ";
(*m_out) << "0\n";
return;
#endif
char buffer[10000]; char buffer[10000];
char digits[20]; // enough for storing unsigned char digits[20]; // enough for storing unsigned
char* lastd = digits + sizeof(digits); char* lastd = digits + sizeof(digits);
@ -93,7 +86,7 @@ namespace sat {
buffer[1] = ' '; buffer[1] = ' ';
len = 2; len = 2;
} }
for (unsigned i = 0; i < n && len < sizeof(buffer); ++i) { for (unsigned i = 0; i < n; ++i) {
literal lit = c[i]; literal lit = c[i];
unsigned v = lit.var(); unsigned v = lit.var();
if (lit.sign()) buffer[len++] = '-'; if (lit.sign()) buffer[len++] = '-';
@ -104,34 +97,18 @@ namespace sat {
v /= 10; v /= 10;
SASSERT(d > digits); SASSERT(d > digits);
} }
if (len + lastd - d < sizeof(buffer)) { SASSERT(len + lastd - d < sizeof(buffer));
memcpy(buffer + len, d, lastd - d); memcpy(buffer + len, d, lastd - d);
len += static_cast<unsigned>(lastd - d); len += static_cast<unsigned>(lastd - d);
buffer[len++] = ' ';
if (len + 50 > sizeof(buffer)) {
m_out->write(buffer, len);
len = 0;
} }
else { }
len = sizeof(buffer) + 1; buffer[len++] = '0';
} buffer[len++] = '\n';
if (len < sizeof(buffer)) { m_out->write(buffer, len);
buffer[len++] = ' ';
}
}
if (len < sizeof(buffer) + 2) {
buffer[len++] = '0';
buffer[len++] = '\n';
}
else {
len = sizeof(buffer) + 1;
}
if (len <= sizeof(buffer)) {
m_out->write(buffer, len);
}
else {
if (st == status::deleted) (*m_out) << "d ";
for (unsigned i = 0; i < n; ++i) (*m_out) << c[i] << " ";
(*m_out) << "0\n";
}
} }
void drat::bdump(unsigned n, literal const* c, status st) { void drat::bdump(unsigned n, literal const* c, status st) {