3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-08 10:25:18 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2016-12-21 10:04:02 -08:00
commit df492e200f
99 changed files with 1659 additions and 702 deletions

View file

@ -1168,7 +1168,8 @@ class ExeComponent(Component):
c_dep = get_component(dep)
out.write(' ' + c_dep.get_link_name())
out.write('\n')
out.write('\t$(LINK) $(LINK_OUT_FLAG)%s $(LINK_FLAGS)' % exefile)
extra_opt = '-static' if not IS_WINDOWS and STATIC_BIN else ''
out.write('\t$(LINK) %s $(LINK_OUT_FLAG)%s $(LINK_FLAGS)' % (extra_opt, exefile))
for obj in objs:
out.write(' ')
out.write(obj)
@ -1972,7 +1973,7 @@ class MLComponent(Component):
z3mls = os.path.join(self.sub_dir, 'z3ml')
out.write('%s.cma: %s %s %s\n' % (z3mls, cmos, stubso, z3dllso))
out.write('\t%s -o %s -I %s %s %s %s\n' % (OCAMLMKLIB, z3mls, self.sub_dir, stubso, cmos, LIBZ3))
out.write('%s.cmxa: %s %s %s\n' % (z3mls, cmxs, stubso, z3dllso))
out.write('%s.cmxa: %s %s %s %s.cma\n' % (z3mls, cmxs, stubso, z3dllso, z3mls))
out.write('\t%s -o %s -I %s %s %s %s\n' % (OCAMLMKLIB, z3mls, self.sub_dir, stubso, cmxs, LIBZ3))
out.write('%s.cmxs: %s.cmxa\n' % (z3mls, z3mls))
out.write('\t%s -shared -o %s.cmxs -I %s %s.cmxa\n' % (OCAMLOPTF, z3mls, self.sub_dir, z3mls))
@ -2506,10 +2507,7 @@ def mk_config():
config.write('AR_OUTFLAG=\n')
config.write('EXE_EXT=\n')
config.write('LINK=%s\n' % CXX)
if STATIC_BIN:
config.write('LINK_FLAGS=-static\n')
else:
config.write('LINK_FLAGS=\n')
config.write('LINK_FLAGS=\n')
config.write('LINK_OUT_FLAG=-o \n')
config.write('LINK_EXTRA_FLAGS=-lpthread %s\n' % LDFLAGS)
config.write('SO_EXT=%s\n' % SO_EXT)

View file

@ -1611,7 +1611,7 @@ _lib = None
def lib():
global _lib
if _lib is None:
_dirs = ['.', pkg_resources.resource_filename('z3', 'lib'), os.path.join(sys.prefix, 'lib'), None]
_dirs = ['.', os.path.dirname(os.path.abspath(__file__)), pkg_resources.resource_filename('z3', 'lib'), os.path.join(sys.prefix, 'lib'), None]
for _dir in _dirs:
try:
init(_dir)

View file

@ -1128,6 +1128,10 @@ extern "C" {
case Z3_OP_RE_OPTION: return Z3_OP_RE_OPTION;
case Z3_OP_RE_CONCAT: return Z3_OP_RE_CONCAT;
case Z3_OP_RE_UNION: return Z3_OP_RE_UNION;
case Z3_OP_RE_INTERSECT: return Z3_OP_RE_INTERSECT;
case Z3_OP_RE_LOOP: return Z3_OP_RE_LOOP;
case Z3_OP_RE_FULL_SET: return Z3_OP_RE_FULL_SET;
case Z3_OP_RE_EMPTY_SET: return Z3_OP_RE_EMPTY_SET;
default:
return Z3_OP_INTERNAL;
}

View file

@ -116,15 +116,18 @@ extern "C" {
Z3_CATCH_RETURN("");
}
Z3_ast Z3_API Z3_mk_seq_empty(Z3_context c, Z3_sort seq) {
Z3_TRY;
LOG_Z3_mk_seq_empty(c, seq);
RESET_ERROR_CODE();
app* a = mk_c(c)->sutil().str.mk_empty(to_sort(seq));
mk_c(c)->save_ast_trail(a);
RETURN_Z3(of_ast(a));
Z3_CATCH_RETURN(0);
}
#define MK_SORTED(NAME, FN ) \
Z3_ast Z3_API NAME(Z3_context c, Z3_sort s) { \
Z3_TRY; \
LOG_ ## NAME(c, s); \
RESET_ERROR_CODE(); \
app* a = FN(to_sort(s)); \
mk_c(c)->save_ast_trail(a); \
RETURN_Z3(of_ast(a)); \
Z3_CATCH_RETURN(0); \
}
MK_SORTED(Z3_mk_seq_empty, mk_c(c)->sutil().str.mk_empty);
MK_UNARY(Z3_mk_seq_unit, mk_c(c)->get_seq_fid(), OP_SEQ_UNIT, SKIP);
MK_NARY(Z3_mk_seq_concat, mk_c(c)->get_seq_fid(), OP_SEQ_CONCAT, SKIP);
@ -139,12 +142,27 @@ extern "C" {
MK_UNARY(Z3_mk_seq_to_re, mk_c(c)->get_seq_fid(), OP_SEQ_TO_RE, SKIP);
MK_BINARY(Z3_mk_seq_in_re, mk_c(c)->get_seq_fid(), OP_SEQ_IN_RE, SKIP);
Z3_ast Z3_API Z3_mk_re_loop(Z3_context c, Z3_ast r, unsigned lo, unsigned hi) {
Z3_TRY;
LOG_Z3_mk_re_loop(c, r, lo, hi);
RESET_ERROR_CODE();
app* a = hi == 0 ? mk_c(c)->sutil().re.mk_loop(to_expr(r), lo) : mk_c(c)->sutil().re.mk_loop(to_expr(r), lo, hi);
mk_c(c)->save_ast_trail(a);
RETURN_Z3(of_ast(a));
Z3_CATCH_RETURN(0);
}
MK_UNARY(Z3_mk_re_plus, mk_c(c)->get_seq_fid(), OP_RE_PLUS, SKIP);
MK_UNARY(Z3_mk_re_star, mk_c(c)->get_seq_fid(), OP_RE_STAR, SKIP);
MK_UNARY(Z3_mk_re_option, mk_c(c)->get_seq_fid(), OP_RE_OPTION, SKIP);
MK_UNARY(Z3_mk_re_complement, mk_c(c)->get_seq_fid(), OP_RE_COMPLEMENT, SKIP);
MK_NARY(Z3_mk_re_union, mk_c(c)->get_seq_fid(), OP_RE_UNION, SKIP);
MK_NARY(Z3_mk_re_intersect, mk_c(c)->get_seq_fid(), OP_RE_INTERSECT, SKIP);
MK_NARY(Z3_mk_re_concat, mk_c(c)->get_seq_fid(), OP_RE_CONCAT, SKIP);
MK_BINARY(Z3_mk_re_range, mk_c(c)->get_seq_fid(), OP_RE_RANGE, SKIP);
MK_SORTED(Z3_mk_re_empty, mk_c(c)->sutil().re.mk_empty);
MK_SORTED(Z3_mk_re_full, mk_c(c)->sutil().re.mk_full);

View file

@ -934,7 +934,20 @@ namespace z3 {
check_error();
return expr(ctx(), r);
}
friend expr range(expr const& lo, expr const& hi);
/**
\brief create a looping regular expression.
*/
expr loop(unsigned lo) {
Z3_ast r = Z3_mk_re_loop(ctx(), m_ast, lo, 0);
check_error();
return expr(ctx(), r);
}
expr loop(unsigned lo, unsigned hi) {
Z3_ast r = Z3_mk_re_loop(ctx(), m_ast, lo, hi);
check_error();
return expr(ctx(), r);
}
/**
@ -1227,7 +1240,6 @@ namespace z3 {
/**
\brief Create the if-then-else expression <tt>ite(c, t, e)</tt>
@ -2436,31 +2448,51 @@ namespace z3 {
return expr(s.ctx(), r);
}
inline expr to_re(expr const& s) {
Z3_ast r = Z3_mk_seq_to_re(s.ctx(), s);
s.check_error();
return expr(s.ctx(), r);
MK_EXPR1(Z3_mk_seq_to_re, s);
}
inline expr in_re(expr const& s, expr const& re) {
check_context(s, re);
Z3_ast r = Z3_mk_seq_in_re(s.ctx(), s, re);
MK_EXPR2(Z3_mk_seq_in_re, s, re);
}
inline expr plus(expr const& re) {
MK_EXPR1(Z3_mk_re_plus, re);
}
inline expr option(expr const& re) {
MK_EXPR1(Z3_mk_re_option, re);
}
inline expr star(expr const& re) {
MK_EXPR1(Z3_mk_re_star, re);
}
inline expr re_empty(sort const& s) {
Z3_ast r = Z3_mk_re_empty(s.ctx(), s);
s.check_error();
return expr(s.ctx(), r);
}
inline expr plus(expr const& re) {
Z3_ast r = Z3_mk_re_plus(re.ctx(), re);
re.check_error();
return expr(re.ctx(), r);
inline expr re_full(sort const& s) {
Z3_ast r = Z3_mk_re_full(s.ctx(), s);
s.check_error();
return expr(s.ctx(), r);
}
inline expr option(expr const& re) {
Z3_ast r = Z3_mk_re_option(re.ctx(), re);
re.check_error();
return expr(re.ctx(), r);
inline expr re_intersect(expr_vector const& args) {
assert(args.size() > 0);
context& ctx = args[0].ctx();
array<Z3_ast> _args(args);
Z3_ast r = Z3_mk_re_intersect(ctx, _args.size(), _args.ptr());
ctx.check_error();
return expr(ctx, r);
}
inline expr star(expr const& re) {
Z3_ast r = Z3_mk_re_star(re.ctx(), re);
re.check_error();
return expr(re.ctx(), r);
inline expr re_complement(expr const& a) {
MK_EXPR1(Z3_mk_re_complement, a);
}
inline expr range(expr const& lo, expr const& hi) {
check_context(lo, hi);
Z3_ast r = Z3_mk_re_range(lo.ctx(), lo, hi);
lo.check_error();
return expr(lo.ctx(), r);
}
inline expr interpolant(expr const& a) {
return expr(a.ctx(), Z3_mk_interpolant(a.ctx(), a));

View file

@ -2564,10 +2564,20 @@ namespace Microsoft.Z3
return new ReExpr(this, Native.Z3_mk_re_star(nCtx, re.NativeObject));
}
/// <summary>
/// Take the bounded Kleene star of a regular expression.
/// </summary>
public ReExpr MkLoop(ReExpr re, uint lo, uint hi = 0)
{
Contract.Requires(re != null);
Contract.Ensures(Contract.Result<ReExpr>() != null);
return new ReExpr(this, Native.Z3_mk_re_loop(nCtx, re.NativeObject, lo, hi));
}
/// <summary>
/// Take the Kleene plus of a regular expression.
/// </summary>
public ReExpr MPlus(ReExpr re)
public ReExpr MkPlus(ReExpr re)
{
Contract.Requires(re != null);
Contract.Ensures(Contract.Result<ReExpr>() != null);
@ -2577,13 +2587,23 @@ namespace Microsoft.Z3
/// <summary>
/// Create the optional regular expression.
/// </summary>
public ReExpr MOption(ReExpr re)
public ReExpr MkOption(ReExpr re)
{
Contract.Requires(re != null);
Contract.Ensures(Contract.Result<ReExpr>() != null);
return new ReExpr(this, Native.Z3_mk_re_option(nCtx, re.NativeObject));
}
/// <summary>
/// Create the complement regular expression.
/// </summary>
public ReExpr MkComplement(ReExpr re)
{
Contract.Requires(re != null);
Contract.Ensures(Contract.Result<ReExpr>() != null);
return new ReExpr(this, Native.Z3_mk_re_complement(nCtx, re.NativeObject));
}
/// <summary>
/// Create the concatenation of regular languages.
/// </summary>
@ -2609,6 +2629,52 @@ namespace Microsoft.Z3
CheckContextMatch<ReExpr>(t);
return new ReExpr(this, Native.Z3_mk_re_union(nCtx, (uint)t.Length, AST.ArrayToNative(t)));
}
/// <summary>
/// Create the intersection of regular languages.
/// </summary>
public ReExpr MkIntersect(params ReExpr[] t)
{
Contract.Requires(t != null);
Contract.Requires(Contract.ForAll(t, a => a != null));
Contract.Ensures(Contract.Result<ReExpr>() != null);
CheckContextMatch<ReExpr>(t);
return new ReExpr(this, Native.Z3_mk_re_intersect(nCtx, (uint)t.Length, AST.ArrayToNative(t)));
}
/// <summary>
/// Create the empty regular expression.
/// </summary>
public ReExpr MkEmptyRe(Sort s)
{
Contract.Requires(s != null);
Contract.Ensures(Contract.Result<SeqExpr>() != null);
return new ReExpr(this, Native.Z3_mk_re_empty(nCtx, s.NativeObject));
}
/// <summary>
/// Create the full regular expression.
/// </summary>
public ReExpr MkFullRe(Sort s)
{
Contract.Requires(s != null);
Contract.Ensures(Contract.Result<SeqExpr>() != null);
return new ReExpr(this, Native.Z3_mk_re_full(nCtx, s.NativeObject));
}
/// <summary>
/// Create a range expression.
/// </summary>
public ReExpr MkRange(SeqExpr lo, SeqExpr hi)
{
Contract.Requires(lo != null);
Contract.Requires(hi != null);
Contract.Ensures(Contract.Result<ReExpr>() != null);
CheckContextMatch(lo, hi);
return new ReExpr(this, Native.Z3_mk_re_range(nCtx, lo.NativeObject, hi.NativeObject));
}
#endregion

View file

@ -31,13 +31,17 @@ public class Context implements AutoCloseable {
static final Object creation_lock = new Object();
public Context () {
m_ctx = Native.mkContextRc(0);
init();
synchronized (creation_lock) {
m_ctx = Native.mkContextRc(0);
init();
}
}
protected Context (long m_ctx) {
this.m_ctx = m_ctx;
init();
synchronized (creation_lock) {
this.m_ctx = m_ctx;
init();
}
}
@ -59,13 +63,15 @@ public class Context implements AutoCloseable {
* module parameters. For this purpose we should now use {@code Global.setParameter}
**/
public Context(Map<String, String> settings) {
long cfg = Native.mkConfig();
for (Map.Entry<String, String> kv : settings.entrySet()) {
Native.setParamValue(cfg, kv.getKey(), kv.getValue());
synchronized (creation_lock) {
long cfg = Native.mkConfig();
for (Map.Entry<String, String> kv : settings.entrySet()) {
Native.setParamValue(cfg, kv.getKey(), kv.getValue());
}
m_ctx = Native.mkContextRc(cfg);
Native.delConfig(cfg);
init();
}
m_ctx = Native.mkContextRc(cfg);
Native.delConfig(cfg);
init();
}
private void init() {
@ -4037,7 +4043,9 @@ public class Context implements AutoCloseable {
m_intSort = null;
m_realSort = null;
m_stringSort = null;
Native.delContext(m_ctx);
synchronized (creation_lock) {
Native.delContext(m_ctx);
}
}
}

View file

@ -9384,6 +9384,7 @@ class SeqSortRef(SortRef):
False
"""
return Z3_is_string_sort(self.ctx_ref(), self.ast)
def StringSort(ctx=None):
"""Create a string sort
@ -9507,8 +9508,29 @@ def Empty(s):
>>> e3 = Empty(SeqSort(IntSort()))
>>> print(e3)
seq.empty
>>> e4 = Empty(ReSort(SeqSort(IntSort())))
>>> print(e4)
re.empty
"""
return SeqRef(Z3_mk_seq_empty(s.ctx_ref(), s.ast), s.ctx)
if isinstance(s, SeqSortRef):
return SeqRef(Z3_mk_seq_empty(s.ctx_ref(), s.ast), s.ctx)
if isinstance(s, ReSortRef):
return ReRef(Z3_mk_re_empty(s.ctx_ref(), s.ast), s.ctx)
raise Z3Exception("Non-sequence, non-regular expression sort passed to Empty")
def Full(s):
"""Create the regular expression that accepts the universal langauge
>>> e = Full(ReSort(SeqSort(IntSort())))
>>> print(e)
re.all
>>> e1 = Full(ReSort(StringSort()))
>>> print(e1)
re.allchar
"""
if isinstance(s, ReSortRef):
return ReRef(Z3_mk_re_full(s.ctx_ref(), s.ast), s.ctx)
raise Z3Exception("Non-sequence, non-regular expression sort passed to Full")
def Unit(a):
"""Create a singleton sequence"""
@ -9624,10 +9646,10 @@ class ReSortRef(SortRef):
def ReSort(s):
if is_ast(s):
return ReSortRef(Z3_mk_re_sort(s.ctx.ref(), s.as_ast()), ctx)
return ReSortRef(Z3_mk_re_sort(s.ctx.ref(), s.ast), s.ctx)
if s is None or isinstance(s, Context):
ctx = _get_ctx(s)
return ReSortRef(Z3_mk_re_sort(ctx.ref(), Z3_mk_string_sort(ctx.ref())), ctx)
return ReSortRef(Z3_mk_re_sort(ctx.ref(), Z3_mk_string_sort(ctx.ref())), s.ctx)
raise Z3Exception("Regular expression sort constructor expects either a string or a context or no argument")
@ -9698,6 +9720,10 @@ def Option(re):
"""
return ReRef(Z3_mk_re_option(re.ctx_ref(), re.as_ast()), re.ctx)
def Complement(re):
"""Create the complement regular expression."""
return ReRef(Z3_mk_re_complement(re.ctx_ref(), re.as_ast()), re.ctx)
def Star(re):
"""Create the regular expression accepting zero or more repetitions of argument.
>>> re = Star(Re("a"))
@ -9709,3 +9735,15 @@ def Star(re):
True
"""
return ReRef(Z3_mk_re_star(re.ctx_ref(), re.as_ast()), re.ctx)
def Loop(re, lo, hi=0):
"""Create the regular expression accepting between a lower and upper bound repetitions
>>> re = Loop(Re("a"), 1, 3)
>>> print(simplify(InRe("aa", re)))
True
>>> print(simplify(InRe("aaaa", re)))
False
>>> print(simplify(InRe("", re)))
False
"""
return ReRef(Z3_mk_re_loop(re.ctx_ref(), re.as_ast(), lo, hi), re.ctx)

View file

@ -1154,6 +1154,12 @@ typedef enum {
Z3_OP_RE_OPTION,
Z3_OP_RE_CONCAT,
Z3_OP_RE_UNION,
Z3_OP_RE_RANGE,
Z3_OP_RE_LOOP,
Z3_OP_RE_INTERSECT,
Z3_OP_RE_EMPTY_SET,
Z3_OP_RE_FULL_SET,
Z3_OP_RE_COMPLEMENT,
// Auxiliary
Z3_OP_LABEL = 0x700,
@ -3367,6 +3373,60 @@ extern "C" {
*/
Z3_ast Z3_API Z3_mk_re_concat(Z3_context c, unsigned n, Z3_ast const args[]);
/**
\brief Create the range regular expression over two sequences of length 1.
def_API('Z3_mk_re_range' ,AST ,(_in(CONTEXT), _in(AST), _in(AST)))
*/
Z3_ast Z3_API Z3_mk_re_range(Z3_context c, Z3_ast lo, Z3_ast hi);
/**
\brief Create a regular expression loop. The supplied regular expression \c r is repated
between \c lo and \c hi times. The \c lo should be below \c hi with one exection: when
supplying the value \c hi as 0, the meaning is to repeat the argument \c r at least
\c lo number of times, and with an unbounded upper bound.
def_API('Z3_mk_re_loop', AST, (_in(CONTEXT), _in(AST), _in(UINT), _in(UINT)))
*/
Z3_ast Z3_API Z3_mk_re_loop(Z3_context c, Z3_ast r, unsigned lo, unsigned hi);
/**
\brief Create the intersection of the regular languages.
\pre n > 0
def_API('Z3_mk_re_intersect' ,AST ,(_in(CONTEXT), _in(UINT), _in_array(1, AST)))
*/
Z3_ast Z3_API Z3_mk_re_intersect(Z3_context c, unsigned n, Z3_ast const args[]);
/**
\brief Create the complement of the regular language \c re.
def_API('Z3_mk_re_complement' ,AST ,(_in(CONTEXT), _in(AST)))
*/
Z3_ast Z3_API Z3_mk_re_complement(Z3_context c, Z3_ast re);
/**
\brief Create an empty regular expression of sort \c re.
\pre re is a regular expression sort.
def_API('Z3_mk_re_empty' ,AST ,(_in(CONTEXT), _in(SORT)))
*/
Z3_ast Z3_API Z3_mk_re_empty(Z3_context c, Z3_sort re);
/**
\brief Create an universal regular expression of sort \c re.
\pre re is a regular expression sort.
def_API('Z3_mk_re_full' ,AST ,(_in(CONTEXT), _in(SORT)))
*/
Z3_ast Z3_API Z3_mk_re_full(Z3_context c, Z3_sort re);
/*@}*/

View file

@ -1463,11 +1463,17 @@ void fpa2bv_converter::mk_fma(func_decl * f, unsigned num, expr * const * args,
v6 = z;
// (x is 0) || (y is 0) -> z
expr_ref c71(m), xy_sgn(m), xyz_sgn(m);
m_simp.mk_or(x_is_zero, y_is_zero, c7);
expr_ref ite_c(m), rm_is_not_to_neg(m);
m_simp.mk_xor(x_is_neg, y_is_neg, xy_sgn);
m_simp.mk_xor(xy_sgn, z_is_neg, xyz_sgn);
m_simp.mk_and(z_is_zero, xyz_sgn, c71);
expr_ref zero_cond(m), rm_is_not_to_neg(m);
rm_is_not_to_neg = m.mk_not(rm_is_to_neg);
m_simp.mk_and(z_is_zero, rm_is_not_to_neg, ite_c);
mk_ite(ite_c, pzero, z, v7);
m_simp.mk_ite(rm_is_to_neg, nzero, pzero, zero_cond);
mk_ite(c71, zero_cond, z, v7);
// else comes the fused multiplication.
unsigned ebits = m_util.get_ebits(f->get_range());

View file

@ -494,7 +494,7 @@ void macro_util::normalize_expr(app * head, expr * t, expr_ref & norm_t) const {
tout << "applying substitution to:\n" << mk_ll_pp(t, m_manager) << "\nsubstitution:\n";
for (unsigned i = 0; i < var_mapping.size(); i++) {
if (var_mapping[i] != 0)
tout << "#" << i << " -> " << mk_ll_pp(var_mapping[i], m_manager);
tout << "#" << i << " -> " << mk_ll_pp(var_mapping[i], m_manager);
});
subst(t, var_mapping.size(), var_mapping.c_ptr(), norm_t);
}

View file

@ -91,7 +91,7 @@ func_decl * pb_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters, p
}
void pb_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol const & logic) {
if (logic == symbol::null) {
if (logic == symbol::null || logic == "QF_FD") {
op_names.push_back(builtin_name(m_at_most_sym.bare_str(), OP_AT_MOST_K));
op_names.push_back(builtin_name(m_at_least_sym.bare_str(), OP_AT_LEAST_K));
op_names.push_back(builtin_name(m_pble_sym.bare_str(), OP_PB_LE));

View file

@ -66,9 +66,6 @@ struct blaster_cfg {
void mk_nor(expr * a, expr * b, expr_ref & r) { m_rewriter.mk_nor(a, b, r); }
};
// CMW: GCC/LLVM do not like this definition because a symbol of the same name exists in assert_set_bit_blaster.o
// template class bit_blaster_tpl<blaster_cfg>;
class blaster : public bit_blaster_tpl<blaster_cfg> {
bool_rewriter m_rewriter;
bv_util m_util;
@ -625,9 +622,6 @@ MK_PARAMETRIC_UNARY_REDUCE(reduce_sign_extend, mk_sign_extend);
}
};
// CMW: GCC/LLVM do not like this definition because a symbol of the same name exists in assert_set_bit_blaster.o
// template class rewriter_tpl<blaster_rewriter_cfg>;
struct bit_blaster_rewriter::imp : public rewriter_tpl<blaster_rewriter_cfg> {
blaster m_blaster;
blaster_rewriter_cfg m_cfg;

View file

@ -111,7 +111,7 @@ protected:
void elim_reflex_prs(unsigned spos);
public:
rewriter_core(ast_manager & m, bool proof_gen);
~rewriter_core();
virtual ~rewriter_core();
ast_manager & m() const { return m_manager; }
void reset();
void cleanup();

View file

@ -243,9 +243,9 @@ eautomaton* re2automaton::re2aut(expr* e) {
TRACE("seq", tout << "Range expression is not handled: " << mk_pp(e, m) << "\n";);
}
}
else if (u.re.is_complement(e, e0) && (a = re2aut(e0)) && m_sa) {
return m_sa->mk_complement(*a);
}
else if (u.re.is_complement(e, e0) && (a = re2aut(e0)) && m_sa) {
return m_sa->mk_complement(*a);
}
else if (u.re.is_loop(e, e1, lo, hi) && (a = re2aut(e1))) {
scoped_ptr<eautomaton> eps = eautomaton::mk_epsilon(sm);
b = eautomaton::mk_epsilon(sm);
@ -524,7 +524,7 @@ br_status seq_rewriter::mk_seq_contains(expr* a, expr* b, expr_ref& result) {
result = m().mk_bool_val(c.contains(d));
return BR_DONE;
}
// check if subsequence of b is in a.
// check if subsequence of a is in b.
expr_ref_vector as(m()), bs(m());
m_util.str.get_concat(a, as);
m_util.str.get_concat(b, bs);
@ -587,6 +587,12 @@ br_status seq_rewriter::mk_seq_contains(expr* a, expr* b, expr_ref& result) {
SASSERT(sz > offs);
result = m_util.str.mk_contains(m_util.str.mk_concat(sz-offs, as.c_ptr()+offs), b);
return BR_REWRITE2;
}
expr* x, *y, *z;
if (m_util.str.is_extract(b, x, y, z) && x == a) {
result = m().mk_true();
return BR_DONE;
}
return BR_FAILED;
@ -1715,7 +1721,7 @@ bool seq_rewriter::solve_itos(unsigned szl, expr* const* ls, unsigned szr, expr*
}
}
if (szr == 1 && m_util.str.is_itos(rs[0], r)) {
if (szr == 1 && m_util.str.is_itos(rs[0], r) && !m_util.str.is_itos(ls[0])) {
return solve_itos(szr, rs, szl, ls, rhs, lhs, is_sat);
}

View file

@ -601,7 +601,7 @@ func_decl * seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
match(*m_sigs[k], arity, domain, range, rng);
return m.mk_func_decl(symbol("re.allchar"), arity, domain, rng, func_decl_info(m_family_id, k));
}
return m.mk_func_decl(m_sigs[k]->m_name, arity, domain, rng, func_decl_info(m_family_id, k));
return m.mk_func_decl(m_sigs[k]->m_name, arity, domain, range, func_decl_info(m_family_id, k));
case _OP_REGEXP_EMPTY:
@ -617,7 +617,7 @@ func_decl * seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
match(*m_sigs[k], arity, domain, range, rng);
return m.mk_func_decl(symbol("re.nostr"), arity, domain, rng, func_decl_info(m_family_id, k));
}
return m.mk_func_decl(m_sigs[k]->m_name, arity, domain, rng, func_decl_info(m_family_id, k));
return m.mk_func_decl(m_sigs[k]->m_name, arity, domain, range, func_decl_info(m_family_id, k));
case OP_RE_LOOP:
switch (arity) {
@ -861,7 +861,7 @@ app* seq_util::re::mk_full(sort* s) {
return m.mk_app(m_fid, OP_RE_FULL_SET, 0, 0, 0, 0, s);
}
app* seq_util::re::mk_empty(sort* s) {
app* seq_util::re::mk_empty(sort* s) {
return m.mk_app(m_fid, OP_RE_EMPTY_SET, 0, 0, 0, 0, s);
}

View file

@ -21,6 +21,7 @@ Revision History:
#include"array_decl_plugin.h"
#include"bv_decl_plugin.h"
#include"seq_decl_plugin.h"
#include"pb_decl_plugin.h"
#include"datatype_decl_plugin.h"
#include"ast_pp.h"
#include"for_each_expr.h"
@ -34,6 +35,7 @@ struct check_logic::imp {
array_util m_ar_util;
seq_util m_seq_util;
datatype_util m_dt_util;
pb_util m_pb_util;
bool m_uf; // true if the logic supports uninterpreted functions
bool m_arrays; // true if the logic supports arbitrary arrays
bool m_bv_arrays; // true if the logic supports only bv arrays
@ -45,7 +47,7 @@ struct check_logic::imp {
bool m_quantifiers; // true if the logic supports quantifiers
bool m_unknown_logic;
imp(ast_manager & _m):m(_m), m_a_util(m), m_bv_util(m), m_ar_util(m), m_seq_util(m), m_dt_util(m) {
imp(ast_manager & _m):m(_m), m_a_util(m), m_bv_util(m), m_ar_util(m), m_seq_util(m), m_dt_util(m), m_pb_util(m) {
reset();
}
@ -443,6 +445,9 @@ struct check_logic::imp {
else if (fid == m_dt_util.get_family_id() && m_logic == "QF_FD") {
// nothing to check
}
else if (fid == m_pb_util.get_family_id() && m_logic == "QF_FD") {
// nothing to check
}
else {
std::stringstream strm;
strm << "logic does not support theory " << m.get_family_name(fid);

View file

@ -519,6 +519,10 @@ bool cmd_context::logic_has_seq() const {
return !has_logic() || smt_logics::logic_has_seq(m_logic);
}
bool cmd_context::logic_has_pb() const {
return !has_logic() || smt_logics::logic_has_pb(m_logic);
}
bool cmd_context::logic_has_fpa() const {
return !has_logic() || smt_logics::logic_has_fpa(m_logic);
}
@ -547,7 +551,7 @@ void cmd_context::init_manager_core(bool new_manager) {
register_plugin(symbol("array"), alloc(array_decl_plugin), logic_has_array());
register_plugin(symbol("datatype"), alloc(datatype_decl_plugin), logic_has_datatype());
register_plugin(symbol("seq"), alloc(seq_decl_plugin), logic_has_seq());
register_plugin(symbol("pb"), alloc(pb_decl_plugin), !has_logic());
register_plugin(symbol("pb"), alloc(pb_decl_plugin), logic_has_pb());
register_plugin(symbol("fpa"), alloc(fpa_decl_plugin), logic_has_fpa());
register_plugin(symbol("datalog_relation"), alloc(datalog::dl_decl_plugin), !has_logic());
}
@ -563,6 +567,7 @@ void cmd_context::init_manager_core(bool new_manager) {
load_plugin(symbol("datatype"), logic_has_datatype(), fids);
load_plugin(symbol("seq"), logic_has_seq(), fids);
load_plugin(symbol("fpa"), logic_has_fpa(), fids);
load_plugin(symbol("pb"), logic_has_pb(), fids);
svector<family_id>::iterator it = fids.begin();
svector<family_id>::iterator end = fids.end();

View file

@ -251,6 +251,7 @@ protected:
bool logic_has_arith() const;
bool logic_has_bv() const;
bool logic_has_pb() const;
bool logic_has_seq() const;
bool logic_has_array() const;
bool logic_has_datatype() const;

View file

@ -72,6 +72,7 @@ public:
// m_params.set_func_decl(m_last, f);
// m_last = symbol::null;
}
virtual void set_next_arg(cmd_context & ctx, sexpr * n) { UNREACHABLE(); }
};
#endif

View file

@ -3099,7 +3099,7 @@ namespace Duality {
// Maps nodes of derivation tree into old subtree
hash_map<Node *, Node*> cex_map;
virtual void ChooseExpand(const std::set<RPFP::Node *> &choices, std::set<RPFP::Node *> &best){
virtual void ChooseExpand(const std::set<RPFP::Node *> &choices, std::set<RPFP::Node *> &best, bool, bool){
if(old_node == 0){
Heuristic::ChooseExpand(choices,best);
return;

View file

@ -26,6 +26,7 @@ Revision History:
template<class T>
class positive_boolean_algebra {
public:
virtual ~positive_boolean_algebra() {}
virtual T mk_false() = 0;
virtual T mk_true() = 0;
virtual T mk_and(T x, T y) = 0;
@ -38,6 +39,7 @@ public:
template<class T>
class boolean_algebra : public positive_boolean_algebra<T> {
public:
virtual ~boolean_algebra() {}
virtual T mk_not(T x) = 0;
//virtual lbool are_equivalent(T x, T y) = 0;
//virtual T simplify(T x) = 0;

View file

@ -35,6 +35,8 @@ class subpaving_tactic : public tactic {
display_var_proc(expr2var & e2v):m_inv(e2v.m()) {
e2v.mk_inv(m_inv);
}
virtual ~display_var_proc() {}
ast_manager & m() const { return m_inv.get_manager(); }

View file

@ -88,18 +88,20 @@ void model_core::register_decl(func_decl * d, func_interp * fi) {
}
void model_core::unregister_decl(func_decl * d) {
decl2expr::obj_map_entry * ec = m_interp.find_core(d);
if (ec && ec->get_data().m_value != 0) {
m_manager.dec_ref(ec->get_data().m_key);
m_manager.dec_ref(ec->get_data().m_value);
m_interp.remove(d);
return;
}
decl2finterp::obj_map_entry * ef = m_finterp.find_core(d);
if (ef && ef->get_data().m_value != 0) {
m_manager.dec_ref(ef->get_data().m_key);
dealloc(ef->get_data().m_value);
m_finterp.remove(d);
}
}
decl2expr::obj_map_entry * ec = m_interp.find_core(d);
if (ec && ec->get_data().m_value != 0) {
m_manager.dec_ref(ec->get_data().m_key);
m_manager.dec_ref(ec->get_data().m_value);
m_interp.remove(d);
m_const_decls.erase(d);
return;
}
decl2finterp::obj_map_entry * ef = m_finterp.find_core(d);
if (ef && ef->get_data().m_value != 0) {
m_manager.dec_ref(ef->get_data().m_key);
dealloc(ef->get_data().m_value);
m_finterp.remove(d);
m_func_decls.erase(d);
}
}

View file

@ -60,7 +60,7 @@ public:
void register_decl(func_decl * d, expr * v);
void register_decl(func_decl * f, func_interp * fi);
void unregister_decl(func_decl * d);
void unregister_decl(func_decl * d);
virtual expr * get_some_value(sort * s) = 0;

View file

@ -119,7 +119,6 @@ namespace datalog {
virtual expr_ref try_get_formula(func_decl * pred) const = 0;
virtual void display_output_facts(rule_set const& rules, std::ostream & out) const = 0;
virtual void display_facts(std::ostream & out) const = 0;
virtual void display_profile(std::ostream& out) = 0;
virtual void restrict_predicates(func_decl_set const& predicates) = 0;
virtual bool result_contains_fact(relation_fact const& f) = 0;
virtual void add_fact(func_decl* pred, relation_fact const& fact) = 0;

View file

@ -66,7 +66,7 @@ namespace datalog {
}
virtual void reset_statistics() {}
virtual void display_profile(std::ostream& out) const {}
virtual void display_profile(std::ostream& out) {}
virtual void collect_statistics(statistics& st) const {}
virtual unsigned get_num_levels(func_decl* pred) {
throw default_exception(std::string("get_num_levels is not supported for ") + m_name);

View file

@ -220,6 +220,8 @@ namespace datalog {
*/
class mutator_fn : public base_fn {
public:
virtual ~mutator_fn() {}
virtual void operator()(base_object & t) = 0;
virtual bool supports_attachment(base_object& other) { return false; }
@ -869,6 +871,7 @@ namespace datalog {
class table_row_mutator_fn {
public:
virtual ~table_row_mutator_fn() {}
/**
\brief The function is called for a particular table row. The \c func_columns contains
a pointer to an array of functional column values that can be modified. If the function
@ -882,6 +885,7 @@ namespace datalog {
class table_row_pair_reduce_fn {
public:
virtual ~table_row_pair_reduce_fn() {}
/**
\brief The function is called for pair of table rows that became duplicit due to projection.
The values that are in the first array after return from the function will be used for the

View file

@ -255,7 +255,7 @@ namespace datalog {
table_plugin & tplugin = rmgr.get_appropriate_plugin(tsig);
relation_plugin & inner_plugin = rmgr.get_table_relation_plugin(tplugin);
return sieve_relation_plugin::get_plugin(rmgr).mk_full(p, sig, inner_plugin);
return sieve_relation_plugin::get_plugin(rmgr).full(p, sig, inner_plugin);
}
void init(relation_signature const& r1_sig, unsigned num_rels1, relation_base const* const* r1,
@ -294,7 +294,7 @@ namespace datalog {
rel2 = r1_plugin.mk_full(p, r2_sig, r1_kind);
}
else {
rel2 = sieve_relation_plugin::get_plugin(rmgr).mk_full(p, r2_sig, r1_plugin);
rel2 = sieve_relation_plugin::get_plugin(rmgr).full(p, r2_sig, r1_plugin);
}
m_offset1.push_back(i);
m_kind1.push_back(T_INPUT);
@ -318,7 +318,7 @@ namespace datalog {
rel1 = r2_plugin.mk_full(p, r1_sig, r2_kind);
}
else {
rel1 = sieve_relation_plugin::get_plugin(rmgr).mk_full(p, r1_sig, r2_plugin);
rel1 = sieve_relation_plugin::get_plugin(rmgr).full(p, r1_sig, r2_plugin);
}
m_offset1.push_back(m_full.size());
m_kind1.push_back(T_FULL);

View file

@ -1622,6 +1622,8 @@ namespace datalog {
m_union_fn = plugin.mk_union_fn(t, *m_aux_table, static_cast<table_base *>(0));
}
virtual ~default_table_map_fn() {}
virtual void operator()(table_base & t) {
SASSERT(t.get_signature()==m_aux_table->get_signature());
if(!m_aux_table->empty()) {
@ -1678,6 +1680,8 @@ namespace datalog {
m_former_row.resize(get_result_signature().size());
}
virtual ~default_table_project_with_reduce_fn() {}
virtual void modify_fact(table_fact & f) const {
unsigned ofs=1;
unsigned r_i=1;

View file

@ -253,7 +253,7 @@ namespace datalog {
return mk_from_inner(s, inner_cols, inner);
}
sieve_relation * sieve_relation_plugin::mk_full(func_decl* p, const relation_signature & s, relation_plugin & inner_plugin) {
sieve_relation * sieve_relation_plugin::full(func_decl* p, const relation_signature & s, relation_plugin & inner_plugin) {
SASSERT(!inner_plugin.is_sieve_relation()); //it does not make sense to make a sieve of a sieve
svector<bool> inner_cols(s.size());
extract_inner_columns(s, inner_plugin, inner_cols);

View file

@ -104,8 +104,7 @@ namespace datalog {
sieve_relation * mk_empty(const relation_signature & s, relation_plugin & inner_plugin);
virtual relation_base * mk_full(func_decl* p, const relation_signature & s);
sieve_relation * mk_full(func_decl* p, const relation_signature & s, relation_plugin & inner_plugin);
sieve_relation * full(func_decl* p, const relation_signature & s, relation_plugin & inner_plugin);
sieve_relation * mk_from_inner(const relation_signature & s, const bool * inner_columns,
relation_base * inner_rel);

View file

@ -54,7 +54,7 @@ namespace datalog {
return alloc(table_relation, *this, s, t);
}
relation_base * table_relation_plugin::mk_full(const relation_signature & s, func_decl* p, family_id kind) {
relation_base * table_relation_plugin::mk_full_relation(const relation_signature & s, func_decl* p, family_id kind) {
table_signature tsig;
if(!get_manager().relation_signature_to_table(s, tsig)) {
return 0;

View file

@ -49,7 +49,7 @@ namespace datalog {
virtual bool can_handle_signature(const relation_signature & s);
virtual relation_base * mk_empty(const relation_signature & s);
virtual relation_base * mk_full(const relation_signature & s, func_decl* p, family_id kind);
virtual relation_base * mk_full_relation(const relation_signature & s, func_decl* p, family_id kind);
relation_base * mk_from_table(const relation_signature & s, table_base * t);
protected:

View file

@ -805,8 +805,9 @@ public:
lbool init_local() {
m_lower.reset();
m_trail.reset();
lbool is_sat = l_true;
obj_map<expr, rational> new_soft;
lbool is_sat = find_mutexes(new_soft);
is_sat = find_mutexes(new_soft);
if (is_sat != l_true) {
return is_sat;
}

View file

@ -333,8 +333,15 @@ namespace opt {
TRACE("opt", tout << mk_pp(f, m) << " weight: " << w << "\n";);
SASSERT(m.is_bool(f));
SASSERT(w.is_pos());
m_soft_constraints.push_back(f);
m_weights.push_back(w);
unsigned index = 0;
if (m_soft_constraint_index.find(f, index)) {
m_weights[index] += w;
}
else {
m_soft_constraint_index.insert(f, m_weights.size());
m_soft_constraints.push_back(f);
m_weights.push_back(w);
}
m_upper += w;
}

View file

@ -120,6 +120,7 @@ namespace opt {
unsigned m_index;
scoped_ptr<maxsmt_solver_base> m_msolver;
expr_ref_vector m_soft_constraints;
obj_map<expr, unsigned> m_soft_constraint_index;
expr_ref_vector m_answer;
vector<rational> m_weights;
rational m_lower;
@ -138,7 +139,6 @@ namespace opt {
expr* operator[](unsigned idx) const { return m_soft_constraints[idx]; }
rational weight(unsigned idx) const { return m_weights[idx]; }
void commit_assignment();
rational get_value() const;
rational get_lower() const;
rational get_upper() const;
void update_lower(rational const& r);

View file

@ -169,6 +169,11 @@ namespace opt {
r.append(m_labels);
}
void context::get_unsat_core(ptr_vector<expr> & r) {
throw default_exception("Unsat cores are not supported with optimization");
}
void context::set_hard_constraints(ptr_vector<expr>& fmls) {
if (m_scoped_state.set(fmls)) {
clear_state();
@ -355,6 +360,7 @@ namespace opt {
}
if (scoped) get_solver().pop(1);
if (result == l_true && committed) ms.commit_assignment();
DEBUG_CODE(if (result == l_true) validate_maxsat(id););
return result;
}
@ -1443,6 +1449,32 @@ namespace opt {
return out.str();
}
void context::validate_maxsat(symbol const& id) {
maxsmt& ms = *m_maxsmts.find(id);
for (unsigned i = 0; i < m_objectives.size(); ++i) {
objective const& obj = m_objectives[i];
if (obj.m_id == id) {
SASSERT(obj.m_type == O_MAXSMT);
rational value(0);
expr_ref val(m);
for (unsigned i = 0; i < obj.m_terms.size(); ++i) {
bool evaluated = m_model->eval(obj.m_terms[i], val);
SASSERT(evaluated);
CTRACE("opt", evaluated && !m.is_true(val) && !m.is_false(val), tout << mk_pp(obj.m_terms[i], m) << " " << val << "\n";);
CTRACE("opt", !evaluated, tout << mk_pp(obj.m_terms[i], m) << "\n";);
if (evaluated && !m.is_true(val)) {
value += obj.m_weights[i];
}
// TBD: check that optimal was not changed.
}
value = obj.m_adjust_value(value);
rational value0 = ms.get_lower();
TRACE("opt", tout << "value " << value << " " << value0 << "\n";);
SASSERT(value == value0);
}
}
}
void context::validate_lex() {
rational r1;
expr_ref val(m);

View file

@ -190,7 +190,7 @@ namespace opt {
virtual void collect_statistics(statistics& stats) const;
virtual proof* get_proof() { return 0; }
virtual void get_labels(svector<symbol> & r);
virtual void get_unsat_core(ptr_vector<expr> & r) {}
virtual void get_unsat_core(ptr_vector<expr> & r);
virtual std::string reason_unknown() const;
virtual void set_reason_unknown(char const* msg) { m_unknown = msg; }
@ -291,6 +291,7 @@ namespace opt {
void validate_lex();
void validate_maxsat(symbol const& id);
void display_benchmark();

View file

@ -57,7 +57,7 @@ namespace opt {
opt_solver::~opt_solver() {
}
void opt_solver::updt_params(params_ref & _p) {
void opt_solver::updt_params(params_ref const & _p) {
opt_params p(_p);
m_dump_benchmarks = p.dump_benchmarks();
m_params.updt_params(_p);
@ -198,6 +198,10 @@ namespace opt {
return m_context.find_mutexes(vars, mutexes);
}
lbool opt_solver::preferred_sat(expr_ref_vector const& asms, vector<expr_ref_vector>& cores) {
return m_context.preferred_sat(asms, cores);
}
/**
@ -379,13 +383,13 @@ namespace opt {
if (typeid(smt::theory_idl) == typeid(opt)) {
smt::theory_idl& th = dynamic_cast<smt::theory_idl&>(opt);
return th.mk_ge(m_fm, v, val.get_rational());
return th.mk_ge(m_fm, v, val);
}
if (typeid(smt::theory_rdl) == typeid(opt) &&
val.get_infinitesimal().is_zero()) {
smt::theory_rdl& th = dynamic_cast<smt::theory_rdl&>(opt);
return th.mk_ge(m_fm, v, val.get_rational());
return th.mk_ge(m_fm, v, val);
}
// difference logic?

View file

@ -88,7 +88,7 @@ namespace opt {
virtual ~opt_solver();
virtual solver* translate(ast_manager& m, params_ref const& p);
virtual void updt_params(params_ref & p);
virtual void updt_params(params_ref const& p);
virtual void collect_param_descrs(param_descrs & r);
virtual void collect_statistics(statistics & st) const;
virtual void assert_expr(expr * t);
@ -107,6 +107,7 @@ namespace opt {
virtual std::ostream& display(std::ostream & out) const;
virtual ast_manager& get_manager() const { return m; }
virtual lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes);
virtual lbool preferred_sat(expr_ref_vector const& asms, vector<expr_ref_vector>& cores);
void set_logic(symbol const& logic);
smt::theory_var add_objective(app* term);

View file

@ -32,64 +32,286 @@ namespace opt {
class wmax : public maxsmt_solver_base {
obj_map<expr, rational> m_weights;
obj_map<expr, expr*> m_keys;
expr_ref_vector m_trail, m_defs;
void reset() {
m_weights.reset();
m_keys.reset();
m_trail.reset();
m_defs.reset();
}
public:
wmax(maxsat_context& c, weights_t& ws, expr_ref_vector const& soft):
maxsmt_solver_base(c, ws, soft) {}
maxsmt_solver_base(c, ws, soft),
m_trail(m),
m_defs(m) {}
virtual ~wmax() {}
lbool operator()() {
TRACE("opt", tout << "weighted maxsat\n";);
scoped_ensure_theory wth(*this);
obj_map<expr, rational> soft;
reset();
lbool is_sat = find_mutexes(soft);
if (is_sat != l_true) {
return is_sat;
}
rational offset = m_lower;
m_upper = offset;
m_upper = m_lower;
bool was_sat = false;
expr_ref_vector disj(m);
expr_ref_vector disj(m), asms(m);
vector<expr_ref_vector> cores;
obj_map<expr, rational>::iterator it = soft.begin(), end = soft.end();
for (; it != end; ++it) {
expr_ref tmp(m);
bool is_true = m_model->eval(it->m_key, tmp) && m.is_true(tmp);
expr* c = wth().assert_weighted(it->m_key, it->m_value, is_true);
if (!is_true) {
expr* c = assert_weighted(wth(), it->m_key, it->m_value);
if (!is_true(it->m_key)) {
disj.push_back(m.mk_not(c));
m_upper += it->m_value;
disj.push_back(c);
}
}
wth().init_min_cost(m_upper - m_lower);
s().assert_expr(mk_or(disj));
trace_bounds("wmax");
while (l_true == is_sat && m_lower < m_upper) {
while (!m.canceled() && m_lower < m_upper) {
//mk_assumptions(asms);
//is_sat = s().preferred_sat(asms, cores);
is_sat = s().check_sat(0, 0);
if (m.canceled()) {
is_sat = l_undef;
}
if (is_sat == l_false) {
break;
}
if (is_sat == l_true) {
if (wth().is_optimal()) {
m_upper = offset + wth().get_min_cost();
m_upper = m_lower + wth().get_cost();
s().get_model(m_model);
}
expr_ref fml = wth().mk_block();
//DEBUG_CODE(verify_cores(cores););
s().assert_expr(fml);
was_sat = true;
}
else {
//DEBUG_CODE(verify_cores(cores););
}
update_cores(wth(), cores);
wth().init_min_cost(m_upper - m_lower);
trace_bounds("wmax");
SASSERT(m_lower <= m_upper);
}
if (was_sat) {
wth().get_assignment(m_assignment);
m_upper = offset + wth().get_min_cost();
}
if (is_sat == l_false && was_sat) {
update_assignment();
if (!m.canceled() && is_sat == l_undef && m_lower == m_upper) {
is_sat = l_true;
}
if (is_sat == l_true) {
if (is_sat == l_false) {
is_sat = l_true;
m_lower = m_upper;
}
TRACE("opt", tout << "min cost: " << m_upper << "\n";);
return is_sat;
}
bool is_true(expr* e) {
expr_ref tmp(m);
return m_model->eval(e, tmp) && m.is_true(tmp);
}
void update_assignment() {
m_assignment.reset();
for (unsigned i = 0; i < m_soft.size(); ++i) {
m_assignment.push_back(is_true(m_soft[i]));
}
}
struct compare_asm {
wmax& max;
compare_asm(wmax& max):max(max) {}
bool operator()(expr* a, expr* b) const {
return max.m_weights[a] > max.m_weights[b];
}
};
void mk_assumptions(expr_ref_vector& asms) {
ptr_vector<expr> _asms;
obj_map<expr, rational>::iterator it = m_weights.begin(), end = m_weights.end();
for (; it != end; ++it) {
_asms.push_back(it->m_key);
}
compare_asm comp(*this);
std::sort(_asms.begin(),_asms.end(), comp);
asms.reset();
for (unsigned i = 0; i < _asms.size(); ++i) {
asms.push_back(m.mk_not(_asms[i]));
}
}
void verify_cores(vector<expr_ref_vector> const& cores) {
for (unsigned i = 0; i < cores.size(); ++i) {
verify_core(cores[i]);
}
}
void verify_core(expr_ref_vector const& core) {
s().push();
s().assert_expr(core);
VERIFY(l_false == s().check_sat(0, 0));
s().pop(1);
}
void update_cores(smt::theory_wmaxsat& th, vector<expr_ref_vector> const& cores) {
obj_hashtable<expr> seen;
bool updated = false;
unsigned min_core_size = UINT_MAX;
for (unsigned i = 0; i < cores.size(); ++i) {
expr_ref_vector const& core = cores[i];
if (core.size() <= 20) {
s().assert_expr(m.mk_not(mk_and(core)));
}
min_core_size = std::min(core.size(), min_core_size);
if (core.size() >= 11) {
continue;
}
bool found = false;
for (unsigned j = 0; !found && j < core.size(); ++j) {
found = seen.contains(core[j]);
}
if (found) {
continue;
}
for (unsigned j = 0; j < core.size(); ++j) {
seen.insert(core[j]);
}
update_core(th, core);
updated = true;
}
// if no core was selected, then take the smallest cores.
for (unsigned i = 0; !updated && i < cores.size(); ++i) {
expr_ref_vector const& core = cores[i];
if (core.size() > min_core_size + 2) {
continue;
}
bool found = false;
for (unsigned j = 0; !found && j < core.size(); ++j) {
found = seen.contains(core[j]);
}
if (found) {
continue;
}
for (unsigned j = 0; j < core.size(); ++j) {
seen.insert(core[j]);
}
update_core(th, core);
}
}
rational remove_negations(smt::theory_wmaxsat& th, expr_ref_vector const& core, ptr_vector<expr>& keys, vector<rational>& weights) {
rational min_weight(-1);
for (unsigned i = 0; i < core.size(); ++i) {
expr* e;
VERIFY(m.is_not(core[i], e));
keys.push_back(m_keys[e]);
rational weight = m_weights[e];
if (i == 0 || weight < min_weight) {
min_weight = weight;
}
weights.push_back(weight);
m_weights.erase(e);
m_keys.erase(e);
th.disable_var(e);
}
for (unsigned i = 0; i < core.size(); ++i) {
rational weight = weights[i];
if (weight > min_weight) {
weight -= min_weight;
assert_weighted(th, keys[i], weight);
}
}
return min_weight;
}
// assert maxres clauses
// assert new core members with value of current model.
// update lower bound
// bounds get re-normalized when solver is invoked.
// each element of core is negated literal from theory_wmaxsat
// disable those literals from th
void update_core(smt::theory_wmaxsat& th, expr_ref_vector const& core) {
ptr_vector<expr> keys;
vector<rational> weights;
rational min_weight = remove_negations(th, core, keys, weights);
max_resolve(th, keys, min_weight);
m_lower += min_weight;
// std::cout << core << " " << min_weight << "\n";
}
void max_resolve(smt::theory_wmaxsat& th, ptr_vector<expr> const& core, rational const& w) {
SASSERT(!core.empty());
expr_ref fml(m), asum(m);
app_ref cls(m), d(m), dd(m);
//
// d_0 := true
// d_i := b_{i-1} and d_{i-1} for i = 1...sz-1
// soft (b_i or !d_i)
// == (b_i or !(!b_{i-1} or d_{i-1}))
// == (b_i or b_0 & b_1 & ... & b_{i-1})
//
// Soft constraint is satisfied if previous soft constraint
// holds or if it is the first soft constraint to fail.
//
// Soundness of this rule can be established using MaxRes
//
for (unsigned i = 1; i < core.size(); ++i) {
expr* b_i = core[i-1];
expr* b_i1 = core[i];
if (i == 1) {
d = to_app(b_i);
}
else if (i == 2) {
d = m.mk_and(b_i, d);
m_trail.push_back(d);
}
else {
dd = mk_fresh_bool("d");
fml = m.mk_implies(dd, d);
s().assert_expr(fml);
m_defs.push_back(fml);
fml = m.mk_implies(dd, b_i);
s().assert_expr(fml);
m_defs.push_back(fml);
fml = m.mk_and(d, b_i);
update_model(dd, fml);
d = dd;
}
cls = m.mk_or(b_i1, d);
m_trail.push_back(cls);
assert_weighted(th, cls, w);
}
}
expr* assert_weighted(smt::theory_wmaxsat& th, expr* key, rational const& w) {
expr* c = th.assert_weighted(key, w);
m_weights.insert(c, w);
m_keys.insert(c, key);
m_trail.push_back(c);
return c;
}
void update_model(expr* def, expr* value) {
expr_ref val(m);
if (m_model && m_model->eval(value, val, true)) {
m_model->register_decl(to_app(def)->get_decl(), val);
}
}
};
maxsmt_solver_base* mk_wmax(maxsat_context& c, weights_t& ws, expr_ref_vector const& soft) {

View file

@ -110,7 +110,7 @@ namespace qe {
imp(ast_manager& m): m(m), a(m) {}
~imp() {}
virtual bool solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) {
bool solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) {
return false;
}

View file

@ -37,7 +37,7 @@ namespace qe {
imp(ast_manager& m):
m(m), dt(m), m_val(m) {}
virtual bool solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) {
bool solve(model& model, app_ref_vector& vars, expr_ref_vector& lits) {
return lift_foreign(vars, lits);
}

View file

@ -29,6 +29,7 @@ Revision History:
#include "model_v2_pp.h"
#include "expr_functors.h"
#include "for_each_expr.h"
#include "model_evaluator.h"
using namespace qe;
@ -125,6 +126,7 @@ class mbp::impl {
th_rewriter m_rw;
ptr_vector<project_plugin> m_plugins;
expr_mark m_visited;
expr_mark m_bool_visited;
void add_plugin(project_plugin* p) {
family_id fid = p->get_family_id();
@ -212,10 +214,12 @@ class mbp::impl {
}
}
void extract_bools(model& model, expr_ref_vector& fmls, expr* fml) {
bool extract_bools(model_evaluator& eval, expr_ref_vector& fmls, expr* fml) {
TRACE("qe", tout << "extract bools: " << mk_pp(fml, m) << "\n";);
ptr_vector<expr> todo;
expr_safe_replace sub(m);
m_visited.reset();
bool found_bool = false;
if (is_app(fml)) {
todo.append(to_app(fml)->get_num_args(), to_app(fml)->get_args());
}
@ -226,16 +230,16 @@ class mbp::impl {
continue;
}
m_visited.mark(e);
if (m.is_bool(e)) {
expr_ref val(m);
VERIFY(model.eval(e, val));
if (m.is_bool(e) && !m.is_true(e) && !m.is_false(e)) {
expr_ref val = eval(e);
TRACE("qe", tout << "found: " << mk_pp(e, m) << "\n";);
if (m.is_true(val)) {
fmls.push_back(e);
}
else {
fmls.push_back(mk_not(m, e));
SASSERT(m.is_true(val) || m.is_false(val));
if (!m_bool_visited.is_marked(e)) {
fmls.push_back(m.is_true(val) ? e : mk_not(m, e));
}
sub.insert(e, val);
m_bool_visited.mark(e);
found_bool = true;
}
else if (is_app(e)) {
todo.append(to_app(e)->get_num_args(), to_app(e)->get_args());
@ -244,6 +248,14 @@ class mbp::impl {
TRACE("qe", tout << "expression not handled " << mk_pp(e, m) << "\n";);
}
}
if (found_bool) {
expr_ref tmp(m);
sub(fml, tmp);
expr_ref val = eval(tmp);
SASSERT(m.is_true(val) || m.is_false(val));
fmls.push_back(m.is_true(val) ? tmp : mk_not(m, tmp));
}
return found_bool;
}
void project_bools(model& model, app_ref_vector& vars, expr_ref_vector& fmls) {
@ -294,6 +306,8 @@ public:
void extract_literals(model& model, expr_ref_vector& fmls) {
expr_ref val(m);
model_evaluator eval(model);
TRACE("qe", tout << fmls << "\n";);
for (unsigned i = 0; i < fmls.size(); ++i) {
expr* fml = fmls[i].get(), *nfml, *f1, *f2, *f3;
SASSERT(m.is_bool(fml));
@ -303,7 +317,7 @@ public:
}
else if (m.is_or(fml)) {
for (unsigned j = 0; j < to_app(fml)->get_num_args(); ++j) {
VERIFY (model.eval(to_app(fml)->get_arg(j), val));
val = eval(to_app(fml)->get_arg(j));
if (m.is_true(val)) {
fmls[i] = to_app(fml)->get_arg(j);
--i;
@ -316,7 +330,7 @@ public:
project_plugin::erase(fmls, i);
}
else if (m.is_iff(fml, f1, f2) || (m.is_not(fml, nfml) && m.is_xor(nfml, f1, f2))) {
VERIFY (model.eval(f1, val));
val = eval(f1);
if (m.is_false(val)) {
f1 = mk_not(m, f1);
f2 = mk_not(m, f2);
@ -326,7 +340,7 @@ public:
--i;
}
else if (m.is_implies(fml, f1, f2)) {
VERIFY (model.eval(f2, val));
val = eval(f2);
if (m.is_true(val)) {
fmls[i] = f2;
}
@ -336,7 +350,7 @@ public:
--i;
}
else if (m.is_ite(fml, f1, f2, f3)) {
VERIFY (model.eval(f1, val));
val = eval(f1);
if (m.is_true(val)) {
project_plugin::push_back(fmls, f1);
project_plugin::push_back(fmls, f2);
@ -353,7 +367,7 @@ public:
}
else if (m.is_not(fml, nfml) && m.is_and(nfml)) {
for (unsigned j = 0; j < to_app(nfml)->get_num_args(); ++j) {
VERIFY (model.eval(to_app(nfml)->get_arg(j), val));
val = eval(to_app(nfml)->get_arg(j));
if (m.is_false(val)) {
fmls[i] = mk_not(m, to_app(nfml)->get_arg(j));
--i;
@ -368,7 +382,7 @@ public:
project_plugin::erase(fmls, i);
}
else if ((m.is_not(fml, nfml) && m.is_iff(nfml, f1, f2)) || m.is_xor(fml, f1, f2)) {
VERIFY (model.eval(f1, val));
val = eval(f1);
if (m.is_true(val)) {
f2 = mk_not(m, f2);
}
@ -385,7 +399,7 @@ public:
project_plugin::erase(fmls, i);
}
else if (m.is_not(fml, nfml) && m.is_ite(nfml, f1, f2, f3)) {
VERIFY (model.eval(f1, val));
val = eval(f1);
if (m.is_true(val)) {
project_plugin::push_back(fmls, f1);
project_plugin::push_back(fmls, mk_not(m, f2));
@ -397,14 +411,19 @@ public:
project_plugin::erase(fmls, i);
}
else if (m.is_not(fml, nfml)) {
extract_bools(model, fmls, nfml);
if (extract_bools(eval, fmls, nfml)) {
project_plugin::erase(fmls, i);
}
}
else {
extract_bools(model, fmls, fml);
if (extract_bools(eval, fmls, fml)) {
project_plugin::erase(fmls, i);
}
// TBD other Boolean operations.
}
}
m_visited.reset();
TRACE("qe", tout << fmls << "\n";);
m_bool_visited.reset();
}
impl(ast_manager& m):m(m), m_rw(m) {

View file

@ -909,6 +909,7 @@ namespace qe {
num_scopes = 2;
}
else {
if (level.max() + 2 > m_level) return false;
SASSERT(level.max() + 2 <= m_level);
num_scopes = m_level - level.max();
SASSERT(num_scopes >= 2);

View file

@ -2917,6 +2917,7 @@ namespace sat {
++max_weight;
out << "p wcnf " << num_vars() << " " << num_clauses() + sz << " " << max_weight << "\n";
out << "c soft " << sz << "\n";
for (unsigned i = 0; i < m_trail.size(); i++) {
out << max_weight << " " << dimacs_lit(m_trail[i]) << " 0\n";
@ -2940,9 +2941,9 @@ namespace sat {
clause_vector::const_iterator end = cs.end();
for (; it != end; ++it) {
clause const & c = *(*it);
unsigned sz = c.size();
unsigned clsz = c.size();
out << max_weight << " ";
for (unsigned j = 0; j < sz; j++)
for (unsigned j = 0; j < clsz; j++)
out << dimacs_lit(c[j]) << " ";
out << "0\n";
}
@ -2950,6 +2951,7 @@ namespace sat {
for (unsigned i = 0; i < sz; ++i) {
out << weights[i] << " " << lits[i] << " 0\n";
}
out.flush();
}

View file

@ -115,10 +115,18 @@ public:
if (weights != 0) {
for (unsigned i = 0; i < sz; ++i) m_weights.push_back(weights[i]);
}
init_preprocess();
m_solver.pop_to_base_level();
dep2asm_t dep2asm;
expr_ref_vector asms(m);
for (unsigned i = 0; i < sz; ++i) {
expr_ref a(m.mk_fresh_const("s", m.mk_bool_sort()), m);
expr_ref fml(m.mk_implies(a, assumptions[i]), m);
assert_expr(fml);
asms.push_back(a);
}
VERIFY(l_true == internalize_formulas());
VERIFY(l_true == internalize_assumptions(sz, assumptions, dep2asm));
VERIFY(l_true == internalize_assumptions(sz, asms.c_ptr(), dep2asm));
svector<unsigned> nweights;
for (unsigned i = 0; i < m_asms.size(); ++i) {
nweights.push_back((unsigned) m_weights[i]);

View file

@ -174,6 +174,7 @@ struct goal2sat::imp {
switch (to_app(t)->get_decl_kind()) {
case OP_NOT:
case OP_OR:
case OP_AND:
case OP_IFF:
m_frame_stack.push_back(frame(to_app(t), root, sign, 0));
return false;
@ -185,7 +186,6 @@ struct goal2sat::imp {
}
convert_atom(t, root, sign);
return true;
case OP_AND:
case OP_XOR:
case OP_IMPLIES:
case OP_DISTINCT: {
@ -215,8 +215,8 @@ struct goal2sat::imp {
}
else {
mk_clause(m_result_stack.size(), m_result_stack.c_ptr());
m_result_stack.reset();
}
m_result_stack.reset();
}
else {
SASSERT(num <= m_result_stack.size());
@ -240,6 +240,48 @@ struct goal2sat::imp {
}
}
void convert_and(app * t, bool root, bool sign) {
TRACE("goal2sat", tout << "convert_and:\n" << mk_ismt2_pp(t, m) << "\n";);
unsigned num = t->get_num_args();
if (root) {
if (sign) {
for (unsigned i = 0; i < num; ++i) {
m_result_stack[i].neg();
}
}
else {
for (unsigned i = 0; i < num; ++i) {
mk_clause(m_result_stack[i]);
}
}
m_result_stack.reset();
}
else {
SASSERT(num <= m_result_stack.size());
sat::bool_var k = m_solver.mk_var();
sat::literal l(k, false);
m_cache.insert(t, l);
// l => /\ lits
sat::literal * lits = m_result_stack.end() - num;
for (unsigned i = 0; i < num; i++) {
mk_clause(~l, lits[i]);
}
// /\ lits => l
for (unsigned i = 0; i < num; ++i) {
m_result_stack[m_result_stack.size() - num + i].neg();
}
m_result_stack.push_back(l);
lits = m_result_stack.end() - num - 1;
mk_clause(num+1, lits);
unsigned old_sz = m_result_stack.size() - num - 1;
m_result_stack.shrink(old_sz);
if (sign)
l.neg();
m_result_stack.push_back(l);
}
}
void convert_ite(app * n, bool root, bool sign) {
unsigned sz = m_result_stack.size();
SASSERT(sz >= 3);
@ -316,6 +358,9 @@ struct goal2sat::imp {
case OP_OR:
convert_or(t, root, sign);
break;
case OP_AND:
convert_and(t, root, sign);
break;
case OP_ITE:
convert_ite(t, root, sign);
break;
@ -456,7 +501,6 @@ struct unsupported_bool_proc {
void operator()(app * n) {
if (n->get_family_id() == m.get_basic_family_id()) {
switch (n->get_decl_kind()) {
case OP_AND:
case OP_XOR:
case OP_IMPLIES:
case OP_DISTINCT:

View file

@ -31,7 +31,7 @@ arith_factory::arith_factory(ast_manager & m):
arith_factory::~arith_factory() {
}
app * arith_factory::mk_value(rational const & val, bool is_int) {
app * arith_factory::mk_num_value(rational const & val, bool is_int) {
return numeral_factory::mk_value(val, is_int ? m_util.mk_int() : m_util.mk_real());
}
@ -47,6 +47,6 @@ app * bv_factory::mk_value_core(rational const & val, sort * s) {
return m_util.mk_numeral(val, s);
}
app * bv_factory::mk_value(rational const & val, unsigned bv_size) {
app * bv_factory::mk_num_value(rational const & val, unsigned bv_size) {
return numeral_factory::mk_value(val, m_util.mk_sort(bv_size));
}

View file

@ -38,7 +38,7 @@ public:
arith_factory(ast_manager & m);
virtual ~arith_factory();
app * mk_value(rational const & val, bool is_int);
app * mk_num_value(rational const & val, bool is_int);
};
class bv_factory : public numeral_factory {
@ -50,7 +50,7 @@ public:
bv_factory(ast_manager & m);
virtual ~bv_factory();
app * mk_value(rational const & val, unsigned bv_size);
app * mk_num_value(rational const & val, unsigned bv_size);
};
#endif /* NUMERAL_FACTORY_H_ */

View file

@ -56,36 +56,7 @@ namespace smt {
s.insert(lit.var());
}
else {
b_justification js = get_justification(lit.var());
switch (js.get_kind()) {
case b_justification::CLAUSE: {
clause * cls = js.get_clause();
if (!cls) break;
unsigned num_lits = cls->get_num_literals();
for (unsigned j = 0; j < num_lits; ++j) {
literal lit2 = cls->get_literal(j);
if (lit2.var() != lit.var()) {
s |= m_antecedents.find(lit2.var());
}
}
break;
}
case b_justification::BIN_CLAUSE: {
s |= m_antecedents.find(js.get_literal().var());
break;
}
case b_justification::AXIOM: {
break;
}
case b_justification::JUSTIFICATION: {
literal_vector literals;
m_conflict_resolution->justification2literals(js.get_justification(), literals);
for (unsigned j = 0; j < literals.size(); ++j) {
s |= m_antecedents.find(literals[j].var());
}
break;
}
}
justify(lit, s);
}
m_antecedents.insert(lit.var(), s);
TRACE("context", display_literal_verbose(tout, lit);
@ -122,6 +93,39 @@ namespace smt {
}
}
void context::justify(literal lit, index_set& s) {
b_justification js = get_justification(lit.var());
switch (js.get_kind()) {
case b_justification::CLAUSE: {
clause * cls = js.get_clause();
if (!cls) break;
unsigned num_lits = cls->get_num_literals();
for (unsigned j = 0; j < num_lits; ++j) {
literal lit2 = cls->get_literal(j);
if (lit2.var() != lit.var()) {
s |= m_antecedents.find(lit2.var());
}
}
break;
}
case b_justification::BIN_CLAUSE: {
s |= m_antecedents.find(js.get_literal().var());
break;
}
case b_justification::AXIOM: {
break;
}
case b_justification::JUSTIFICATION: {
literal_vector literals;
m_conflict_resolution->justification2literals(js.get_justification(), literals);
for (unsigned j = 0; j < literals.size(); ++j) {
s |= m_antecedents.find(literals[j].var());
}
break;
}
}
}
void context::extract_fixed_consequences(unsigned& start, obj_map<expr, expr*>& vars, index_set const& assumptions, expr_ref_vector& conseq) {
pop_to_search_lvl();
SASSERT(!inconsistent());
@ -369,6 +373,142 @@ namespace smt {
<< ")\n";
}
void context::extract_cores(expr_ref_vector const& asms, vector<expr_ref_vector>& cores, unsigned& min_core_size) {
index_set _asms, _nasms;
u_map<expr*> var2expr;
for (unsigned i = 0; i < asms.size(); ++i) {
literal lit = get_literal(asms[i]);
_asms.insert(lit.index());
_nasms.insert((~lit).index());
var2expr.insert(lit.var(), asms[i]);
}
m_antecedents.reset();
literal_vector const& lits = assigned_literals();
for (unsigned i = 0; i < lits.size(); ++i) {
literal lit = lits[i];
index_set s;
if (_asms.contains(lit.index())) {
s.insert(lit.var());
}
else {
justify(lit, s);
}
m_antecedents.insert(lit.var(), s);
if (_nasms.contains(lit.index())) {
expr_ref_vector core(m_manager);
index_set::iterator it = s.begin(), end = s.end();
for (; it != end; ++it) {
core.push_back(var2expr[*it]);
}
core.push_back(var2expr[lit.var()]);
cores.push_back(core);
min_core_size = std::min(min_core_size, core.size());
}
}
}
void context::preferred_sat(literal_vector& lits) {
bool retry = true;
while (retry) {
retry = false;
for (unsigned i = 0; i < lits.size(); ++i) {
literal lit = lits[i];
if (lit == null_literal || get_assignment(lit) != l_undef) {
continue;
}
push_scope();
assign(lit, b_justification::mk_axiom(), true);
while (!propagate()) {
lits[i] = null_literal;
retry = true;
if (!resolve_conflict() || inconsistent()) {
SASSERT(inconsistent());
return;
}
}
}
}
}
void context::display_partial_assignment(std::ostream& out, expr_ref_vector const& asms, unsigned min_core_size) {
unsigned num_true = 0, num_false = 0, num_undef = 0;
for (unsigned i = 0; i < asms.size(); ++i) {
literal lit = get_literal(asms[i]);
if (get_assignment(lit) == l_false) {
++num_false;
}
if (get_assignment(lit) == l_true) {
++num_true;
}
if (get_assignment(lit) == l_undef) {
++num_undef;
}
}
out << "(smt.preferred-sat true: " << num_true << " false: " << num_false << " undef: " << num_undef << " min core: " << min_core_size << ")\n";
}
lbool context::preferred_sat(expr_ref_vector const& asms, vector<expr_ref_vector>& cores) {
pop_to_base_lvl();
cores.reset();
setup_context(false);
internalize_assertions();
if (m_asserted_formulas.inconsistent() || inconsistent()) {
return l_false;
}
scoped_mk_model smk(*this);
init_search();
flet<bool> l(m_searching, true);
unsigned level = m_scope_lvl;
unsigned min_core_size = UINT_MAX;
lbool is_sat = l_true;
unsigned num_restarts = 0;
while (true) {
if (m_manager.canceled()) {
is_sat = l_undef;
break;
}
literal_vector lits;
for (unsigned i = 0; i < asms.size(); ++i) {
lits.push_back(get_literal(asms[i]));
}
preferred_sat(lits);
if (inconsistent()) {
SASSERT(m_scope_lvl == level);
is_sat = l_false;
break;
}
extract_cores(asms, cores, min_core_size);
IF_VERBOSE(1, display_partial_assignment(verbose_stream(), asms, min_core_size););
if (min_core_size <= 10) {
is_sat = l_undef;
break;
}
is_sat = bounded_search();
if (!restart(is_sat, level)) {
break;
}
++num_restarts;
if (num_restarts >= min_core_size) {
is_sat = l_undef;
while (num_restarts <= 10*min_core_size) {
is_sat = bounded_search();
if (!restart(is_sat, level)) {
break;
}
++num_restarts;
}
break;
}
}
end_search();
return check_finalize(is_sat);
}
struct neg_literal {
unsigned negate(unsigned i) {
return (~to_literal(i)).index();

View file

@ -1111,6 +1111,8 @@ namespace smt {
if (r1 == r2) {
TRACE("add_diseq_inconsistent", tout << "add_diseq #" << n1->get_owner_id() << " #" << n2->get_owner_id() << " inconsistency, scope_lvl: " << m_scope_lvl << "\n";);
//return false;
theory_id t1 = r1->m_th_var_list.get_th_id();
if (t1 == null_theory_id) return false;
return get_theory(t1)->use_diseqs();
@ -3293,19 +3295,6 @@ namespace smt {
m_num_conflicts_since_restart = 0;
}
struct context::scoped_mk_model {
context & m_ctx;
scoped_mk_model(context & ctx):m_ctx(ctx) {
m_ctx.m_proto_model = 0;
m_ctx.m_model = 0;
}
~scoped_mk_model() {
if (m_ctx.m_proto_model.get() != 0) {
m_ctx.m_model = m_ctx.m_proto_model->mk_model();
m_ctx.m_proto_model = 0; // proto_model is not needed anymore.
}
}
};
lbool context::search() {
#ifndef _EXTERNAL_RELEASE
@ -3333,79 +3322,10 @@ namespace smt {
TRACE("search_bug", tout << "status: " << status << ", inconsistent: " << inconsistent() << "\n";);
TRACE("assigned_literals_per_lvl", display_num_assigned_literals_per_lvl(tout);
tout << ", num_assigned: " << m_assigned_literals.size() << "\n";);
if (m_last_search_failure != OK) {
if (status != l_false) {
// build candidate model before returning
mk_proto_model(status);
// status = l_undef;
}
if (!restart(status, curr_lvl)) {
break;
}
bool force_restart = false;
if (status == l_false) {
break;
}
else if (status == l_true) {
SASSERT(!inconsistent());
mk_proto_model(l_true);
// possible outcomes DONE l_true, DONE l_undef, CONTINUE
quantifier_manager::check_model_result cmr = m_qmanager->check_model(m_proto_model.get(), m_model_generator->get_root2value());
if (cmr == quantifier_manager::SAT) {
// done
break;
}
if (cmr == quantifier_manager::UNKNOWN) {
IF_VERBOSE(1, verbose_stream() << "(smt.giveup quantifiers)\n";);
// giving up
m_last_search_failure = QUANTIFIERS;
status = l_undef;
break;
}
status = l_undef;
force_restart = true;
}
SASSERT(status == l_undef);
inc_limits();
if (force_restart || !m_fparams.m_restart_adaptive || m_agility < m_fparams.m_restart_agility_threshold) {
SASSERT(!inconsistent());
IF_VERBOSE(1, verbose_stream() << "(smt.restarting :propagations " << m_stats.m_num_propagations
<< " :decisions " << m_stats.m_num_decisions
<< " :conflicts " << m_stats.m_num_conflicts << " :restart " << m_restart_threshold;
if (m_fparams.m_restart_strategy == RS_IN_OUT_GEOMETRIC) {
verbose_stream() << " :restart-outer " << m_restart_outer_threshold;
}
if (m_fparams.m_restart_adaptive) {
verbose_stream() << " :agility " << m_agility;
}
verbose_stream() << ")" << std::endl; verbose_stream().flush(););
// execute the restart
m_stats.m_num_restarts++;
if (m_scope_lvl > curr_lvl) {
pop_scope(m_scope_lvl - curr_lvl);
SASSERT(at_search_level());
}
ptr_vector<theory>::iterator it = m_theory_set.begin();
ptr_vector<theory>::iterator end = m_theory_set.end();
for (; it != end && !inconsistent(); ++it)
(*it)->restart_eh();
TRACE("mbqi_bug_detail", tout << "before instantiating quantifiers...\n";);
if (!inconsistent()) {
m_qmanager->restart_eh();
}
if (inconsistent()) {
VERIFY(!resolve_conflict());
status = l_false;
break;
}
}
if (m_fparams.m_simplify_clauses)
simplify_clauses();
if (m_fparams.m_lemma_gc_strategy == LGC_AT_RESTART)
del_inactive_lemmas();
}
TRACE("search_lite", tout << "status: " << status << "\n";);
@ -3419,6 +3339,80 @@ namespace smt {
end_search();
return status;
}
bool context::restart(lbool& status, unsigned curr_lvl) {
if (m_last_search_failure != OK) {
if (status != l_false) {
// build candidate model before returning
mk_proto_model(status);
// status = l_undef;
}
return false;
}
if (status == l_false) {
return false;
}
if (status == l_true) {
SASSERT(!inconsistent());
mk_proto_model(l_true);
// possible outcomes DONE l_true, DONE l_undef, CONTINUE
quantifier_manager::check_model_result cmr = m_qmanager->check_model(m_proto_model.get(), m_model_generator->get_root2value());
if (cmr == quantifier_manager::SAT) {
// done
status = l_true;
return false;
}
if (cmr == quantifier_manager::UNKNOWN) {
IF_VERBOSE(1, verbose_stream() << "(smt.giveup quantifiers)\n";);
// giving up
m_last_search_failure = QUANTIFIERS;
status = l_undef;
return false;
}
}
inc_limits();
if (status == l_true || !m_fparams.m_restart_adaptive || m_agility < m_fparams.m_restart_agility_threshold) {
SASSERT(!inconsistent());
IF_VERBOSE(1, verbose_stream() << "(smt.restarting :propagations " << m_stats.m_num_propagations
<< " :decisions " << m_stats.m_num_decisions
<< " :conflicts " << m_stats.m_num_conflicts << " :restart " << m_restart_threshold;
if (m_fparams.m_restart_strategy == RS_IN_OUT_GEOMETRIC) {
verbose_stream() << " :restart-outer " << m_restart_outer_threshold;
}
if (m_fparams.m_restart_adaptive) {
verbose_stream() << " :agility " << m_agility;
}
verbose_stream() << ")" << std::endl; verbose_stream().flush(););
// execute the restart
m_stats.m_num_restarts++;
if (m_scope_lvl > curr_lvl) {
pop_scope(m_scope_lvl - curr_lvl);
SASSERT(at_search_level());
}
ptr_vector<theory>::iterator it = m_theory_set.begin();
ptr_vector<theory>::iterator end = m_theory_set.end();
for (; it != end && !inconsistent(); ++it)
(*it)->restart_eh();
TRACE("mbqi_bug_detail", tout << "before instantiating quantifiers...\n";);
if (!inconsistent()) {
m_qmanager->restart_eh();
}
if (inconsistent()) {
VERIFY(!resolve_conflict());
status = l_false;
return false;
}
}
if (m_fparams.m_simplify_clauses)
simplify_clauses();
if (m_fparams.m_lemma_gc_strategy == LGC_AT_RESTART)
del_inactive_lemmas();
status = l_undef;
return true;
}
void context::tick(unsigned & counter) const {
counter++;

View file

@ -200,7 +200,20 @@ namespace smt {
model_ref m_model;
std::string m_unknown;
void mk_proto_model(lbool r);
struct scoped_mk_model;
struct scoped_mk_model {
context & m_ctx;
scoped_mk_model(context & ctx):m_ctx(ctx) {
m_ctx.m_proto_model = 0;
m_ctx.m_model = 0;
}
~scoped_mk_model() {
if (m_ctx.m_proto_model.get() != 0) {
m_ctx.m_model = m_ctx.m_proto_model->mk_model();
m_ctx.m_proto_model = 0; // proto_model is not needed anymore.
}
}
};
// -----------------------------------
//
@ -234,7 +247,6 @@ namespace smt {
return m_params;
}
bool get_cancel_flag() { return !m_manager.limit().inc(); }
region & get_region() {
@ -1056,6 +1068,8 @@ namespace smt {
void inc_limits();
bool restart(lbool& status, unsigned curr_lvl);
void tick(unsigned & counter) const;
lbool bounded_search();
@ -1367,6 +1381,13 @@ namespace smt {
void validate_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars,
expr_ref_vector const& conseq, expr_ref_vector const& unfixed);
void justify(literal lit, index_set& s);
void extract_cores(expr_ref_vector const& asms, vector<expr_ref_vector>& cores, unsigned& min_core_size);
void preferred_sat(literal_vector& literals);
void display_partial_assignment(std::ostream& out, expr_ref_vector const& asms, unsigned min_core_size);
public:
context(ast_manager & m, smt_params & fp, params_ref const & p = params_ref());
@ -1410,6 +1431,8 @@ namespace smt {
lbool get_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars, expr_ref_vector& conseq, expr_ref_vector& unfixed);
lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes);
lbool preferred_sat(expr_ref_vector const& asms, vector<expr_ref_vector>& cores);
lbool setup_and_check(bool reset_cancel = true);

View file

@ -322,6 +322,9 @@ namespace smt {
bool context::check_th_diseq_propagation() const {
TRACE("check_th_diseq_propagation", tout << "m_propagated_th_diseqs.size() " << m_propagated_th_diseqs.size() << "\n";);
int num = get_num_bool_vars();
if (inconsistent()) {
return true;
}
for (bool_var v = 0; v < num; v++) {
if (has_enode(v)) {
enode * n = bool_var2enode(v);

View file

@ -32,7 +32,7 @@ namespace smt {
return static_cast<unsigned>(acc / m_lemmas.size());
}
void acc_num_occs(clause * cls, unsigned_vector & lit2num_occs) {
static void acc_num_occs(clause * cls, unsigned_vector & lit2num_occs) {
unsigned num_lits = cls->get_num_literals();
for (unsigned i = 0; i < num_lits; i++) {
literal l = cls->get_literal(i);
@ -40,7 +40,7 @@ namespace smt {
}
}
void acc_num_occs(clause_vector const & v, unsigned_vector & lit2num_occs) {
static void acc_num_occs(clause_vector const & v, unsigned_vector & lit2num_occs) {
clause_vector::const_iterator it = v.begin();
clause_vector::const_iterator end = v.end();
for (; it != end; ++it)
@ -79,7 +79,7 @@ namespace smt {
out << (m_assigned_literals.size() - n) << "]";
}
void acc_var_num_occs(clause * cls, unsigned_vector & var2num_occs) {
static void acc_var_num_occs(clause * cls, unsigned_vector & var2num_occs) {
unsigned num_lits = cls->get_num_literals();
for (unsigned i = 0; i < num_lits; i++) {
literal l = cls->get_literal(i);
@ -87,7 +87,7 @@ namespace smt {
}
}
void acc_var_num_occs(clause_vector const & v, unsigned_vector & var2num_occs) {
static void acc_var_num_occs(clause_vector const & v, unsigned_vector & var2num_occs) {
clause_vector::const_iterator it = v.begin();
clause_vector::const_iterator end = v.end();
for (; it != end; ++it)
@ -114,7 +114,7 @@ namespace smt {
out << "\n";
}
void acc_var_num_min_occs(clause * cls, unsigned_vector & var2num_min_occs) {
static void acc_var_num_min_occs(clause * cls, unsigned_vector & var2num_min_occs) {
unsigned num_lits = cls->get_num_literals();
bool_var min_var = cls->get_literal(0).var();
for (unsigned i = 1; i < num_lits; i++) {
@ -125,7 +125,7 @@ namespace smt {
var2num_min_occs[min_var]++;
}
void acc_var_num_min_occs(clause_vector const & v, unsigned_vector & var2num_min_occs) {
static void acc_var_num_min_occs(clause_vector const & v, unsigned_vector & var2num_min_occs) {
clause_vector::const_iterator it = v.begin();
clause_vector::const_iterator end = v.end();
for (; it != end; ++it)

View file

@ -335,7 +335,7 @@ namespace smt {
}
}
bool find_arg(app * n, expr * t, expr * & other) {
static bool find_arg(app * n, expr * t, expr * & other) {
SASSERT(n->get_num_args() == 2);
if (n->get_arg(0) == t) {
other = n->get_arg(1);
@ -348,7 +348,7 @@ namespace smt {
return false;
}
bool check_args(app * n, expr * t1, expr * t2) {
static bool check_args(app * n, expr * t1, expr * t2) {
SASSERT(n->get_num_args() == 2);
return (n->get_arg(0) == t1 && n->get_arg(1) == t2) || (n->get_arg(1) == t1 && n->get_arg(0) == t2);
}

View file

@ -115,6 +115,11 @@ namespace smt {
return m_kernel.get_consequences(assumptions, vars, conseq, unfixed);
}
lbool preferred_sat(expr_ref_vector const& asms, vector<expr_ref_vector>& cores) {
return m_kernel.preferred_sat(asms, cores);
}
lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes) {
return m_kernel.find_mutexes(vars, mutexes);
}
@ -282,6 +287,10 @@ namespace smt {
return m_imp->get_consequences(assumptions, vars, conseq, unfixed);
}
lbool kernel::preferred_sat(expr_ref_vector const& asms, vector<expr_ref_vector>& cores) {
return m_imp->preferred_sat(asms, cores);
}
lbool kernel::find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes) {
return m_imp->find_mutexes(vars, mutexes);
}

View file

@ -133,11 +133,16 @@ namespace smt {
lbool get_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars,
expr_ref_vector& conseq, expr_ref_vector& unfixed);
/*
/**
\brief find mutually exclusive variables.
*/
lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes);
/**
\brief Preferential SAT.
*/
lbool preferred_sat(expr_ref_vector const& asms, vector<expr_ref_vector>& cores);
/**
\brief Return the model associated with the last check command.
*/

View file

@ -363,9 +363,6 @@ namespace smt {
}
}
struct scoped_set_relevancy {
};
bool model_checker::check(proto_model * md, obj_map<enode, app *> const & root2value) {
SASSERT(md != 0);
m_root2value = &root2value;

View file

@ -498,7 +498,7 @@ namespace smt {
m_bvsimp = static_cast<bv_simplifier_plugin*>(s.get_plugin(m.mk_family_id("bv")));
}
~auf_solver() {
virtual ~auf_solver() {
flush_nodes();
reset_eval_cache();
}

View file

@ -188,7 +188,7 @@ namespace smt {
}
}
void check_no_arithmetic(static_features const & st, char const * logic) {
static void check_no_arithmetic(static_features const & st, char const * logic) {
if (st.m_num_arith_ineqs > 0 || st.m_num_arith_terms > 0 || st.m_num_arith_eqs > 0)
throw default_exception("Benchmark constains arithmetic, but specified loging does not support it.");
}
@ -231,21 +231,21 @@ namespace smt {
(st.m_num_arith_eqs + st.m_num_arith_ineqs) > st.m_num_uninterpreted_constants * 9;
}
bool is_in_diff_logic(static_features const & st) {
static bool is_in_diff_logic(static_features const & st) {
return
st.m_num_arith_eqs == st.m_num_diff_eqs &&
st.m_num_arith_terms == st.m_num_diff_terms &&
st.m_num_arith_ineqs == st.m_num_diff_ineqs;
}
bool is_diff_logic(static_features const & st) {
static bool is_diff_logic(static_features const & st) {
return
is_in_diff_logic(st) &&
(st.m_num_diff_ineqs > 0 || st.m_num_diff_eqs > 0 || st.m_num_diff_terms > 0)
;
}
void check_no_uninterpreted_functions(static_features const & st, char const * logic) {
static void check_no_uninterpreted_functions(static_features const & st, char const * logic) {
if (st.m_num_uninterpreted_functions != 0)
throw default_exception("Benchmark contains uninterpreted function symbols, but specified logic does not support them.");
}

View file

@ -1080,7 +1080,7 @@ namespace smt {
virtual inf_eps_rational<inf_rational> maximize(theory_var v, expr_ref& blocker, bool& has_shared);
virtual inf_eps_rational<inf_rational> value(theory_var v);
virtual theory_var add_objective(app* term);
virtual expr_ref mk_ge(filter_model_converter& fm, theory_var v, inf_numeral const& val);
expr_ref mk_ge(filter_model_converter& fm, theory_var v, inf_numeral const& val);
void enable_record_conflict(expr* bound);
void record_conflict(unsigned num_lits, literal const * lits,
unsigned num_eqs, enode_pair const * eqs,

View file

@ -417,8 +417,8 @@ namespace smt {
template<typename Ext>
void theory_arith<Ext>::atom::display(theory_arith<Ext> const& th, std::ostream& out) const {
literal l(get_bool_var(), !m_is_true);
out << "v" << bound::get_var() << " " << bound::get_bound_kind() << " " << get_k() << " ";
out << l << ":";
// out << "v" << bound::get_var() << " " << bound::get_bound_kind() << " " << get_k() << " ";
// out << l << ":";
th.get_context().display_detailed_literal(out, l);
}

View file

@ -1069,7 +1069,7 @@ namespace smt {
template<typename Ext>
void theory_arith<Ext>::flush_bound_axioms() {
CTRACE("arith", !m_new_atoms.empty(), tout << "flush bound axioms\n";);
CTRACE("arith_verbose", !m_new_atoms.empty(), tout << "flush bound axioms\n";);
while (!m_new_atoms.empty()) {
ptr_vector<atom> atoms;
@ -1084,7 +1084,7 @@ namespace smt {
--i;
}
}
CTRACE("arith", !atoms.empty(),
CTRACE("arith", atoms.size() > 1,
for (unsigned i = 0; i < atoms.size(); ++i) {
atoms[i]->display(*this, tout); tout << "\n";
});
@ -1292,7 +1292,7 @@ namespace smt {
template<typename Ext>
void theory_arith<Ext>::assign_eh(bool_var v, bool is_true) {
TRACE("arith", tout << "p" << v << " := " << (is_true?"true":"false") << "\n";);
TRACE("arith_verbose", tout << "p" << v << " := " << (is_true?"true":"false") << "\n";);
atom * a = get_bv2a(v);
if (!a) return;
SASSERT(get_context().get_assignment(a->get_bool_var()) != l_undef);
@ -3043,12 +3043,14 @@ namespace smt {
m_stats.m_conflicts++;
m_num_conflicts++;
TRACE("arith_conflict",
tout << "scope: " << ctx.get_scope_level() << "\n";
for (unsigned i = 0; i < num_literals; i++) {
ctx.display_detailed_literal(tout, lits[i]);
tout << " ";
if (coeffs_enabled()) {
tout << "bound: " << bounds.lit_coeffs()[i] << "\n";
}
tout << "\n";
}
for (unsigned i = 0; i < num_eqs; i++) {
tout << "#" << eqs[i].first->get_owner_id() << "=#" << eqs[i].second->get_owner_id() << " ";
@ -3229,7 +3231,7 @@ namespace smt {
TRACE("arith", tout << "Truncating non-integer value. This is possible for non-linear constraints v" << v << " " << num << "\n";);
num = floor(num);
}
return alloc(expr_wrapper_proc, m_factory->mk_value(num, m_util.is_int(var2expr(v))));
return alloc(expr_wrapper_proc, m_factory->mk_num_value(num, m_util.is_int(var2expr(v))));
}
// -----------------------------------

View file

@ -1583,7 +1583,7 @@ namespace smt {
#endif
get_fixed_value(v, val);
SASSERT(r);
return alloc(expr_wrapper_proc, m_factory->mk_value(val, get_bv_size(v)));
return alloc(expr_wrapper_proc, m_factory->mk_num_value(val, get_bv_size(v)));
}
void theory_bv::display_var(std::ostream & out, theory_var v) const {

View file

@ -198,7 +198,7 @@ namespace smt {
void del_vars(unsigned old_num_vars);
void init_model();
bool internalize_objective(expr * n, rational const& m, rational& r, objective_term & objective);
expr_ref mk_ineq(theory_var v, inf_rational const& val, bool is_strict);
expr_ref mk_ineq(theory_var v, inf_eps const& val, bool is_strict);
#ifdef Z3DEBUG
bool check_vector_sizes() const;
bool check_matrix() const;
@ -270,8 +270,8 @@ namespace smt {
virtual inf_eps_rational<inf_rational> maximize(theory_var v, expr_ref& blocker, bool& has_shared);
virtual inf_eps_rational<inf_rational> value(theory_var v);
virtual theory_var add_objective(app* term);
virtual expr_ref mk_gt(theory_var v, inf_rational const& val);
virtual expr_ref mk_ge(filter_model_converter& fm, theory_var v, inf_rational const& val);
virtual expr_ref mk_gt(theory_var v, inf_eps const& val);
expr_ref mk_ge(filter_model_converter& fm, theory_var v, inf_eps const& val);
// -----------------------------------
//

View file

@ -828,7 +828,7 @@ namespace smt {
SASSERT(v != null_theory_var);
numeral const & val = m_assignment[v];
rational num = val.get_rational().to_rational() + m_epsilon * val.get_infinitesimal().to_rational();
return alloc(expr_wrapper_proc, m_factory->mk_value(num, is_int(v)));
return alloc(expr_wrapper_proc, m_factory->mk_num_value(num, is_int(v)));
}
// TBD: code is common to both sparse and dense difference logic solvers.
@ -1002,9 +1002,10 @@ namespace smt {
m_assignment[i] = a;
// TBD: if epsilon is != 0, then adjust a by some small fraction.
}
blocker = mk_gt(v, r);
inf_eps result(rational(0), r);
blocker = mk_gt(v, result);
IF_VERBOSE(10, verbose_stream() << blocker << "\n";);
return inf_eps(rational(0), r);
return result;
}
default:
TRACE("opt", tout << "unbounded\n"; );
@ -1034,18 +1035,18 @@ namespace smt {
}
template<typename Ext>
expr_ref theory_dense_diff_logic<Ext>::mk_gt(theory_var v, inf_rational const& val) {
expr_ref theory_dense_diff_logic<Ext>::mk_gt(theory_var v, inf_eps const& val) {
return mk_ineq(v, val, true);
}
template<typename Ext>
expr_ref theory_dense_diff_logic<Ext>::mk_ge(
filter_model_converter& fm, theory_var v, inf_rational const& val) {
filter_model_converter& fm, theory_var v, inf_eps const& val) {
return mk_ineq(v, val, false);
}
template<typename Ext>
expr_ref theory_dense_diff_logic<Ext>::mk_ineq(theory_var v, inf_rational const& val, bool is_strict) {
expr_ref theory_dense_diff_logic<Ext>::mk_ineq(theory_var v, inf_eps const& val, bool is_strict) {
ast_manager& m = get_manager();
objective_term const& t = m_objectives[v];
expr_ref e(m), f(m), f2(m);

View file

@ -324,14 +324,15 @@ namespace smt {
virtual inf_eps maximize(theory_var v, expr_ref& blocker, bool& has_shared);
virtual inf_eps value(theory_var v);
virtual theory_var add_objective(app* term);
virtual expr_ref mk_gt(theory_var v, inf_rational const& val);
virtual expr_ref mk_ge(filter_model_converter& fm, theory_var v, inf_rational const& val);
expr_ref mk_ge(filter_model_converter& fm, theory_var v, inf_eps const& val);
bool internalize_objective(expr * n, rational const& m, rational& r, objective_term & objective);
private:
expr_ref mk_ineq(theory_var v, inf_rational const& val, bool is_strict);
expr_ref mk_gt(theory_var v, inf_eps const& val);
expr_ref mk_ineq(theory_var v, inf_eps const& val, bool is_strict);
virtual void new_eq_eh(theory_var v1, theory_var v2, justification& j);

View file

@ -905,7 +905,7 @@ model_value_proc * theory_diff_logic<Ext>::mk_value(enode * n, model_generator &
numeral val = m_graph.get_assignment(v);
rational num = val.get_rational().to_rational() + m_delta * val.get_infinitesimal().to_rational();
TRACE("arith", tout << mk_pp(n->get_owner(), get_manager()) << " |-> " << num << "\n";);
return alloc(expr_wrapper_proc, m_factory->mk_value(num, m_util.is_int(n->get_owner())));
return alloc(expr_wrapper_proc, m_factory->mk_num_value(num, m_util.is_int(n->get_owner())));
}
template<typename Ext>
@ -1242,7 +1242,8 @@ theory_diff_logic<Ext>::maximize(theory_var v, expr_ref& blocker, bool& has_shar
rational r = rational(val.first) + m_delta*rational(val.second);
m_graph.set_assignment(i, numeral(r));
}
blocker = mk_gt(v, r);
inf_eps r1(rational(0), r);
blocker = mk_gt(v, r1);
return inf_eps(rational(0), r + m_objective_consts[v]);
}
default:
@ -1273,7 +1274,7 @@ theory_var theory_diff_logic<Ext>::add_objective(app* term) {
}
template<typename Ext>
expr_ref theory_diff_logic<Ext>::mk_ineq(theory_var v, inf_rational const& val, bool is_strict) {
expr_ref theory_diff_logic<Ext>::mk_ineq(theory_var v, inf_eps const& val, bool is_strict) {
ast_manager& m = get_manager();
objective_term const& t = m_objectives[v];
expr_ref e(m), f(m), f2(m);
@ -1304,7 +1305,7 @@ expr_ref theory_diff_logic<Ext>::mk_ineq(theory_var v, inf_rational const& val,
return f;
}
inf_rational new_val = val; // - inf_rational(m_objective_consts[v]);
inf_eps new_val = val; // - inf_rational(m_objective_consts[v]);
e = m_util.mk_numeral(new_val.get_rational(), m.get_sort(f));
if (new_val.get_infinitesimal().is_neg()) {
@ -1328,12 +1329,12 @@ expr_ref theory_diff_logic<Ext>::mk_ineq(theory_var v, inf_rational const& val,
}
template<typename Ext>
expr_ref theory_diff_logic<Ext>::mk_gt(theory_var v, inf_rational const& val) {
expr_ref theory_diff_logic<Ext>::mk_gt(theory_var v, inf_eps const& val) {
return mk_ineq(v, val, true);
}
template<typename Ext>
expr_ref theory_diff_logic<Ext>::mk_ge(filter_model_converter& fm, theory_var v, inf_rational const& val) {
expr_ref theory_diff_logic<Ext>::mk_ge(filter_model_converter& fm, theory_var v, inf_eps const& val) {
return mk_ineq(v, val, false);
}

View file

@ -33,7 +33,6 @@ namespace smt {
virtual inf_eps value(theory_var) = 0;
virtual inf_eps maximize(theory_var v, expr_ref& blocker, bool& has_shared) = 0;
virtual theory_var add_objective(app* term) = 0;
virtual expr_ref mk_ge(filter_model_converter& fm, theory_var v, inf_eps const& val) { UNREACHABLE(); return expr_ref(*((ast_manager*)0)); }
bool is_linear(ast_manager& m, expr* term);
bool is_numeral(arith_util& a, expr* term);
};

View file

@ -2235,8 +2235,9 @@ bool theory_seq::add_stoi_axiom(expr* e) {
context& ctx = get_context();
expr* n;
rational val;
TRACE("seq", tout << mk_pp(e, m) << "\n";);
VERIFY(m_util.str.is_stoi(e, n));
if (get_value(e, val) && !m_stoi_axioms.contains(val)) {
if (get_num_value(e, val) && !m_stoi_axioms.contains(val)) {
m_stoi_axioms.insert(val);
if (!val.is_minus_one()) {
app_ref e1(m_util.str.mk_string(symbol(val.to_string().c_str())), m);
@ -2252,15 +2253,72 @@ bool theory_seq::add_stoi_axiom(expr* e) {
return true;
}
}
if (upper_bound(n, val) && get_length(n, val) && val.is_pos() && !m_stoi_axioms.contains(val)) {
zstring s;
SASSERT(val.is_unsigned());
unsigned sz = val.get_unsigned();
expr_ref len1(m), len2(m), ith_char(m), num(m), coeff(m);
expr_ref_vector nums(m);
len1 = m_util.str.mk_length(n);
len2 = m_autil.mk_int(sz);
literal lit = mk_eq(len1, len2, false);
literal_vector lits;
lits.push_back(~lit);
for (unsigned i = 0; i < sz; ++i) {
ith_char = mk_nth(n, m_autil.mk_int(i));
lits.push_back(~is_digit(ith_char));
nums.push_back(digit2int(ith_char));
}
for (unsigned i = sz-1, c = 1; i > 0; c *= 10) {
--i;
coeff = m_autil.mk_int(c);
nums[i] = m_autil.mk_mul(coeff, nums[i].get());
}
num = m_autil.mk_add(nums.size(), nums.c_ptr());
lits.push_back(mk_eq(e, num, false));
++m_stats.m_add_axiom;
m_new_propagation = true;
for (unsigned i = 0; i < lits.size(); ++i) {
ctx.mark_as_relevant(lits[i]);
}
ctx.mk_th_axiom(get_id(), lits.size(), lits.c_ptr());
m_stoi_axioms.insert(val);
m_trail_stack.push(insert_map<theory_seq, rational_set, rational>(m_stoi_axioms, val));
m_trail_stack.push(push_replay(alloc(replay_axiom, m, e)));
return true;
}
return false;
}
literal theory_seq::is_digit(expr* ch) {
bv_util bv(m);
literal isd = mk_literal(mk_skolem(symbol("seq.is_digit"), ch, 0, 0, m.mk_bool_sort()));
expr_ref d2i = digit2int(ch);
expr_ref _lo(bv.mk_ule(bv.mk_numeral(rational('0'), bv.mk_sort(8)), ch), m);
expr_ref _hi(bv.mk_ule(ch, bv.mk_numeral(rational('9'), bv.mk_sort(8))), m);
literal lo = mk_literal(_lo);
literal hi = mk_literal(_hi);
add_axiom(~lo, ~hi, isd);
add_axiom(~isd, lo);
add_axiom(~isd, hi);
for (unsigned i = 0; i < 10; ++i) {
add_axiom(~mk_eq(ch, bv.mk_numeral(rational('0'+i), bv.mk_sort(8)), false), mk_eq(d2i, m_autil.mk_int(i), false));
}
return isd;
}
expr_ref theory_seq::digit2int(expr* ch) {
return expr_ref(mk_skolem(symbol("seq.digit2int"), ch, 0, 0, m_autil.mk_int()), m);
}
bool theory_seq::add_itos_axiom(expr* e) {
context& ctx = get_context();
rational val;
expr* n;
TRACE("seq", tout << mk_pp(e, m) << "\n";);
VERIFY(m_util.str.is_itos(e, n));
if (get_value(n, val)) {
if (get_num_value(n, val)) {
if (!m_itos_axioms.contains(val)) {
m_itos_axioms.insert(val);
app_ref e1(m_util.str.mk_string(symbol(val.to_string().c_str())), m);
@ -2282,6 +2340,9 @@ bool theory_seq::add_itos_axiom(expr* e) {
else {
// stoi(itos(n)) = n
app_ref e2(m_util.str.mk_stoi(e), m);
if (ctx.e_internalized(e2) && ctx.get_enode(e2)->get_root() == ctx.get_enode(n)->get_root()) {
return false;
}
add_axiom(mk_eq(e2, n, false));
m_trail_stack.push(push_replay(alloc(replay_axiom, m, e)));
return true;
@ -2464,22 +2525,27 @@ void theory_seq::init_model(model_generator & mg) {
class theory_seq::seq_value_proc : public model_value_proc {
enum source_t { unit_source, int_source, string_source };
theory_seq& th;
sort* m_sort;
svector<model_value_dependency> m_dependencies;
ptr_vector<expr> m_strings;
svector<bool> m_source;
svector<source_t> m_source;
public:
seq_value_proc(theory_seq& th, sort* s): th(th), m_sort(s) {
}
virtual ~seq_value_proc() {}
void add_dependency(enode* n) {
void add_unit(enode* n) {
m_dependencies.push_back(model_value_dependency(n));
m_source.push_back(true);
m_source.push_back(unit_source);
}
void add_int(enode* n) {
m_dependencies.push_back(model_value_dependency(n));
m_source.push_back(int_source);
}
void add_string(expr* n) {
m_strings.push_back(n);
m_source.push_back(false);
m_source.push_back(string_source);
}
virtual void get_dependencies(buffer<model_value_dependency> & result) {
result.append(m_dependencies.size(), m_dependencies.c_ptr());
@ -2504,11 +2570,13 @@ public:
unsigned sz;
for (unsigned i = 0; i < m_source.size(); ++i) {
if (m_source[i]) {
switch (m_source[i]) {
case unit_source: {
VERIFY(bv.is_numeral(values[j++], val, sz));
sbuffer.push_back(val.get_unsigned());
break;
}
else {
case string_source: {
dependency* deps = 0;
expr_ref tmp = th.canonize(m_strings[k], deps);
zstring zs;
@ -2519,17 +2587,34 @@ public:
TRACE("seq", tout << "Not a string: " << tmp << "\n";);
}
++k;
break;
}
case int_source: {
std::ostringstream strm;
arith_util arith(th.m);
VERIFY(arith.is_numeral(values[j++], val));
if (val.is_neg()) strm << "-";
strm << abs(val);
zstring zs(strm.str().c_str());
add_buffer(sbuffer, zs);
break;
}
}
}
result = th.m_util.str.mk_string(zstring(sbuffer.size(), sbuffer.c_ptr()));
}
else {
for (unsigned i = 0; i < m_source.size(); ++i) {
if (m_source[i]) {
switch (m_source[i]) {
case unit_source:
args.push_back(th.m_util.str.mk_unit(values[j++]));
}
else {
break;
case string_source:
args.push_back(m_strings[k++]);
break;
case int_source:
UNREACHABLE();
break;
}
}
result = th.mk_concat(args, m_sort);
@ -2567,7 +2652,12 @@ model_value_proc * theory_seq::mk_value(enode * n, model_generator & mg) {
TRACE("seq", tout << mk_pp(c, m) << "\n";);
if (m_util.str.is_unit(c, c1)) {
if (ctx.e_internalized(c1)) {
sv->add_dependency(ctx.get_enode(c1));
sv->add_unit(ctx.get_enode(c1));
}
}
else if (m_util.str.is_itos(c, c1)) {
if (ctx.e_internalized(c1)) {
sv->add_int(ctx.get_enode(c1));
}
}
else if (m_util.str.is_string(c)) {
@ -2741,7 +2831,8 @@ expr_ref theory_seq::expand(expr* e0, dependency*& eqs) {
}
else if (m_util.str.is_itos(e, e1)) {
rational val;
if (get_value(e1, val)) {
TRACE("seq", tout << mk_pp(e, m) << "\n";);
if (get_num_value(e1, val)) {
TRACE("seq", tout << mk_pp(e, m) << " -> " << val << "\n";);
expr_ref num(m), res(m);
num = m_autil.mk_numeral(val, true);
@ -2916,7 +3007,7 @@ void theory_seq::add_indexof_axiom(expr* i) {
expr_ref len_t(m_util.str.mk_length(t), m);
literal offset_ge_len = mk_literal(m_autil.mk_ge(mk_sub(offset, len_t), zero));
add_axiom(offset_ge_len, mk_eq(i, minus_one, false));
add_axiom(~offset_ge_len, mk_eq(i, minus_one, false));
expr_ref x = mk_skolem(m_indexof_left, t, s, offset);
expr_ref y = mk_skolem(m_indexof_right, t, s, offset);
@ -3024,7 +3115,7 @@ void theory_seq::add_itos_length_axiom(expr* len) {
unsigned num_char1 = 1, num_char2 = 1;
rational len1, len2;
rational ten(10);
if (get_value(n, len1)) {
if (get_num_value(n, len1)) {
bool neg = len1.is_neg();
if (neg) len1.neg();
num_char1 = neg?2:1;
@ -3038,7 +3129,7 @@ void theory_seq::add_itos_length_axiom(expr* len) {
}
SASSERT(len1 <= upper);
}
if (get_value(len, len2) && len2.is_unsigned()) {
if (get_num_value(len, len2) && len2.is_unsigned()) {
num_char2 = len2.get_unsigned();
}
unsigned num_char = std::max(num_char1, num_char2);
@ -3172,18 +3263,17 @@ static theory_mi_arith* get_th_arith(context& ctx, theory_id afid, expr* e) {
}
}
bool theory_seq::get_value(expr* e, rational& val) const {
bool theory_seq::get_num_value(expr* e, rational& val) const {
context& ctx = get_context();
theory_mi_arith* tha = get_th_arith(ctx, m_autil.get_family_id(), e);
expr_ref _val(m);
if (!tha) return false;
enode* next = ctx.get_enode(e), *n;
enode* next = ctx.get_enode(e), *n = next;
do {
n = next;
if (tha->get_value(n, _val) && m_autil.is_numeral(_val, val) && val.is_int()) {
if (tha->get_value(next, _val) && m_autil.is_numeral(_val, val) && val.is_int()) {
return true;
}
next = n->get_next();
next = next->get_next();
}
while (next != n);
return false;
@ -3692,7 +3782,10 @@ void theory_seq::assign_eh(bool_var v, bool is_true) {
else if (is_skolem(symbol("seq.split"), e)) {
// propagate equalities
}
else if (is_skolem(symbol("seq.is_digit"), e)) {
}
else {
TRACE("seq", tout << mk_pp(e, m) << "\n";);
UNREACHABLE();
}
}

View file

@ -499,6 +499,8 @@ namespace smt {
void add_in_re_axiom(expr* n);
bool add_stoi_axiom(expr* n);
bool add_itos_axiom(expr* n);
literal is_digit(expr* ch);
expr_ref digit2int(expr* ch);
void add_itos_length_axiom(expr* n);
literal mk_literal(expr* n);
literal mk_eq_empty(expr* n, bool phase = true);
@ -512,7 +514,7 @@ namespace smt {
// arithmetic integration
bool get_value(expr* s, rational& val) const;
bool get_num_value(expr* s, rational& val) const;
bool lower_bound(expr* s, rational& lo) const;
bool upper_bound(expr* s, rational& hi) const;
bool get_length(expr* s, rational& val) const;

View file

@ -901,7 +901,7 @@ namespace smt {
bool is_int = a.is_int(n->get_owner());
rational num = mk_value(v, is_int);
TRACE("utvpi", tout << mk_pp(n->get_owner(), get_manager()) << " |-> " << num << "\n";);
return alloc(expr_wrapper_proc, m_factory->mk_value(num, is_int));
return alloc(expr_wrapper_proc, m_factory->mk_num_value(num, is_int));
}
/**

View file

@ -21,294 +21,351 @@ Notes:
#include "smt_context.h"
#include "ast_pp.h"
#include "theory_wmaxsat.h"
#include "smt_justification.h"
namespace smt {
theory_wmaxsat::theory_wmaxsat(ast_manager& m, filter_model_converter& mc):
theory(m.mk_family_id("weighted_maxsat")),
m_mc(mc),
m_vars(m),
m_fmls(m),
m_zweights(m_mpz),
m_old_values(m_mpz),
m_zcost(m_mpz),
m_zmin_cost(m_mpz),
m_found_optimal(false),
m_propagate(false),
m_normalize(false),
m_den(1)
{}
theory_wmaxsat::~theory_wmaxsat() {
m_old_values.reset();
}
/**
\brief return the complement of variables that are currently assigned.
*/
void theory_wmaxsat::get_assignment(svector<bool>& result) {
result.reset();
theory_wmaxsat::theory_wmaxsat(ast_manager& m, filter_model_converter& mc):
theory(m.mk_family_id("weighted_maxsat")),
m_mc(mc),
m_vars(m),
m_fmls(m),
m_zweights(m_mpz),
m_old_values(m_mpz),
m_zcost(m_mpz),
m_zmin_cost(m_mpz),
m_found_optimal(false),
m_propagate(false),
m_normalize(false),
m_den(1)
{}
if (!m_found_optimal) {
for (unsigned i = 0; i < m_vars.size(); ++i) {
result.push_back(false);
}
theory_wmaxsat::~theory_wmaxsat() {
m_old_values.reset();
}
else {
std::sort(m_cost_save.begin(), m_cost_save.end());
for (unsigned i = 0,j = 0; i < m_vars.size(); ++i) {
if (j < m_cost_save.size() && m_cost_save[j] == static_cast<theory_var>(i)) {
/**
\brief return the complement of variables that are currently assigned.
*/
void theory_wmaxsat::get_assignment(svector<bool>& result) {
result.reset();
if (!m_found_optimal) {
for (unsigned i = 0; i < m_vars.size(); ++i) {
result.push_back(false);
++j;
}
else {
result.push_back(true);
}
}
else {
std::sort(m_cost_save.begin(), m_cost_save.end());
for (unsigned i = 0,j = 0; i < m_vars.size(); ++i) {
if (j < m_cost_save.size() && m_cost_save[j] == static_cast<theory_var>(i)) {
result.push_back(false);
++j;
}
else {
result.push_back(true);
}
}
}
TRACE("opt",
tout << "cost save: ";
for (unsigned i = 0; i < m_cost_save.size(); ++i) {
tout << m_cost_save[i] << " ";
}
tout << "\nvars: ";
for (unsigned i = 0; i < m_vars.size(); ++i) {
tout << mk_pp(m_vars[i].get(), get_manager()) << " ";
}
tout << "\nassignment: ";
for (unsigned i = 0; i < result.size(); ++i) {
tout << result[i] << " ";
}
tout << "\n";);
}
TRACE("opt",
tout << "cost save: ";
for (unsigned i = 0; i < m_cost_save.size(); ++i) {
tout << m_cost_save[i] << " ";
}
tout << "\nvars: ";
for (unsigned i = 0; i < m_vars.size(); ++i) {
tout << mk_pp(m_vars[i].get(), get_manager()) << " ";
}
tout << "\nassignment: ";
for (unsigned i = 0; i < result.size(); ++i) {
tout << result[i] << " ";
}
tout << "\n";);
}
void theory_wmaxsat::init_search_eh() {
m_propagate = true;
}
expr* theory_wmaxsat::assert_weighted(expr* fml, rational const& w, bool is_true) {
context & ctx = get_context();
ast_manager& m = get_manager();
app_ref var(m), wfml(m);
var = m.mk_fresh_const("w", m.mk_bool_sort());
m_mc.insert(var->get_decl());
wfml = m.mk_or(var, fml);
ctx.assert_expr(wfml);
m_rweights.push_back(w);
m_vars.push_back(var);
m_fmls.push_back(fml);
m_assigned.push_back(false);
if (!is_true) {
m_rmin_cost += w;
void theory_wmaxsat::init_search_eh() {
m_propagate = true;
}
m_normalize = true;
return ctx.bool_var2expr(register_var(var, true));
}
bool_var theory_wmaxsat::register_var(app* var, bool attach) {
context & ctx = get_context();
bool_var bv;
SASSERT(!ctx.e_internalized(var));
enode* x = ctx.mk_enode(var, false, true, true);
if (ctx.b_internalized(var)) {
bv = ctx.get_bool_var(var);
expr* theory_wmaxsat::assert_weighted(expr* fml, rational const& w) {
context & ctx = get_context();
ast_manager& m = get_manager();
app_ref var(m), wfml(m);
var = m.mk_fresh_const("w", m.mk_bool_sort());
m_mc.insert(var->get_decl());
wfml = m.mk_or(var, fml);
ctx.assert_expr(wfml);
m_rweights.push_back(w);
m_vars.push_back(var);
m_fmls.push_back(fml);
m_assigned.push_back(false);
m_enabled.push_back(true);
m_normalize = true;
bool_var bv = register_var(var, true);
TRACE("opt", tout << "enable: v" << m_bool2var[bv] << " b" << bv << " " << mk_pp(var, get_manager()) << "\n";
tout << wfml << "\n";);
return var;
}
else {
bv = ctx.mk_bool_var(var);
}
ctx.set_enode_flag(bv, true);
if (attach) {
ctx.set_var_theory(bv, get_id());
theory_var v = mk_var(x);
ctx.attach_th_var(x, this, v);
m_bool2var.insert(bv, v);
SASSERT(v == static_cast<theory_var>(m_var2bool.size()));
m_var2bool.push_back(bv);
SASSERT(ctx.bool_var2enode(bv));
}
return bv;
}
rational const& theory_wmaxsat::get_min_cost() {
unsynch_mpq_manager mgr;
scoped_mpq q(mgr);
mgr.set(q, m_zmin_cost, m_den.to_mpq().numerator());
m_rmin_cost = rational(q);
return m_rmin_cost;
}
void theory_wmaxsat::assign_eh(bool_var v, bool is_true) {
TRACE("opt", tout << "Assign " << mk_pp(m_vars[m_bool2var[v]].get(), get_manager()) << " " << is_true << "\n";);
if (is_true) {
if (m_normalize) normalize();
void theory_wmaxsat::disable_var(expr* var) {
context& ctx = get_context();
theory_var tv = m_bool2var[v];
if (m_assigned[tv]) return;
scoped_mpz w(m_mpz);
w = m_zweights[tv];
ctx.push_trail(numeral_trail(m_zcost, m_old_values));
ctx.push_trail(push_back_vector<context, svector<theory_var> >(m_costs));
ctx.push_trail(value_trail<context, bool>(m_assigned[tv]));
m_zcost += w;
m_costs.push_back(tv);
m_assigned[tv] = true;
if (m_zcost > m_zmin_cost) {
block();
SASSERT(ctx.b_internalized(var));
bool_var bv = ctx.get_bool_var(var);
theory_var tv = m_bool2var[bv];
m_enabled[tv] = false;
TRACE("opt", tout << "disable: v" << tv << " b" << bv << " " << mk_pp(var, get_manager()) << "\n";);
}
bool_var theory_wmaxsat::register_var(app* var, bool attach) {
context & ctx = get_context();
bool_var bv;
SASSERT(!ctx.e_internalized(var));
enode* x = ctx.mk_enode(var, false, true, true);
if (ctx.b_internalized(var)) {
bv = ctx.get_bool_var(var);
}
}
}
final_check_status theory_wmaxsat::final_check_eh() {
if (m_normalize) normalize();
return FC_DONE;
}
void theory_wmaxsat::reset_eh() {
theory::reset_eh();
reset_local();
}
void theory_wmaxsat::reset_local() {
m_vars.reset();
m_fmls.reset();
m_rweights.reset();
m_rmin_cost.reset();
m_rcost.reset();
m_zweights.reset();
m_zcost.reset();
m_zmin_cost.reset();
m_cost_save.reset();
m_bool2var.reset();
m_var2bool.reset();
m_propagate = false;
m_found_optimal = false;
m_assigned.reset();
}
void theory_wmaxsat::propagate() {
context& ctx = get_context();
for (unsigned i = 0; m_propagate && i < m_vars.size(); ++i) {
bool_var bv = m_var2bool[i];
lbool asgn = ctx.get_assignment(bv);
if (asgn == l_true) {
assign_eh(bv, true);
else {
bv = ctx.mk_bool_var(var);
}
ctx.set_enode_flag(bv, true);
if (attach) {
ctx.set_var_theory(bv, get_id());
theory_var v = mk_var(x);
ctx.attach_th_var(x, this, v);
m_bool2var.insert(bv, v);
SASSERT(v == static_cast<theory_var>(m_var2bool.size()));
m_var2bool.push_back(bv);
SASSERT(ctx.bool_var2enode(bv));
}
return bv;
}
m_propagate = false;
}
bool theory_wmaxsat::is_optimal() const {
return !m_found_optimal || m_zcost < m_zmin_cost;
}
expr_ref theory_wmaxsat::mk_block() {
++m_stats.m_num_blocks;
ast_manager& m = get_manager();
expr_ref_vector disj(m);
compare_cost compare_cost(*this);
svector<theory_var> costs(m_costs);
std::sort(costs.begin(), costs.end(), compare_cost);
scoped_mpz weight(m_mpz);
m_mpz.reset(weight);
for (unsigned i = 0; i < costs.size() && m_mpz.lt(weight, m_zmin_cost); ++i) {
weight += m_zweights[costs[i]];
disj.push_back(m.mk_not(m_vars[costs[i]].get()));
}
if (is_optimal()) {
rational theory_wmaxsat::get_cost() {
unsynch_mpq_manager mgr;
scoped_mpq q(mgr);
mgr.set(q, m_zmin_cost, m_den.to_mpq().numerator());
rational rw = rational(q);
m_zmin_cost = weight;
m_found_optimal = true;
mgr.set(q, m_zcost, m_den.to_mpq().numerator());
return rational(q);
}
void theory_wmaxsat::init_min_cost(rational const& r) {
m_rmin_cost = r;
m_zmin_cost = (m_rmin_cost * m_den).to_mpq().numerator();
}
void theory_wmaxsat::assign_eh(bool_var v, bool is_true) {
if (is_true) {
if (m_normalize) normalize();
context& ctx = get_context();
theory_var tv = m_bool2var[v];
if (m_assigned[tv] || !m_enabled[tv]) return;
scoped_mpz w(m_mpz);
w = m_zweights[tv];
ctx.push_trail(numeral_trail(m_zcost, m_old_values));
ctx.push_trail(push_back_vector<context, svector<theory_var> >(m_costs));
ctx.push_trail(value_trail<context, bool>(m_assigned[tv]));
m_zcost += w;
TRACE("opt", tout << "Assign v" << tv << " weight: " << w << " cost: " << m_zcost << " " << mk_pp(m_vars[m_bool2var[v]].get(), get_manager()) << "\n";);
m_costs.push_back(tv);
m_assigned[tv] = true;
if (m_zcost >= m_zmin_cost) {
block();
}
else {
m_can_propagate = true;
}
}
}
final_check_status theory_wmaxsat::final_check_eh() {
if (m_normalize) normalize();
// std::cout << "cost: " << m_zcost << " min cost: " << m_zmin_cost << "\n";
return FC_DONE;
}
void theory_wmaxsat::reset_eh() {
theory::reset_eh();
reset_local();
}
void theory_wmaxsat::reset_local() {
m_vars.reset();
m_fmls.reset();
m_rweights.reset();
m_rmin_cost.reset();
m_zweights.reset();
m_zcost.reset();
m_zmin_cost.reset();
m_cost_save.reset();
m_cost_save.append(m_costs);
m_bool2var.reset();
m_var2bool.reset();
m_propagate = false;
m_can_propagate = false;
m_found_optimal = false;
m_assigned.reset();
m_enabled.reset();
}
void theory_wmaxsat::propagate() {
context& ctx = get_context();
for (unsigned i = 0; m_propagate && i < m_vars.size(); ++i) {
bool_var bv = m_var2bool[i];
lbool asgn = ctx.get_assignment(bv);
if (asgn == l_true) {
assign_eh(bv, true);
}
}
m_propagate = false;
//while (m_found_optimal && max_unassigned_is_blocked() && !ctx.inconsistent()) { }
m_can_propagate = false;
}
bool theory_wmaxsat::is_optimal() const {
return !m_found_optimal || m_zcost < m_zmin_cost;
}
expr_ref theory_wmaxsat::mk_block() {
++m_stats.m_num_blocks;
ast_manager& m = get_manager();
expr_ref_vector disj(m);
compare_cost compare_cost(*this);
svector<theory_var> costs(m_costs);
std::sort(costs.begin(), costs.end(), compare_cost);
scoped_mpz weight(m_mpz);
m_mpz.reset(weight);
for (unsigned i = 0; i < costs.size() && m_mpz.lt(weight, m_zmin_cost); ++i) {
theory_var tv = costs[i];
if (m_enabled[tv]) {
weight += m_zweights[tv];
disj.push_back(m.mk_not(m_vars[tv].get()));
}
}
if (is_optimal()) {
m_found_optimal = true;
m_cost_save.reset();
m_cost_save.append(m_costs);
TRACE("opt",
tout << "costs: ";
for (unsigned i = 0; i < m_costs.size(); ++i) {
tout << mk_pp(get_enode(m_costs[i])->get_owner(), get_manager()) << " ";
}
tout << "\n";
//get_context().display(tout);
);
}
expr_ref result(m.mk_or(disj.size(), disj.c_ptr()), m);
TRACE("opt",
tout << "costs: ";
for (unsigned i = 0; i < m_costs.size(); ++i) {
tout << mk_pp(get_enode(m_costs[i])->get_owner(), get_manager()) << " ";
}
tout << "\n";
get_context().display(tout);
);
tout << result << " weight: " << weight << "\n";
tout << "cost: " << m_zcost << " min-cost: " << m_zmin_cost << "\n";);
return result;
}
expr_ref result(m.mk_or(disj.size(), disj.c_ptr()), m);
TRACE("opt",
tout << result << " weight: " << weight << "\n";
tout << "cost: " << m_zcost << " min-cost: " << m_zmin_cost << "\n";);
return result;
}
expr_ref theory_wmaxsat::mk_optimal_block(svector<bool_var> const& ws, rational const& weight) {
ast_manager& m = get_manager();
expr_ref_vector disj(m);
rational new_w = weight*m_den;
m_zmin_cost = new_w.to_mpq().numerator();
m_cost_save.reset();
for (unsigned i = 0; i < ws.size(); ++i) {
bool_var bv = ws[i];
theory_var v = m_bool2var[bv];
m_cost_save.push_back(v);
disj.push_back(m.mk_not(m_vars[v].get()));
}
expr_ref result(m.mk_or(disj.size(), disj.c_ptr()), m);
return result;
}
void theory_wmaxsat::restart_eh() {}
void theory_wmaxsat::block() {
if (m_vars.empty()) {
return;
void theory_wmaxsat::block() {
if (m_vars.empty()) {
return;
}
++m_stats.m_num_blocks;
context& ctx = get_context();
literal_vector lits;
compare_cost compare_cost(*this);
svector<theory_var> costs(m_costs);
std::sort(costs.begin(), costs.end(), compare_cost);
scoped_mpz weight(m_mpz);
m_mpz.reset(weight);
for (unsigned i = 0; i < costs.size() && weight < m_zmin_cost; ++i) {
weight += m_zweights[costs[i]];
lits.push_back(literal(m_var2bool[costs[i]]));
}
TRACE("opt", ctx.display_literals_verbose(tout, lits); tout << "\n";);
ctx.set_conflict(
ctx.mk_justification(
ext_theory_conflict_justification(get_id(), ctx.get_region(), lits.size(), lits.c_ptr(), 0, 0, 0, 0)));
}
bool theory_wmaxsat::max_unassigned_is_blocked() {
context& ctx = get_context();
unsigned max_unassigned = m_max_unassigned_index;
if (max_unassigned < m_sorted_vars.size() &&
m_zcost + m_zweights[m_sorted_vars[max_unassigned]] < m_zmin_cost) {
return false;
}
// update value of max-unassigned
while (max_unassigned < m_sorted_vars.size() &&
ctx.get_assignment(m_var2bool[m_sorted_vars[max_unassigned]]) != l_undef) {
++max_unassigned;
}
//
if (max_unassigned > m_max_unassigned_index) {
ctx.push_trail(value_trail<context, unsigned>(m_max_unassigned_index));
m_max_unassigned_index = max_unassigned;
}
if (max_unassigned < m_sorted_vars.size() &&
m_zcost + m_zweights[m_sorted_vars[max_unassigned]] >= m_zmin_cost) {
theory_var tv = m_sorted_vars[max_unassigned];
propagate(m_var2bool[tv]);
m_max_unassigned_index++;
return true;
}
return false;
}
++m_stats.m_num_blocks;
context& ctx = get_context();
literal_vector lits;
compare_cost compare_cost(*this);
svector<theory_var> costs(m_costs);
std::sort(costs.begin(), costs.end(), compare_cost);
scoped_mpz weight(m_mpz);
m_mpz.reset(weight);
for (unsigned i = 0; i < costs.size() && weight < m_zmin_cost; ++i) {
weight += m_zweights[costs[i]];
lits.push_back(~literal(m_var2bool[costs[i]]));
}
TRACE("opt",
ast_manager& m = get_manager();
tout << "block: ";
for (unsigned i = 0; i < lits.size(); ++i) {
expr_ref tmp(m);
ctx.literal2expr(lits[i], tmp);
tout << tmp << " ";
}
tout << "\n";
);
ctx.mk_th_axiom(get_id(), lits.size(), lits.c_ptr());
}
void theory_wmaxsat::propagate(bool_var v) {
++m_stats.m_num_propagations;
context& ctx = get_context();
literal_vector lits;
literal lit(v, true);
SASSERT(ctx.get_assignment(lit) == l_undef);
for (unsigned i = 0; i < m_costs.size(); ++i) {
bool_var w = m_var2bool[m_costs[i]];
lits.push_back(literal(w));
}
TRACE("opt",
ctx.display_literals_verbose(tout, lits.size(), lits.c_ptr());
ctx.display_literal_verbose(tout << " --> ", lit););
region& r = ctx.get_region();
ctx.assign(lit, ctx.mk_justification(
ext_theory_propagation_justification(
get_id(), r, lits.size(), lits.c_ptr(), 0, 0, lit, 0, 0)));
}
void theory_wmaxsat::normalize() {
m_den = rational::one();
for (unsigned i = 0; i < m_rweights.size(); ++i) {
m_den = lcm(m_den, denominator(m_rweights[i]));
void theory_wmaxsat::normalize() {
m_den = rational::one();
for (unsigned i = 0; i < m_rweights.size(); ++i) {
if (m_enabled[i]) {
m_den = lcm(m_den, denominator(m_rweights[i]));
}
}
m_den = lcm(m_den, denominator(m_rmin_cost));
SASSERT(!m_den.is_zero());
m_zweights.reset();
m_sorted_vars.reset();
for (unsigned i = 0; i < m_rweights.size(); ++i) {
rational r = m_rweights[i]*m_den;
SASSERT(r.is_int());
mpq const& q = r.to_mpq();
m_zweights.push_back(q.numerator());
m_sorted_vars.push_back(i);
}
compare_cost compare_cost(*this);
std::sort(m_sorted_vars.begin(), m_sorted_vars.end(), compare_cost);
m_max_unassigned_index = 0;
m_zcost.reset();
rational r = m_rmin_cost * m_den;
m_zmin_cost = r.to_mpq().numerator();
m_normalize = false;
}
m_den = lcm(m_den, denominator(m_rmin_cost));
SASSERT(!m_den.is_zero());
m_zweights.reset();
for (unsigned i = 0; i < m_rweights.size(); ++i) {
rational r = m_rweights[i]*m_den;
SASSERT(r.is_int());
mpq const& q = r.to_mpq();
m_zweights.push_back(q.numerator());
}
rational r = m_rcost* m_den;
m_zcost = r.to_mpq().numerator();
r = m_rmin_cost * m_den;
m_zmin_cost = r.to_mpq().numerator();
m_normalize = false;
}
};

View file

@ -28,6 +28,7 @@ namespace smt {
class theory_wmaxsat : public theory {
struct stats {
unsigned m_num_blocks;
unsigned m_num_propagations;
void reset() { memset(this, 0, sizeof(*this)); }
stats() { reset(); }
};
@ -39,27 +40,31 @@ namespace smt {
scoped_mpz_vector m_zweights;
scoped_mpz_vector m_old_values;
svector<theory_var> m_costs; // set of asserted theory variables
unsigned m_max_unassigned_index; // index of literal that is not yet assigned and has maximal weight.
svector<theory_var> m_sorted_vars; // set of all theory variables, sorted by cost
svector<theory_var> m_cost_save; // set of asserted theory variables
rational m_rcost; // current sum of asserted costs
rational m_rmin_cost; // current maximal cost assignment.
scoped_mpz m_zcost; // current sum of asserted costs
scoped_mpz m_zmin_cost; // current maximal cost assignment.
bool m_found_optimal;
u_map<theory_var> m_bool2var; // bool_var -> theory_var
svector<bool_var> m_var2bool; // theory_var -> bool_var
bool m_propagate;
bool m_propagate;
bool m_can_propagate;
bool m_normalize;
rational m_den; // lcm of denominators for rational weights.
svector<bool> m_assigned;
svector<bool> m_assigned, m_enabled;
stats m_stats;
public:
theory_wmaxsat(ast_manager& m, filter_model_converter& mc);
virtual ~theory_wmaxsat();
void get_assignment(svector<bool>& result);
virtual void init_search_eh();
expr* assert_weighted(expr* fml, rational const& w, bool is_true);
expr* assert_weighted(expr* fml, rational const& w);
void disable_var(expr* var);
bool_var register_var(app* var, bool attach);
rational const& get_min_cost();
rational get_cost();
void init_min_cost(rational const& r);
class numeral_trail : public trail<context> {
typedef scoped_mpz T;
T & m_value;
@ -79,6 +84,8 @@ namespace smt {
m_old_values.shrink(m_old_values.size() - 1);
}
};
virtual void init_search_eh();
virtual void assign_eh(bool_var v, bool is_true);
virtual final_check_status final_check_eh();
virtual bool use_diseqs() const {
@ -95,23 +102,30 @@ namespace smt {
virtual void new_eq_eh(theory_var v1, theory_var v2) { }
virtual void new_diseq_eh(theory_var v1, theory_var v2) { }
virtual void display(std::ostream& out) const {}
virtual void restart_eh();
virtual void collect_statistics(::statistics & st) const {
st.update("wmaxsat num blocks", m_stats.m_num_blocks);
st.update("wmaxsat num props", m_stats.m_num_propagations);
}
virtual bool can_propagate() {
return m_propagate;
return m_propagate || m_can_propagate;
}
virtual void propagate();
bool is_optimal() const;
expr_ref mk_block();
expr_ref mk_optimal_block(svector<bool_var> const& ws, rational const& weight);
private:
void block();
void propagate(bool_var v);
void normalize();
bool max_unassigned_is_blocked();
class compare_cost {
theory_wmaxsat& m_th;

View file

@ -144,6 +144,10 @@ bool smt_logics::logic_has_horn(symbol const& s) {
return s == "HORN";
}
bool smt_logics::logic_has_pb(symbol const& s) {
return s == "QF_FD" || s == "ALL";
}
bool smt_logics::logic_has_datatype(symbol const& s) {
return s == "QF_FD";
}

View file

@ -32,6 +32,7 @@ public:
static bool logic_has_seq(symbol const & s);
static bool logic_has_fpa(symbol const & s);
static bool logic_has_horn(symbol const& s);
static bool logic_has_pb(symbol const& s);
static bool logic_has_fd(symbol const& s) { return s == "QF_FD"; }
static bool logic_has_datatype(symbol const& s);
};

View file

@ -154,6 +154,10 @@ lbool solver::find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>&
return l_true;
}
lbool solver::preferred_sat(expr_ref_vector const& asms, vector<expr_ref_vector>& cores) {
return check_sat(0, 0);
}
bool solver::is_literal(ast_manager& m, expr* e) {
return is_uninterp_const(e) || (m.is_not(e, e) && is_uninterp_const(e));
}

View file

@ -151,9 +151,9 @@ public:
/**
\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.
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);
@ -166,6 +166,12 @@ public:
virtual lbool find_mutexes(expr_ref_vector const& vars, vector<expr_ref_vector>& mutexes);
/**
\brief Preferential SAT. Prefer assumptions to be true, produce cores that witness cases when not all assumptions can be met.
by default, preferred sat ignores the assumptions.
*/
virtual lbool preferred_sat(expr_ref_vector const& asms, vector<expr_ref_vector>& cores);
/**
\brief Display the content of this solver.
*/

View file

@ -68,7 +68,8 @@ inline aig_lit right(aig_lit const & n) { return right(n.ptr()); }
inline unsigned to_idx(aig * p) { SASSERT(!is_var(p)); return p->m_id - FIRST_NODE_ID; }
void unmark(unsigned sz, aig * const * ns) {
static void unmark(unsigned sz, aig * const * ns) {
for (unsigned i = 0; i < sz; i++) {
ns[i]->m_mark = false;
}

View file

@ -51,6 +51,7 @@ public:
virtual result operator()(goal const & g) {
return is_unbounded(g);
}
virtual ~is_unbounded_probe() {}
};
probe * mk_is_unbounded_probe() {
@ -109,11 +110,11 @@ class add_bounds_tactic : public tactic {
void operator()(quantifier*) {}
};
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0; pc = 0; core = 0;
tactic_report report("add-bounds", *g);
bound_manager bm(m);

View file

@ -312,11 +312,11 @@ class diff_neq_tactic : public tactic {
return md;
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
SASSERT(g->is_well_sorted());
m_produce_models = g->models_enabled();
mc = 0; pc = 0; core = 0; result.reset();

View file

@ -1549,11 +1549,11 @@ class fm_tactic : public tactic {
throw tactic_exception(TACTIC_MAX_MEMORY_MSG);
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
SASSERT(g->is_well_sorted());
mc = 0; pc = 0; core = 0;
tactic_report report("fm", *g);

View file

@ -188,11 +188,11 @@ class lia2pb_tactic : public tactic {
return true;
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
SASSERT(g->is_well_sorted());
fail_if_proof_generation("lia2pb", g);
m_produce_models = g->models_enabled();

View file

@ -80,11 +80,11 @@ class normalize_bounds_tactic : public tactic {
return false;
}
virtual void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & in,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
mc = 0; pc = 0; core = 0;
bool produce_models = in->models_enabled();
bool produce_proofs = in->proofs_enabled();

View file

@ -885,11 +885,11 @@ private:
r.erase("elim_and");
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
TRACE("pb2bv", g->display(tout););
SASSERT(g->is_well_sorted());
fail_if_proof_generation("pb2bv", g);

View file

@ -819,7 +819,7 @@ class elim_uncnstr_tactic : public tactic {
m_rw = alloc(rw, m(), produce_proofs, m_vars, m_mc.get(), m_max_memory, m_max_steps);
}
virtual void operator()(goal_ref const & g,
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,

View file

@ -46,11 +46,11 @@ class fpa2bv_tactic : public tactic {
m_rw.cfg().updt_params(p);
}
virtual void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
void operator()(goal_ref const & g,
goal_ref_buffer & result,
model_converter_ref & mc,
proof_converter_ref & pc,
expr_dependency_ref & core) {
SASSERT(g->is_well_sorted());
m_proofs_enabled = g->proofs_enabled();
m_produce_models = g->models_enabled();

View file

@ -94,13 +94,13 @@ public:
};
tactic * mk_sls_tactic(ast_manager & m, params_ref const & p) {
static tactic * mk_sls_tactic(ast_manager & m, params_ref const & p) {
return and_then(fail_if_not(mk_is_qfbv_probe()), // Currently only QF_BV is supported.
clean(alloc(sls_tactic, m, p)));
}
tactic * mk_preamble(ast_manager & m, params_ref const & p) {
static tactic * mk_preamble(ast_manager & m, params_ref const & p) {
params_ref main_p;
main_p.set_bool("elim_and", true);
// main_p.set_bool("pull_cheap_ite", true);

View file

@ -32,7 +32,7 @@ Notes:
#define MEMLIMIT 300
tactic * mk_qfbv_preamble(ast_manager& m, params_ref const& p) {
static tactic * mk_qfbv_preamble(ast_manager& m, params_ref const& p) {
params_ref solve_eq_p;
// conservative guassian elimination.
@ -80,7 +80,7 @@ static tactic * main_p(tactic* t) {
}
tactic * mk_qfbv_tactic(ast_manager& m, params_ref const & p, tactic* sat, tactic* smt) {
static tactic * mk_qfbv_tactic(ast_manager& m, params_ref const & p, tactic* sat, tactic* smt) {
params_ref local_ctx_p = p;
local_ctx_p.set_bool("local_ctx", true);

View file

@ -29,7 +29,7 @@ Notes:
#include"ctx_simplify_tactic.h"
#include"cofactor_term_ite_tactic.h"
tactic * mk_qfnia_bv_solver(ast_manager & m, params_ref const & p_ref) {
static tactic * mk_qfnia_bv_solver(ast_manager & m, params_ref const & p_ref) {
params_ref p = p_ref;
p.set_bool("flat", false);
p.set_bool("hi_div0", true);
@ -51,7 +51,7 @@ tactic * mk_qfnia_bv_solver(ast_manager & m, params_ref const & p_ref) {
return r;
}
tactic * mk_qfnia_premable(ast_manager & m, params_ref const & p_ref) {
static tactic * mk_qfnia_premable(ast_manager & m, params_ref const & p_ref) {
params_ref pull_ite_p = p_ref;
pull_ite_p.set_bool("pull_cheap_ite", true);
pull_ite_p.set_bool("local_ctx", true);
@ -77,7 +77,7 @@ tactic * mk_qfnia_premable(ast_manager & m, params_ref const & p_ref) {
using_params(mk_simplify_tactic(m), simp_p));
}
tactic * mk_qfnia_sat_solver(ast_manager & m, params_ref const & p) {
static tactic * mk_qfnia_sat_solver(ast_manager & m, params_ref const & p) {
params_ref nia2sat_p = p;
nia2sat_p.set_uint("nla2bv_max_bv_size", 64);

View file

@ -104,21 +104,12 @@ tactic * mk_aufnira_tactic(ast_manager & m, params_ref const & p) {
}
tactic * mk_lra_tactic(ast_manager & m, params_ref const & p) {
#if 0
tactic * st = and_then(mk_quant_preprocessor(m),
or_else(try_for(mk_smt_tactic(), 100),
try_for(qe::mk_sat_tactic(m), 1000),
try_for(mk_smt_tactic(), 1000),
and_then(mk_qe_tactic(m), mk_smt_tactic())
));
#else
tactic * st = and_then(mk_quant_preprocessor(m),
mk_qe_lite_tactic(m, p),
cond(mk_has_quantifier_probe(),
or_else(mk_qsat_tactic(m, p),
and_then(mk_qe_tactic(m), mk_smt_tactic())),
mk_smt_tactic()));
#endif
st->updt_params(p);
return st;
}

View file

@ -31,11 +31,11 @@ Notes:
#include"ufbv_tactic.h"
tactic * mk_der_fp_tactic(ast_manager & m, params_ref const & p) {
static tactic * mk_der_fp_tactic(ast_manager & m, params_ref const & p) {
return repeat(and_then(mk_der_tactic(m), mk_simplify_tactic(m, p)));
}
tactic * mk_ufbv_preprocessor_tactic(ast_manager & m, params_ref const & p) {
static tactic * mk_ufbv_preprocessor_tactic(ast_manager & m, params_ref const & p) {
params_ref no_elim_and(p);
no_elim_and.set_bool("elim_and", false);

View file

@ -23,8 +23,6 @@ Notes:
class ast_manager;
class tactic;
tactic * mk_ufbv_preprocessor_tactic(ast_manager & m, params_ref const & p = params_ref());
tactic * mk_ufbv_tactic(ast_manager & m, params_ref const & p = params_ref());
/*

View file

@ -795,8 +795,9 @@ void mpf_manager::fma(mpf_rounding_mode rm, mpf const & x, mpf const & y, mpf co
set(o, z);
}
else if (is_zero(x) || is_zero(y)) {
if (is_zero(z) && rm != MPF_ROUND_TOWARD_NEGATIVE)
mk_pzero(x.ebits, x.sbits, o);
bool xy_sgn = is_neg(x) ^ is_neg(y);
if (is_zero(z) && xy_sgn ^ is_neg(z))
mk_zero(x.ebits, x.sbits, rm != MPF_ROUND_TOWARD_NEGATIVE, o);
else
set(o, z);
}
@ -1224,7 +1225,7 @@ void mpf_manager::renormalize(unsigned ebits, unsigned sbits, mpf_exp_t & exp, m
m_mpz_manager.machine_div2k(sig, 1);
exp++;
}
const mpz & pl = m_powers2(sbits-1);
while (m_mpz_manager.lt(sig, pl)) {
m_mpz_manager.mul2k(sig, 1);
@ -1235,7 +1236,7 @@ void mpf_manager::renormalize(unsigned ebits, unsigned sbits, mpf_exp_t & exp, m
void mpf_manager::partial_remainder(mpf & x, mpf const & y, mpf_exp_t const & exp_diff, bool partial) {
unsigned ebits = x.ebits;
unsigned sbits = x.sbits;
SASSERT(-1 <= exp_diff && exp_diff < INT64_MAX);
SASSERT(exp_diff < ebits+sbits || partial);
@ -1252,7 +1253,7 @@ void mpf_manager::partial_remainder(mpf & x, mpf const & y, mpf_exp_t const & ex
SASSERT(m_mpz_manager.lt(y.significand, m_powers2(sbits)));
SASSERT(m_mpz_manager.ge(y.significand, m_powers2(sbits - 1)));
// 1. Compute a/b
// 1. Compute a/b
bool x_div_y_sgn = x.sign != y.sign;
mpf_exp_t x_div_y_exp = D;
scoped_mpz x_sig_shifted(m_mpz_manager), x_div_y_sig_lrg(m_mpz_manager), x_div_y_rem(m_mpz_manager);
@ -1271,7 +1272,7 @@ void mpf_manager::partial_remainder(mpf & x, mpf const & y, mpf_exp_t const & ex
mpf_exp_t Q_exp = x_div_y_exp;
scoped_mpz Q_sig(m_mpz_manager), Q_rem(m_mpz_manager);
unsigned Q_shft = (sbits-1) + (sbits+3) - (unsigned) (partial ? N :Q_exp);
if (partial) {
if (partial) {
// Round according to MPF_ROUND_TOWARD_ZERO
SASSERT(0 < N && N < Q_exp && Q_exp < INT_MAX);
m_mpz_manager.machine_div2k(x_div_y_sig_lrg, Q_shft, Q_sig);
@ -1294,7 +1295,7 @@ void mpf_manager::partial_remainder(mpf & x, mpf const & y, mpf_exp_t const & ex
TRACE("mpf_dbg_rem", tout << "Q_exp=" << Q_exp << std::endl;
tout << "Q_sig=" << m_mpz_manager.to_string(Q_sig) << std::endl;
tout << "Q=" << to_string_hexfloat(Q_sgn, Q_exp, Q_sig, ebits, sbits, 0) << std::endl;);
if ((D == -1 || partial) && m_mpz_manager.is_zero(Q_sig))
return; // This means x % y = x.
@ -1308,7 +1309,7 @@ void mpf_manager::partial_remainder(mpf & x, mpf const & y, mpf_exp_t const & ex
bool YQ_sgn = x.sign;
scoped_mpz YQ_sig(m_mpz_manager);
mpf_exp_t YQ_exp = Q_exp + y.exponent;
m_mpz_manager.mul(y.significand, Q_sig, YQ_sig);
m_mpz_manager.mul(y.significand, Q_sig, YQ_sig);
renormalize(ebits, 2*sbits-1, YQ_exp, YQ_sig); // YQ_sig has `sbits-1' extra bits.
(void)YQ_sgn;
@ -1317,11 +1318,11 @@ void mpf_manager::partial_remainder(mpf & x, mpf const & y, mpf_exp_t const & ex
tout << "YQ_sig=" << m_mpz_manager.to_string(YQ_sig) << std::endl;
tout << "YQ=" << to_string_hexfloat(YQ_sgn, YQ_exp, YQ_sig, ebits, sbits, sbits-1) << std::endl;);
// `sbits-1' extra bits in YQ_sig.
// `sbits-1' extra bits in YQ_sig.
SASSERT(m_mpz_manager.lt(YQ_sig, m_powers2(2*sbits-1)));
SASSERT(m_mpz_manager.ge(YQ_sig, m_powers2(2*sbits-2)) || YQ_exp <= mk_bot_exp(ebits));
// 4. Compute X-Y*Q
// 4. Compute X-Y*Q
mpf_exp_t X_YQ_exp = x.exponent;
scoped_mpz X_YQ_sig(m_mpz_manager);
mpf_exp_t exp_delta = exp(x) - YQ_exp;
@ -1339,14 +1340,14 @@ void mpf_manager::partial_remainder(mpf & x, mpf const & y, mpf_exp_t const & ex
SASSERT(m_mpz_manager.ge(minuend, m_powers2(2*sbits-2)));
SASSERT(m_mpz_manager.lt(subtrahend, m_powers2(2*sbits-1)));
SASSERT(m_mpz_manager.ge(subtrahend, m_powers2(2*sbits-2)));
if (exp_delta != 0) {
scoped_mpz sticky_rem(m_mpz_manager);
m_mpz_manager.set(sticky_rem, 0);
if (exp_delta > sbits+5)
sticky_rem.swap(subtrahend);
sticky_rem.swap(subtrahend);
else if (exp_delta > 0)
m_mpz_manager.machine_div_rem(subtrahend, m_powers2((unsigned)exp_delta), subtrahend, sticky_rem);
m_mpz_manager.machine_div_rem(subtrahend, m_powers2((unsigned)exp_delta), subtrahend, sticky_rem);
else {
SASSERT(exp_delta < 0);
exp_delta = -exp_delta;
@ -1356,7 +1357,7 @@ void mpf_manager::partial_remainder(mpf & x, mpf const & y, mpf_exp_t const & ex
m_mpz_manager.inc(subtrahend);
TRACE("mpf_dbg_rem", tout << "aligned subtrahend=" << m_mpz_manager.to_string(subtrahend) << std::endl;);
}
m_mpz_manager.sub(minuend, subtrahend, X_YQ_sig);
TRACE("mpf_dbg_rem", tout << "X_YQ_sig'=" << m_mpz_manager.to_string(X_YQ_sig) << std::endl;);
@ -1374,7 +1375,7 @@ void mpf_manager::partial_remainder(mpf & x, mpf const & y, mpf_exp_t const & ex
tout << "subtrahend=" << m_mpz_manager.to_string(subtrahend) << std::endl;
tout << "X_YQ_sgn=" << X_YQ_sgn << std::endl;
tout << "X_YQ_exp=" << X_YQ_exp << std::endl;
tout << "X_YQ_sig=" << m_mpz_manager.to_string(X_YQ_sig) << std::endl;
tout << "X_YQ_sig=" << m_mpz_manager.to_string(X_YQ_sig) << std::endl;
tout << "X-YQ=" << to_string_hexfloat(X_YQ_sgn, X_YQ_exp, X_YQ_sig, ebits, sbits, sbits-1) << std::endl;);
// `sbits-1' extra bits in X_YQ_sig
@ -1384,7 +1385,7 @@ void mpf_manager::partial_remainder(mpf & x, mpf const & y, mpf_exp_t const & ex
TRACE("mpf_dbg_rem", tout << "final sticky=" << m_mpz_manager.to_string(rnd_bits) << std::endl; );
// Round to nearest, ties to even.
if (m_mpz_manager.eq(rnd_bits, mpz(32))) { // tie.
if (m_mpz_manager.eq(rnd_bits, mpz(32))) { // tie.
if (m_mpz_manager.is_odd(X_YQ_sig)) {
m_mpz_manager.inc(X_YQ_sig);
}
@ -1430,7 +1431,7 @@ void mpf_manager::rem(mpf const & x, mpf const & y, mpf & o) {
mpf_exp_t D;
do {
if (ST0.exponent() < ST1.exponent() - 1) {
D = 0;
D = 0;
}
else {
D = ST0.exponent() - ST1.exponent();
@ -1889,7 +1890,7 @@ void mpf_manager::round(mpf_rounding_mode rm, mpf & o) {
const mpz & p_m1 = m_powers2(o.sbits+2);
const mpz & p_m2 = m_powers2(o.sbits+3);
(void)p_m1;
(void)p_m1;
TRACE("mpf_dbg", tout << "p_m1 = " << m_mpz_manager.to_string(p_m1) << std::endl <<
"p_m2 = " << m_mpz_manager.to_string(p_m2) << std::endl;);

View file

@ -20,7 +20,7 @@ Revision History:
#include "common_msgs.h"
reslimit::reslimit():
m_cancel(false),
m_cancel(0),
m_count(0),
m_limit(0) {
}
@ -29,7 +29,6 @@ uint64 reslimit::count() const {
return m_count;
}
bool reslimit::inc() {
++m_count;
return m_cancel == 0 && (m_limit == 0 || m_count <= m_limit);
@ -46,7 +45,7 @@ void reslimit::push(unsigned delta_limit) {
new_limit = 0;
}
m_limits.push_back(m_limit);
m_limit = m_limit==0?new_limit:std::min(new_limit, m_limit);
m_limit = m_limit==0 ? new_limit : std::min(new_limit, m_limit);
m_cancel = 0;
}
@ -71,14 +70,14 @@ char const* reslimit::get_cancel_msg() const {
void reslimit::push_child(reslimit* r) {
#pragma omp critical (reslimit_cancel)
{
m_children.push_back(r);
m_children.push_back(r);
}
}
void reslimit::pop_child() {
#pragma omp critical (reslimit_cancel)
{
m_children.pop_back();
m_children.pop_back();
}
}
@ -99,7 +98,7 @@ void reslimit::reset_cancel() {
void reslimit::inc_cancel() {
#pragma omp critical (reslimit_cancel)
{
{
set_cancel(m_cancel+1);
}
}
@ -114,8 +113,8 @@ void reslimit::dec_cancel() {
}
}
void reslimit::set_cancel(unsigned f) {
m_cancel = f;
void reslimit::set_cancel(unsigned f) {
m_cancel = f;
for (unsigned i = 0; i < m_children.size(); ++i) {
m_children[i]->set_cancel(f);
}

View file

@ -29,8 +29,8 @@ class reslimit {
ptr_vector<reslimit> m_children;
void set_cancel(unsigned f);
public:
public:
reslimit();
void push(unsigned delta_limit);
void pop();
@ -39,7 +39,7 @@ public:
bool inc();
bool inc(unsigned offset);
uint64 count() const;
uint64 count() const;
bool get_cancel_flag() const { return m_cancel > 0; }

View file

@ -73,6 +73,7 @@ struct scoped_timer::imp {
pthread_cond_t m_cond;
unsigned m_ms;
bool m_initialized;
bool m_signal_sent;
#else
// Other
#endif
@ -119,10 +120,18 @@ struct scoped_timer::imp {
pthread_mutex_lock(&st->m_mutex);
st->m_initialized = true;
int e = pthread_cond_timedwait(&st->m_cond, &st->m_mutex, &end_time);
ENSURE(e == 0 || e == ETIMEDOUT);
int e = 0;
// `pthread_cond_timedwait()` may spuriously wake even if the signal
// was not sent so we loop until a timeout occurs or the signal was
// **really** sent.
while (!(e == 0 && st->m_signal_sent)) {
e = pthread_cond_timedwait(&st->m_cond, &st->m_mutex, &end_time);
ENSURE(e == 0 || e == ETIMEDOUT);
if (e == ETIMEDOUT)
break;
}
pthread_mutex_unlock(&st->m_mutex);
if (e == ETIMEDOUT)
st->m_eh->operator()();
return 0;
@ -170,6 +179,7 @@ struct scoped_timer::imp {
// Linux & FreeBSD
m_ms = ms;
m_initialized = false;
m_signal_sent = false;
ENSURE(pthread_mutex_init(&m_mutex, NULL) == 0);
ENSURE(pthread_cond_init(&m_cond, NULL) == 0);
ENSURE(pthread_create(&m_thread_id, NULL, &thread_func, this) == 0);
@ -218,6 +228,10 @@ struct scoped_timer::imp {
if (!init)
sched_yield();
}
pthread_mutex_lock(&m_mutex);
m_signal_sent = true;
pthread_mutex_unlock(&m_mutex);
// Perform signal outside of lock to avoid waking timing thread twice.
pthread_cond_signal(&m_cond);
pthread_join(m_thread_id, NULL);