3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-22 16:45:31 +00:00

Merge remote-tracking branch 'upstream/master' into lackr

This commit is contained in:
Mikolas Janota 2016-01-25 13:04:46 +00:00
commit c2edf2c5bf
30 changed files with 420 additions and 153 deletions

View file

@ -76,7 +76,6 @@ namespace api {
m_sutil(m()),
m_last_result(m()),
m_ast_trail(m()),
m_replay_stack(),
m_pmanager(m_limit) {
m_error_code = Z3_OK;
@ -100,23 +99,12 @@ namespace api {
m_fpa_fid = m().mk_family_id("fpa");
m_seq_fid = m().mk_family_id("seq");
m_dt_plugin = static_cast<datatype_decl_plugin*>(m().get_plugin(m_dt_fid));
if (!m_user_ref_count) {
m_replay_stack.push_back(0);
}
install_tactics(*this);
}
context::~context() {
m_last_obj = 0;
if (!m_user_ref_count) {
for (unsigned i = 0; i < m_replay_stack.size(); ++i) {
dealloc(m_replay_stack[i]);
}
m_ast_trail.reset();
}
reset_parser();
}

View file

@ -58,7 +58,7 @@ namespace api {
bv_util m_bv_util;
datalog::dl_decl_util m_datalog_util;
fpa_util m_fpa_util;
datatype_util m_dtutil;
datatype_util m_dtutil;
seq_util m_sutil;
// Support for old solver API
@ -67,8 +67,6 @@ namespace api {
ast_ref_vector m_last_result; //!< used when m_user_ref_count == true
ast_ref_vector m_ast_trail; //!< used when m_user_ref_count == false
unsigned_vector m_ast_lim;
ptr_vector<ast_ref_vector> m_replay_stack;
ref<api::object> m_last_obj; //!< reference to the last API object returned by the APIs
@ -123,7 +121,7 @@ namespace api {
bv_util & bvutil() { return m_bv_util; }
datalog::dl_decl_util & datalog_util() { return m_datalog_util; }
fpa_util & fpautil() { return m_fpa_util; }
datatype_util& dtutil() { return m_dtutil; }
datatype_util& dtutil() { return m_dtutil; }
seq_util& sutil() { return m_sutil; }
family_id get_basic_fid() const { return m_basic_fid; }
family_id get_array_fid() const { return m_array_fid; }
@ -181,8 +179,6 @@ namespace api {
void interrupt();
void invoke_error_handler(Z3_error_code c);
static void out_of_memory_handler(void * _ctx);
void check_sorts(ast * n);

View file

@ -9095,6 +9095,10 @@ def _coerce_seq(s, ctx=None):
if isinstance(s, str):
ctx = _get_ctx(ctx)
s = StringVal(s, ctx)
if not is_expr(s):
raise Z3Exception("Non-expression passed as a sequence")
if not is_seq(s):
raise Z3Exception("Non-sequence passed as a sequence")
return s
def _get_ctx2(a, b, ctx=None):

View file

@ -923,7 +923,8 @@ void fpa2bv_converter::mk_div(func_decl * f, unsigned num, expr * const * args,
m_bv_util.mk_bv_sub(b_exp_ext, b_lz_ext));
expr_ref quotient(m);
quotient = m.mk_app(m_bv_util.get_fid(), OP_BUDIV, a_sig_ext, b_sig_ext);
// b_sig_ext can't be 0 here, so it's safe to use OP_BUDIV_I
quotient = m.mk_app(m_bv_util.get_fid(), OP_BUDIV_I, a_sig_ext, b_sig_ext);
dbg_decouple("fpa2bv_div_quotient", quotient);

View file

@ -29,12 +29,27 @@ Notes:
expr_ref sym_expr::accept(expr* e) {
ast_manager& m = m_t.get_manager();
expr_ref result(m);
if (m_is_pred) {
switch (m_ty) {
case t_pred: {
var_subst subst(m);
subst(m_t, 1, &e, result);
break;
}
else {
case t_char:
result = m.mk_eq(e, m_t);
break;
case t_range: {
bv_util bv(m);
rational r1, r2, r3;
unsigned sz;
if (bv.is_numeral(m_t, r1, sz) && bv.is_numeral(e, r2, sz) && bv.is_numeral(m_s, r3, sz)) {
result = m.mk_bool_val((r1 <= r2) && (r2 <= r3));
}
else {
result = m.mk_and(bv.mk_ule(m_t, e), bv.mk_ule(e, m_s));
}
break;
}
}
return result;
}
@ -104,8 +119,7 @@ eautomaton* re2automaton::re2aut(expr* e) {
expr_ref v(m.mk_var(0, s), m);
expr_ref _start(bv.mk_numeral(start, nb), m);
expr_ref _stop(bv.mk_numeral(stop, nb), m);
expr_ref cond(m.mk_and(bv.mk_ule(_start, v), bv.mk_ule(v, _stop)), m);
a = alloc(eautomaton, sm, sym_expr::mk_pred(cond));
a = alloc(eautomaton, sm, sym_expr::mk_range(_start, _stop));
return a.detach();
}
else {
@ -208,7 +222,8 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
case OP_RE_RANGE:
return BR_FAILED;
case OP_RE_INTERSECT:
return BR_FAILED;
SASSERT(num_args == 2);
return mk_re_inter(args[0], args[1], result);
case OP_RE_LOOP:
return mk_re_loop(num_args, args, result);
case OP_RE_EMPTY_SET:
@ -359,7 +374,7 @@ br_status seq_rewriter::mk_seq_length(expr* a, expr_ref& result) {
es.push_back(m_autil.mk_numeral(rational(len, rational::ui64()), true));
}
result = m_autil.mk_add(es.size(), es.c_ptr());
return BR_DONE;
return BR_REWRITE2;
}
return BR_FAILED;
}
@ -703,7 +718,8 @@ br_status seq_rewriter::mk_str_stoi(expr* a, expr_ref& result) {
void seq_rewriter::add_next(u_map<expr*>& next, expr_ref_vector& trail, unsigned idx, expr* cond) {
expr* acc;
if (!m().is_true(cond) && next.find(idx, acc)) {
cond = m().mk_or(cond, acc);
expr* args[2] = { cond, acc };
cond = mk_or(m(), 2, args);
}
trail.push_back(cond);
next.insert(idx, cond);
@ -715,8 +731,14 @@ bool seq_rewriter::is_sequence(eautomaton& aut, expr_ref_vector& seq) {
unsigned state = aut.init();
uint_set visited;
eautomaton::moves mvs;
aut.get_moves_from(state, mvs, true);
while (!aut.is_final_state(state)) {
unsigned_vector states;
aut.get_epsilon_closure(state, states);
bool has_final = false;
for (unsigned i = 0; !has_final && i < states.size(); ++i) {
has_final = aut.is_final_state(states[i]);
}
aut.get_moves_from(state, mvs, true);
while (!has_final) {
if (mvs.size() != 1) {
return false;
}
@ -735,6 +757,12 @@ bool seq_rewriter::is_sequence(eautomaton& aut, expr_ref_vector& seq) {
state = mvs[0].dst();
mvs.reset();
aut.get_moves_from(state, mvs, true);
states.reset();
has_final = false;
aut.get_epsilon_closure(state, states);
for (unsigned i = 0; !has_final && i < states.size(); ++i) {
has_final = aut.is_final_state(states[i]);
}
}
return mvs.empty();
}
@ -773,6 +801,14 @@ bool seq_rewriter::is_sequence(expr* e, expr_ref_vector& seq) {
}
br_status seq_rewriter::mk_str_in_regexp(expr* a, expr* b, expr_ref& result) {
if (m_util.re.is_empty(b)) {
result = m().mk_false();
return BR_DONE;
}
if (m_util.re.is_full(b)) {
result = m().mk_true();
return BR_DONE;
}
scoped_ptr<eautomaton> aut;
expr_ref_vector seq(m());
if (!(aut = m_re2aut(b))) {
@ -817,7 +853,7 @@ br_status seq_rewriter::mk_str_in_regexp(expr* a, expr* b, expr_ref& result) {
aut->get_moves_from(state, mvs, false);
for (unsigned j = 0; j < mvs.size(); ++j) {
eautomaton::move const& mv = mvs[j];
SASSERT(mv.t());
SASSERT(mv.t());
if (mv.t()->is_char() && m().is_value(mv.t()->get_char()) && m().is_value(ch)) {
if (mv.t()->get_char() == ch) {
add_next(next, trail, mv.dst(), acc);
@ -828,7 +864,11 @@ br_status seq_rewriter::mk_str_in_regexp(expr* a, expr* b, expr_ref& result) {
}
else {
cond = mv.t()->accept(ch);
if (!m().is_true(acc)) cond = m().mk_and(acc, cond);
if (m().is_false(cond)) {
continue;
}
expr* args[2] = { cond, acc };
cond = mk_and(m(), 2, args);
add_next(next, trail, mv.dst(), cond);
}
}
@ -856,18 +896,18 @@ br_status seq_rewriter::mk_str_to_regexp(expr* a, expr_ref& result) {
return BR_FAILED;
}
br_status seq_rewriter::mk_re_concat(expr* a, expr* b, expr_ref& result) {
if (m_util.re.is_full(a) && m_util.re.is_full(b)) {
result = a;
return BR_DONE;
}
if (m_util.re.is_empty(a)) {
result = a;
return BR_DONE;
}
if (m_util.re.is_empty(b)) {
result = b;
return BR_DONE;
}
if (m_util.re.is_full(a) && m_util.re.is_full(b)) {
result = a;
return BR_DONE;
}
if (m_util.re.is_empty(a)) {
result = a;
return BR_DONE;
}
if (m_util.re.is_empty(b)) {
result = b;
return BR_DONE;
}
if (is_epsilon(a)) {
result = b;
return BR_DONE;
@ -916,6 +956,38 @@ br_status seq_rewriter::mk_re_union(expr* a, expr* b, expr_ref& result) {
}
/**
(emp n r) = emp
(r n emp) = emp
(all n r) = r
(r n all) = r
(r n r) = r
*/
br_status seq_rewriter::mk_re_inter(expr* a, expr* b, expr_ref& result) {
if (a == b) {
result = a;
return BR_DONE;
}
if (m_util.re.is_empty(a)) {
result = a;
return BR_DONE;
}
if (m_util.re.is_empty(b)) {
result = b;
return BR_DONE;
}
if (m_util.re.is_full(a)) {
result = b;
return BR_DONE;
}
if (m_util.re.is_full(b)) {
result = a;
return BR_DONE;
}
return BR_FAILED;
}
br_status seq_rewriter::mk_re_loop(unsigned num_args, expr* const* args, expr_ref& result) {
rational n1, n2;
switch (num_args) {
@ -945,13 +1017,26 @@ br_status seq_rewriter::mk_re_loop(unsigned num_args, expr* const* args, expr_re
(a* + b)* = (a + b)*
(a + b*)* = (a + b)*
(a*b*)* = (a + b)*
a+* = a*
emp* = ""
all* = all
*/
br_status seq_rewriter::mk_re_star(expr* a, expr_ref& result) {
expr* b, *c, *b1, *c1;
if (m_util.re.is_star(a) || m_util.re.is_empty(a) || m_util.re.is_full(a)) {
if (m_util.re.is_star(a) || m_util.re.is_full(a)) {
result = a;
return BR_DONE;
}
if (m_util.re.is_empty(a)) {
sort* seq_sort = 0;
VERIFY(m_util.is_re(a, seq_sort));
result = m_util.re.mk_to_re(m_util.str.mk_empty(seq_sort));
return BR_DONE;
}
if (m_util.re.is_plus(a, b)) {
result = m_util.re.mk_star(b);
return BR_DONE;
}
if (m_util.re.is_union(a, b, c)) {
if (m_util.re.is_star(b, b1)) {
result = m_util.re.mk_star(m_util.re.mk_union(b1, c));
@ -961,6 +1046,14 @@ br_status seq_rewriter::mk_re_star(expr* a, expr_ref& result) {
result = m_util.re.mk_star(m_util.re.mk_union(b, c1));
return BR_REWRITE2;
}
if (is_epsilon(b)) {
result = m_util.re.mk_star(c);
return BR_REWRITE2;
}
if (is_epsilon(c)) {
result = m_util.re.mk_star(b);
return BR_REWRITE2;
}
}
if (m_util.re.is_concat(a, b, c) &&
m_util.re.is_star(b, b1) && m_util.re.is_star(c, c1)) {
@ -972,9 +1065,34 @@ br_status seq_rewriter::mk_re_star(expr* a, expr_ref& result) {
}
/*
emp+ = emp
all+ = all
a*+ = a*
a++ = a+
a+ = aa*
*/
br_status seq_rewriter::mk_re_plus(expr* a, expr_ref& result) {
if (m_util.re.is_empty(a)) {
result = a;
return BR_DONE;
}
if (m_util.re.is_full(a)) {
result = a;
return BR_DONE;
}
if (is_epsilon(a)) {
result = a;
return BR_DONE;
}
if (m_util.re.is_plus(a)) {
result = a;
return BR_DONE;
}
if (m_util.re.is_star(a)) {
result = a;
return BR_DONE;
}
return BR_FAILED;
// result = m_util.re.mk_concat(a, m_util.re.mk_star(a));
// return BR_REWRITE2;
@ -1052,14 +1170,13 @@ bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_
rs.pop_back();
}
else {
expr_ref s2(m_util.str.mk_string(s.extract(0, s.length()-2)), m());
expr_ref s2(m_util.str.mk_string(s.extract(0, s.length()-1)), m());
rs[rs.size()-1] = s2;
}
}
else {
break;
}
TRACE("seq", tout << "change back\n";);
change = true;
lchange = true;
}

View file

@ -27,20 +27,27 @@ Notes:
#include"automaton.h"
class sym_expr {
bool m_is_pred;
enum ty {
t_char,
t_pred,
t_range
};
ty m_ty;
expr_ref m_t;
expr_ref m_s;
unsigned m_ref;
sym_expr(bool is_pred, expr_ref& t) : m_is_pred(is_pred), m_t(t), m_ref(0) {}
sym_expr(ty ty, expr_ref& t, expr_ref& s) : m_ty(ty), m_t(t), m_s(s), m_ref(0) {}
public:
expr_ref accept(expr* e);
static sym_expr* mk_char(expr_ref& t) { return alloc(sym_expr, false, t); }
static sym_expr* mk_char(ast_manager& m, expr* t) { expr_ref tr(t, m); return alloc(sym_expr, false, tr); }
static sym_expr* mk_pred(expr_ref& t) { return alloc(sym_expr, true, t); }
static sym_expr* mk_char(expr_ref& t) { return alloc(sym_expr, t_char, t, t); }
static sym_expr* mk_char(ast_manager& m, expr* t) { expr_ref tr(t, m); return mk_char(tr); }
static sym_expr* mk_pred(expr_ref& t) { return alloc(sym_expr, t_pred, t, t); }
static sym_expr* mk_range(expr_ref& lo, expr_ref& hi) { return alloc(sym_expr, t_range, lo, hi); }
void inc_ref() { ++m_ref; }
void dec_ref() { --m_ref; if (m_ref == 0) dealloc(this); }
std::ostream& display(std::ostream& out) const;
bool is_char() const { return !m_is_pred; }
bool is_pred() const { return m_is_pred; }
bool is_char() const { return m_ty == t_char; }
bool is_pred() const { return !is_char(); }
expr* get_char() const { SASSERT(is_char()); return m_t; }
};
@ -88,6 +95,7 @@ class seq_rewriter {
br_status mk_str_to_regexp(expr* a, expr_ref& result);
br_status mk_re_concat(expr* a, expr* b, expr_ref& result);
br_status mk_re_union(expr* a, expr* b, expr_ref& result);
br_status mk_re_inter(expr* a, expr* b, expr_ref& result);
br_status mk_re_star(expr* a, expr_ref& result);
br_status mk_re_plus(expr* a, expr_ref& result);
br_status mk_re_opt(expr* a, expr_ref& result);

View file

@ -612,9 +612,8 @@ func_decl * seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
func_decl_info(m_family_id, OP_STRING_CONST, num_parameters, parameters));
case OP_RE_UNION:
return mk_assoc_fun(k, arity, domain, range, k, k);
case OP_RE_CONCAT:
case OP_RE_INTERSECT:
return mk_assoc_fun(k, arity, domain, range, k, k);
case OP_SEQ_CONCAT:

View file

@ -268,6 +268,7 @@ public:
MATCH_TERNARY(is_extract);
MATCH_BINARY(is_contains);
MATCH_BINARY(is_at);
MATCH_BINARY(is_index);
MATCH_TERNARY(is_index);
MATCH_TERNARY(is_replace);
MATCH_BINARY(is_prefix);

View file

@ -43,6 +43,8 @@ Notes:
#include"model_smt2_pp.h"
#include"model_v2_pp.h"
#include"model_params.hpp"
#include"th_rewriter.h"
#include"tactic_exception.h"
func_decls::func_decls(ast_manager & m, func_decl * f):
m_decls(TAG(func_decl*, f, 0)) {
@ -1462,7 +1464,8 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions
throw ex;
}
catch (z3_exception & ex) {
throw cmd_exception(ex.msg());
m_solver->set_reason_unknown(ex.msg());
r = l_undef;
}
m_solver->set_status(r);
}
@ -1624,6 +1627,7 @@ void cmd_context::validate_model() {
TRACE("model_validate", tout << "checking\n" << mk_ismt2_pp(a, m()) << "\nresult:\n" << mk_ismt2_pp(r, m()) << "\n";);
if (m().is_true(r))
continue;
// The evaluator for array expressions is not complete
// If r contains as_array/store/map/const expressions, then we do not generate the error.
// TODO: improve evaluator for model expressions.

View file

@ -105,6 +105,8 @@ public:
// create an automaton from initial state, final states, and moves
automaton(M& m, unsigned init, unsigned_vector const& final, moves const& mvs): m(m) {
m_init = init;
m_delta.push_back(moves());
m_delta_inv.push_back(moves());
for (unsigned i = 0; i < final.size(); ++i) {
add_to_final_states(final[i]);
}
@ -331,6 +333,7 @@ public:
// Src - ET -> dst - e -> dst1 => Src - ET -> dst1 if out_degree(dst) = 1,
//
void compress() {
SASSERT(!m_delta.empty());
for (unsigned i = 0; i < m_delta.size(); ++i) {
for (unsigned j = 0; j < m_delta[i].size(); ++j) {
move const& mv = m_delta[i][j];
@ -419,6 +422,7 @@ public:
}
}
}
SASSERT(!m_delta.empty());
while (true) {
SASSERT(!m_delta.empty());
unsigned src = m_delta.size() - 1;

View file

@ -24,6 +24,7 @@ Revision History:
#include"arith_rewriter.h"
#include"bv_rewriter.h"
#include"pb_rewriter.h"
#include"seq_rewriter.h"
#include"datatype_rewriter.h"
#include"array_rewriter.h"
#include"fpa_rewriter.h"
@ -39,6 +40,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
datatype_rewriter m_dt_rw;
pb_rewriter m_pb_rw;
fpa_rewriter m_f_rw;
seq_rewriter m_seq_rw;
unsigned long long m_max_memory;
unsigned m_max_steps;
bool m_model_completion;
@ -55,7 +57,8 @@ struct evaluator_cfg : public default_rewriter_cfg {
m_ar_rw(m, p),
m_dt_rw(m),
m_pb_rw(m),
m_f_rw(m) {
m_f_rw(m),
m_seq_rw(m) {
m_b_rw.set_flat(false);
m_a_rw.set_flat(false);
m_bv_rw.set_flat(false);
@ -139,6 +142,8 @@ struct evaluator_cfg : public default_rewriter_cfg {
st = m_dt_rw.mk_eq_core(args[0], args[1], result);
else if (s_fid == m_f_rw.get_fid())
st = m_f_rw.mk_eq_core(args[0], args[1], result);
else if (s_fid == m_seq_rw.get_fid())
st = m_seq_rw.mk_eq_core(args[0], args[1], result);
if (st != BR_FAILED)
return st;
}
@ -157,6 +162,8 @@ struct evaluator_cfg : public default_rewriter_cfg {
st = m_pb_rw.mk_app_core(f, num, args, result);
else if (fid == m_f_rw.get_fid())
st = m_f_rw.mk_app_core(f, num, args, result);
else if (fid == m_seq_rw.get_fid())
st = m_seq_rw.mk_app_core(f, num, args, result);
else if (evaluate(f, num, args, result)) {
TRACE("model_evaluator", tout << "reduce_app " << f->get_name() << "\n";
for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << "\n";

View file

@ -132,7 +132,8 @@ namespace opt {
m_objective_refs(m),
m_enable_sat(false),
m_is_clausal(false),
m_pp_neat(false)
m_pp_neat(false),
m_unknown("unknown")
{
params_ref p;
p.set_bool("model", true);
@ -487,7 +488,7 @@ namespace opt {
if (m_solver.get()) {
return m_solver->reason_unknown();
}
return std::string("unknown");
return m_unknown;
}
void context::display_bounds(std::ostream& out, bounds_t const& b) const {

View file

@ -163,6 +163,7 @@ namespace opt {
symbol m_maxsat_engine;
symbol m_logic;
svector<symbol> m_labels;
std::string m_unknown;
public:
context(ast_manager& m);
virtual ~context();
@ -184,6 +185,7 @@ namespace opt {
virtual void get_labels(svector<symbol> & 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; }
virtual void display_assignment(std::ostream& out);
virtual bool is_pareto() { return m_pareto.get() != 0; }

View file

@ -290,6 +290,10 @@ namespace opt {
std::string opt_solver::reason_unknown() const {
return m_context.last_failure_as_string();
}
void opt_solver::set_reason_unknown(char const* msg) {
m_context.set_reason_unknown(msg);
}
void opt_solver::get_labels(svector<symbol> & r) {
r.reset();

View file

@ -99,6 +99,7 @@ namespace opt {
virtual void get_model(model_ref & _m);
virtual proof * get_proof();
virtual std::string reason_unknown() const;
virtual void set_reason_unknown(char const* msg);
virtual void get_labels(svector<symbol> & r);
virtual void set_progress_callback(progress_callback * callback);
virtual unsigned get_num_assertions() const;

View file

@ -432,8 +432,10 @@ namespace smt2 {
}
}
void unknown_sort(symbol id) {
std::string msg = "unknown sort '";
void unknown_sort(symbol id, char const* context = "") {
std::string msg = context;
if (context[0]) msg += ": ";
msg += "unknown sort '";
msg += id.str() + "'";
throw parser_exception(msg.c_str());
}
@ -528,12 +530,12 @@ namespace smt2 {
SASSERT(sexpr_stack().size() == stack_pos + 1);
}
sort * parse_sort_name() {
sort * parse_sort_name(char const* context = "") {
SASSERT(curr_is_identifier());
symbol id = curr_id();
psort_decl * d = m_ctx.find_psort_decl(id);
if (d == 0)
unknown_sort(id);
unknown_sort(id, context);
if (!d->has_var_params() && d->get_num_params() != 0)
throw parser_exception("sort constructor expects parameters");
sort * r = d->instantiate(pm());
@ -689,23 +691,24 @@ namespace smt2 {
next();
}
void parse_sort() {
void parse_sort(char const* context) {
unsigned stack_pos = sort_stack().size();
unsigned num_frames = 0;
do {
if (curr_is_identifier()) {
sort_stack().push_back(parse_sort_name());
sort_stack().push_back(parse_sort_name(context));
}
else if (curr_is_rparen()) {
if (num_frames == 0)
throw parser_exception("invalid sort, unexpected ')'");
if (num_frames == 0) {
throw parser_exception(std::string(context) + " invalid sort, unexpected ')'");
}
pop_sort_app_frame();
num_frames--;
}
else {
check_lparen_next("invalid sort, symbol, '_' or '(' expected");
if (!curr_is_identifier())
throw parser_exception("invalid sort, symbol or '_' expected");
throw parser_exception(std::string(context) + " invalid sort, symbol or '_' expected");
if (curr_id_is_underscore()) {
sort_stack().push_back(parse_indexed_sort());
}
@ -723,7 +726,7 @@ namespace smt2 {
unsigned sz = 0;
check_lparen_next(context);
while (!curr_is_rparen()) {
parse_sort();
parse_sort(context);
sz++;
}
next();
@ -1151,7 +1154,7 @@ namespace smt2 {
symbol_stack().push_back(curr_id());
TRACE("parse_sorted_vars", tout << "push_back curr_id(): " << curr_id() << "\n";);
next();
parse_sort();
parse_sort("invalid sorted variables");
check_rparen_next("invalid sorted variable, ')' expected");
num++;
}
@ -1243,7 +1246,7 @@ namespace smt2 {
has_as = true;
next();
symbol r = parse_indexed_identifier();
parse_sort();
parse_sort("Invalid qualified identifier");
check_rparen_next("invalid qualified identifier, ')' expected");
return r;
}
@ -1848,7 +1851,7 @@ namespace smt2 {
unsigned sort_spos = sort_stack().size();
unsigned expr_spos = expr_stack().size();
unsigned num_vars = parse_sorted_vars();
parse_sort();
parse_sort("Invalid function definition");
parse_expr();
if (m().get_sort(expr_stack().back()) != sort_stack().back())
throw parser_exception("invalid function/constant definition, sort mismatch");
@ -1936,7 +1939,7 @@ namespace smt2 {
unsigned expr_spos = expr_stack().size();
unsigned num_vars = parse_sorted_vars();
SASSERT(num_vars == m_num_bindings);
parse_sort();
parse_sort("Invalid recursive function definition");
f = m().mk_func_decl(id, num_vars, sort_stack().c_ptr() + sort_spos, sort_stack().back());
bindings.append(num_vars, expr_stack().c_ptr() + expr_spos);
ids.append(num_vars, symbol_stack().c_ptr() + sym_spos);
@ -1999,7 +2002,7 @@ namespace smt2 {
check_identifier("invalid constant definition, symbol expected");
symbol id = curr_id();
next();
parse_sort();
parse_sort("Invalid constant definition");
parse_expr();
if (m().get_sort(expr_stack().back()) != sort_stack().back())
throw parser_exception("invalid constant definition, sort mismatch");
@ -2020,7 +2023,7 @@ namespace smt2 {
next();
unsigned spos = sort_stack().size();
unsigned num_params = parse_sorts("Parsing function declaration. Expecting sort list '('");
parse_sort();
parse_sort("Invalid function declaration");
func_decl_ref f(m());
f = m().mk_func_decl(id, num_params, sort_stack().c_ptr() + spos, sort_stack().back());
sort_stack().shrink(spos);
@ -2037,7 +2040,7 @@ namespace smt2 {
check_identifier("invalid constant declaration, symbol expected");
symbol id = curr_id();
next();
parse_sort();
parse_sort("Invalid constant declaration");
SASSERT(!sort_stack().empty());
func_decl_ref c(m());
c = m().mk_const_decl(id, sort_stack().back());
@ -2300,9 +2303,9 @@ namespace smt2 {
next();
}
unsigned spos = sort_stack().size();
parse_sorts("Parsing function name. Expecting sort list startig with '(' to disambiguate function name");
parse_sorts("Invalid function name. Expecting sort list startig with '(' to disambiguate function name");
unsigned domain_size = sort_stack().size() - spos;
parse_sort();
parse_sort("Invalid function name");
func_decl * d = m_ctx.find_func_decl(id, indices.size(), indices.c_ptr(), domain_size, sort_stack().c_ptr() + spos, sort_stack().back());
sort_stack().shrink(spos);
check_rparen_next("invalid function declaration reference, ')' expected");
@ -2375,7 +2378,7 @@ namespace smt2 {
break;
}
case CPK_SORT:
parse_sort();
parse_sort("invalid command argument, sort expected");
m_curr_cmd->set_next_arg(m_ctx, sort_stack().back());
return;
case CPK_SORT_LIST: {

View file

@ -46,7 +46,7 @@ namespace smt2 {
}
m_spos++;
}
void scanner::read_comment() {
SASSERT(curr() == ';');
next();
@ -62,7 +62,7 @@ namespace smt2 {
next();
}
}
scanner::token scanner::read_quoted_symbol() {
SASSERT(curr() == '|');
bool escape = false;
@ -105,7 +105,7 @@ namespace smt2 {
}
}
}
scanner::token scanner::read_symbol() {
SASSERT(m_normalized[static_cast<unsigned>(curr())] == 'a' || curr() == ':' || curr() == '-');
m_string.reset();
@ -113,14 +113,14 @@ namespace smt2 {
next();
return read_symbol_core();
}
scanner::token scanner::read_number() {
SASSERT('0' <= curr() && curr() <= '9');
rational q(1);
m_number = rational(curr() - '0');
next();
bool is_float = false;
while (true) {
char c = curr();
if ('0' <= c && c <= '9') {
@ -139,7 +139,7 @@ namespace smt2 {
break;
}
}
if (is_float)
if (is_float)
m_number /= q;
TRACE("scanner", tout << "new number: " << m_number << "\n";);
return is_float ? FLOAT_TOKEN : INT_TOKEN;
@ -160,14 +160,14 @@ namespace smt2 {
return read_symbol_core();
}
}
scanner::token scanner::read_string() {
SASSERT(curr() == '\"');
next();
m_string.reset();
while (true) {
char c = curr();
if (c == EOF)
if (c == EOF)
throw scanner_exception("unexpected end of string", m_line, m_spos);
if (c == '\n') {
new_line();
@ -183,7 +183,7 @@ namespace smt2 {
next();
}
}
scanner::token scanner::read_bv_literal() {
SASSERT(curr() == '#');
next();
@ -200,7 +200,7 @@ namespace smt2 {
}
else if ('a' <= c && c <= 'f') {
m_number *= rational(16);
m_number += rational(10 + (c - 'a'));
m_number += rational(10 + (c - 'a'));
}
else if ('A' <= c && c <= 'F') {
m_number *= rational(16);
@ -236,9 +236,9 @@ namespace smt2 {
throw scanner_exception("invalid bit-vector literal, expecting 'x' or 'b'", m_line, m_spos);
}
}
scanner::scanner(cmd_context & ctx, std::istream& stream, bool interactive):
m_interactive(interactive),
m_interactive(interactive),
m_spos(0),
m_curr(0), // avoid Valgrind warning
m_line(1),
@ -248,7 +248,7 @@ namespace smt2 {
m_bend(0),
m_stream(stream),
m_cache_input(false) {
m_smtlib2_compliant = ctx.params().m_smtlib2_compliant;
for (int i = 0; i < 256; ++i) {
@ -287,7 +287,7 @@ namespace smt2 {
m_normalized[static_cast<int>('/')] = 'a';
next();
}
scanner::token scanner::scan() {
while (true) {
signed char c = curr();

View file

@ -60,6 +60,8 @@ class inc_sat_solver : public solver {
model_converter_ref m_mc2;
expr_dependency_ref m_dep_core;
svector<double> m_weights;
std::string m_unknown;
typedef obj_map<expr, sat::literal> dep2asm_t;
public:
@ -73,7 +75,8 @@ public:
m_map(m),
m_bb_rewriter(m, p),
m_num_scopes(0),
m_dep_core(m) {
m_dep_core(m),
m_unknown("no reason given") {
m_params.set_bool("elim_vars", false);
m_solver.updt_params(m_params);
params_ref simp2_p = p;
@ -243,8 +246,12 @@ public:
UNREACHABLE();
return 0;
}
virtual std::string reason_unknown() const {
return "no reason given";
return m_unknown;
}
virtual void set_reason_unknown(char const* msg) {
m_unknown = msg;
}
virtual void get_labels(svector<symbol> & r) {
}

View file

@ -72,6 +72,7 @@ namespace smt {
m_not_l(null_literal),
m_conflict_resolution(mk_conflict_resolution(m, *this, m_dyn_ack_manager, p, m_assigned_literals, m_watches)),
m_unsat_proof(m),
m_unknown("unknown"),
m_unsat_core(m),
#ifdef Z3DEBUG
m_trail_enabled(true),
@ -4110,8 +4111,7 @@ namespace smt {
m_fingerprints.display(tout);
);
failure fl = get_last_search_failure();
if (fl == TIMEOUT || fl == MEMOUT || fl == CANCELED || fl == NUM_CONFLICTS) {
// don't generate model.
if (fl == MEMOUT || fl == CANCELED || fl == TIMEOUT || fl == NUM_CONFLICTS) {
return;
}
@ -4126,7 +4126,6 @@ namespace smt {
if (m_fparams.m_model_compact)
m_proto_model->compress();
TRACE("mbqi_bug", tout << "after cleanup:\n"; model_pp(tout, *m_proto_model););
//SASSERT(validate_model());
}
}

View file

@ -71,6 +71,7 @@ namespace smt {
std::ostream& display_last_failure(std::ostream& out) const;
std::string last_failure_as_string() const;
void set_reason_unknown(char const* msg) { m_unknown = msg; }
void set_progress_callback(progress_callback *callback);
@ -197,6 +198,7 @@ namespace smt {
// -----------------------------------
proto_model_ref m_proto_model;
model_ref m_model;
std::string m_unknown;
void mk_proto_model(lbool r);
struct scoped_mk_model;

View file

@ -62,7 +62,7 @@ namespace smt {
std::string context::last_failure_as_string() const {
std::string r;
switch(m_last_search_failure) {
case OK: r = "ok"; break;
case OK: r = m_unknown; break;
case TIMEOUT: r = "timeout"; break;
case MEMOUT: r = "memout"; break;
case CANCELED: r = "canceled"; break;
@ -79,7 +79,7 @@ namespace smt {
break;
}
case QUANTIFIERS: r = "(incomplete quantifiers)"; break;
case UNKNOWN: r = "incomplete"; break;
case UNKNOWN: r = m_unknown; break;
}
return r;
}
@ -238,7 +238,7 @@ namespace smt {
out << "equivalence classes:\n";
first = false;
}
out << "#" << n->get_id() << " -> #" << r->get_id() << "\n";
out << "#" << n->get_id() << " -> #" << r->get_id() << ": ";
out << mk_pp(n, m_manager) << " -> " << mk_pp(r, m_manager) << "\n";
}
}

View file

@ -123,6 +123,10 @@ namespace smt {
return m_kernel.last_failure_as_string();
}
void set_reason_unknown(char const* msg) {
m_kernel.set_reason_unknown(msg);
}
void get_assignments(expr_ref_vector & result) {
m_kernel.get_assignments(result);
}
@ -284,6 +288,10 @@ namespace smt {
return m_imp->last_failure_as_string();
}
void kernel::set_reason_unknown(char const* msg) {
m_imp->set_reason_unknown(msg);
}
void kernel::get_assignments(expr_ref_vector & result) {
m_imp->get_assignments(result);
}

View file

@ -155,6 +155,12 @@ namespace smt {
*/
std::string last_failure_as_string() const;
/**
\brief Set the reason for unknown.
*/
void set_reason_unknown(char const* msg);
/**
\brief Return the set of formulas assigned by the kernel.
*/

View file

@ -95,6 +95,10 @@ namespace smt {
return m_context.last_failure_as_string();
}
virtual void set_reason_unknown(char const* msg) {
m_context.set_reason_unknown(msg);
}
virtual void get_labels(svector<symbol> & r) {
buffer<symbol> tmp;
m_context.get_relevant_labels(0, tmp);

View file

@ -221,6 +221,11 @@ final_check_status theory_seq::final_check_eh() {
TRACE("seq", tout << ">>propagate_automata\n";);
return FC_CONTINUE;
}
if (!check_extensionality()) {
++m_stats.m_extensionality;
TRACE("seq", tout << ">>extensionality\n";);
return FC_CONTINUE;
}
if (is_solved()) {
TRACE("seq", tout << ">>is_solved\n";);
return FC_DONE;
@ -239,9 +244,9 @@ bool theory_seq::branch_variable() {
unsigned k = (i + start) % sz;
eq const& e = m_eqs[k];
unsigned id = e.id();
TRACE("seq", tout << e.ls() << " = " << e.rs() << "\n";);
s = find_branch_start(2*id);
TRACE("seq", tout << s << " " << 2*id << ": " << e.ls() << " = " << e.rs() << "\n";);
bool found = find_branch_candidate(s, e.dep(), e.ls(), e.rs());
insert_branch_start(2*id, s);
if (found) {
@ -292,11 +297,14 @@ bool theory_seq::find_branch_candidate(unsigned& start, dependency* dep, expr_re
expr_ref v0(m);
v0 = m_util.str.mk_empty(m.get_sort(l));
if (can_be_equal(ls.size() - 1, ls.c_ptr() + 1, rs.size(), rs.c_ptr()) && l_false != assume_equality(l, v0)) {
TRACE("seq", tout << mk_pp(l, m) << " " << v0 << "\n";);
return true;
literal_vector lits;
if (can_be_equal(ls.size() - 1, ls.c_ptr() + 1, rs.size(), rs.c_ptr())) {
if (l_false != assume_equality(l, v0)) {
TRACE("seq", tout << mk_pp(l, m) << " " << v0 << "\n";);
return true;
}
lits.push_back(~mk_eq_empty(l));
}
// start = 0;
for (; start < rs.size(); ++start) {
unsigned j = start;
SASSERT(!m_util.str.is_concat(rs[j]));
@ -320,11 +328,11 @@ bool theory_seq::find_branch_candidate(unsigned& start, dependency* dep, expr_re
all_units &= m_util.str.is_unit(rs[j]);
}
if (all_units) {
literal_vector lits;
lits.push_back(~mk_eq_empty(l));
for (unsigned i = 0; i < rs.size(); ++i) {
v0 = mk_concat(i + 1, rs.c_ptr());
lits.push_back(~mk_eq(l, v0, false));
if (can_be_equal(ls.size() - 1, ls.c_ptr() + 1, rs.size() - i - 1, rs.c_ptr() + i + 1)) {
v0 = mk_concat(i + 1, rs.c_ptr());
lits.push_back(~mk_eq(l, v0, false));
}
}
set_conflict(dep, lits);
TRACE("seq", tout << mk_pp(l, m) << " " << v0 << "\n";);
@ -501,11 +509,23 @@ expr_ref theory_seq::mk_nth(expr* s, expr* idx) {
}
expr_ref theory_seq::mk_last(expr* s) {
zstring str;
if (m_util.str.is_string(s, str) && str.length() > 0) {
return expr_ref(m_util.str.mk_char(str, str.length()-1), m);
}
sort* char_sort = 0;
VERIFY(m_util.is_seq(m.get_sort(s), char_sort));
return mk_skolem(m_seq_last, s, 0, 0, char_sort);
}
expr_ref theory_seq::mk_first(expr* s) {
zstring str;
if (m_util.str.is_string(s, str) && str.length() > 0) {
return expr_ref(m_util.str.mk_string(str.extract(0, str.length()-1)), m);
}
return mk_skolem(m_seq_first, s);
}
void theory_seq::mk_decompose(expr* e, expr_ref& head, expr_ref& tail) {
expr* e1, *e2;
@ -541,6 +561,44 @@ void theory_seq::mk_decompose(expr* e, expr_ref& head, expr_ref& tail) {
}
}
/*
\brief Check extensionality (for sequences).
*/
bool theory_seq::check_extensionality() {
context& ctx = get_context();
unsigned sz = get_num_vars();
unsigned_vector seqs;
for (unsigned v = 0; v < sz; ++v) {
enode* n = get_enode(v);
expr* o1 = n->get_owner();
if (n != n->get_root()) {
continue;
}
if (!seqs.empty() && ctx.is_relevant(n) && m_util.is_seq(o1) && ctx.is_shared(n)) {
dependency* dep = 0;
expr_ref e1 = canonize(o1, dep);
for (unsigned i = 0; i < seqs.size(); ++i) {
enode* n2 = get_enode(seqs[i]);
expr* o2 = n2->get_owner();
if (m_exclude.contains(o1, o2)) {
continue;
}
expr_ref e2 = canonize(n2->get_owner(), dep);
m_lhs.reset(); m_rhs.reset();
bool change = false;
if (!m_seq_rewrite.reduce_eq(o1, o2, m_lhs, m_rhs, change)) {
m_exclude.update(o1, o2);
continue;
}
TRACE("seq", tout << mk_pp(o1, m) << " = " << mk_pp(o2, m) << "\n";);
ctx.assume_eq(n, n2);
return false;
}
}
seqs.push_back(v);
}
return true;
}
/*
- Eqs = 0
@ -634,15 +692,12 @@ void theory_seq::enforce_length_coherence(enode* n1, enode* n2) {
expr* o1 = n1->get_owner();
expr* o2 = n2->get_owner();
if (m_util.str.is_concat(o1) && m_util.str.is_concat(o2)) {
//std::cout << "concats:\n" << mk_pp(o1,m) << "\n" << mk_pp(o2,m) << "\n";
return;
}
if (has_length(o1) && !has_length(o2)) {
//std::cout << "enforce length: " << mk_pp(o1,m) << " -> " << mk_pp(o2,m) << "\n";
enforce_length(n2);
}
else if (has_length(o2) && !has_length(o1)) {
//std::cout << "enforce length: " << mk_pp(o2,m) << " -> " << mk_pp(o1,m) << "\n";
enforce_length(n1);
}
}
@ -778,7 +833,6 @@ bool theory_seq::solve_eqs(unsigned i) {
bool change = false;
for (; !ctx.inconsistent() && i < m_eqs.size(); ++i) {
eq const& e = m_eqs[i];
TRACE("seq", tout << i << "\n";);
if (solve_eq(e.ls(), e.rs(), e.dep())) {
if (i + 1 != m_eqs.size()) {
eq e1 = m_eqs[m_eqs.size()-1];
@ -835,7 +889,6 @@ bool theory_seq::propagate_max_length(expr* l, expr* r, dependency* deps) {
}
rational hi;
if (is_tail(l, s, idx) && has_length(s) && m_util.str.is_empty(r) && !upper_bound(s, hi)) {
//std::cout << "max length " << mk_pp(s, m) << " " << idx << "\n";
propagate_lit(deps, 0, 0, mk_literal(m_autil.mk_le(m_util.str.mk_length(s), m_autil.mk_int(idx+1))));
return true;
}
@ -1008,7 +1061,7 @@ bool theory_seq::solve_ne(unsigned idx) {
}
TRACE("seq",
for (unsigned j = 0; j < lhs.size(); ++j) {
tout << mk_pp(lhs[j].get(), m) << " ";
tout << mk_pp(lhs[j].get(), m) << " " << mk_pp(rhs[j].get(), m) << "\n";
}
tout << "\n";
tout << n.ls(i) << " != " << n.rs(i) << "\n";);
@ -1018,10 +1071,9 @@ bool theory_seq::solve_ne(unsigned idx) {
expr* nr = rhs[j].get();
if (m_util.is_seq(nl) || m_util.is_re(nl)) {
ls.reset();
rs.reset();
SASSERT(!m_util.str.is_concat(nl));
SASSERT(!m_util.str.is_concat(nr));
ls.push_back(nl); rs.push_back(nr);
rs.reset();
m_util.str.get_concat(nl, ls);
m_util.str.get_concat(nr, rs);
new_ls.push_back(ls);
new_rs.push_back(rs);
}
@ -1253,6 +1305,7 @@ void theory_seq::collect_statistics(::statistics & st) const {
st.update("seq solve !=", m_stats.m_solve_nqs);
st.update("seq solve =", m_stats.m_solve_eqs);
st.update("seq add axiom", m_stats.m_add_axiom);
st.update("seq extensionality", m_stats.m_extensionality);
}
void theory_seq::init_model(expr_ref_vector const& es) {
@ -1539,8 +1592,9 @@ void theory_seq::propagate() {
++m_axioms_head;
}
while (!m_replay.empty() && !ctx.inconsistent()) {
(*m_replay[m_replay.size()-1])(*this);
TRACE("seq", tout << "replay at level: " << ctx.get_scope_level() << "\n";);
apply* app = m_replay[m_replay.size() - 1];
(*app)(*this);
m_replay.pop_back();
}
if (m_new_solution) {
@ -1592,7 +1646,7 @@ void theory_seq::deque_axiom(expr* n) {
lit or s = "" or !prefix(s, x*s1)
*/
void theory_seq::tightest_prefix(expr* s, expr* x, literal lit1, literal lit2) {
expr_ref s1 = mk_skolem(m_seq_first, s);
expr_ref s1 = mk_first(s);
expr_ref c = mk_last(s);
expr_ref s1c = mk_concat(s1, m_util.str.mk_unit(c));
literal s_eq_emp = mk_eq_empty(s);
@ -1628,30 +1682,34 @@ void theory_seq::tightest_prefix(expr* s, expr* x, literal lit1, literal lit2) {
(len(s) <= len(t) -> i <= len(t)-len(s))
*/
void theory_seq::add_indexof_axiom(expr* i) {
expr* s, *t, *offset;
expr* s, *t, *offset = 0;
rational r;
VERIFY(m_util.str.is_index(i, t, s, offset));
VERIFY(m_util.str.is_index(i, t, s) ||
m_util.str.is_index(i, t, s, offset));
expr_ref minus_one(m_autil.mk_int(-1), m);
expr_ref zero(m_autil.mk_int(0), m);
expr_ref xsy(m);
// offset >= len(t) => indexof(s, t, offset) = -1
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));
if (m_autil.is_numeral(offset, r) && r.is_zero()) {
if (!offset || (m_autil.is_numeral(offset, r) && r.is_zero())) {
expr_ref x = mk_skolem(m_contains_left, t, s);
expr_ref y = mk_skolem(m_contains_right, t, s);
xsy = mk_concat(x,s,y);
xsy = mk_concat(x, s, y);
literal cnt = mk_literal(m_util.str.mk_contains(t, s));
literal eq_empty = mk_eq_empty(s);
add_axiom(cnt, mk_eq(i, minus_one, false));
add_axiom(~eq_empty, mk_eq(i, zero, false));
add_axiom(eq_empty, ~mk_eq_empty(t), mk_eq(i, minus_one, false));
add_axiom(~cnt, eq_empty, mk_eq(t, xsy, false));
tightest_prefix(s, x, ~cnt);
}
else {
// offset >= len(t) => indexof(s, t, offset) = -1
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));
expr_ref x = mk_skolem(m_indexof_left, t, s, offset);
expr_ref y = mk_skolem(m_indexof_right, t, s, offset);
expr_ref indexof0(m_util.str.mk_index(y, s, zero), m);
@ -1922,18 +1980,18 @@ void theory_seq::add_extract_axiom(expr* e) {
expr_ref ls(m_util.str.mk_length(s), m);
expr_ref lx(m_util.str.mk_length(x), m);
expr_ref le(m_util.str.mk_length(e), m);
expr_ref ls_minus_i(mk_sub(ls, i), m);
expr_ref ls_minus_i_l(mk_sub(mk_sub(ls, i),l), m);
expr_ref xe = mk_concat(x, e);
expr_ref zero(m_autil.mk_int(0), m);
literal i_ge_0 = mk_literal(m_autil.mk_ge(i, zero));
literal i_ge_ls = mk_literal(m_autil.mk_ge(mk_sub(i, ls), zero));
literal l_ge_ls = mk_literal(m_autil.mk_ge(mk_sub(l, ls), zero));
literal li_ge_ls = mk_literal(m_autil.mk_ge(ls_minus_i_l, zero));
literal l_ge_zero = mk_literal(m_autil.mk_ge(l, zero));
add_axiom(~i_ge_0, i_ge_ls, mk_literal(m_util.str.mk_prefix(xe, s)));
add_axiom(~i_ge_0, i_ge_ls, mk_eq(lx, i, false));
add_axiom(~i_ge_0, i_ge_ls, ~l_ge_ls, mk_eq(le, ls_minus_i, false));
add_axiom(~i_ge_0, i_ge_ls, ~li_ge_ls, mk_eq(le, l, false));
add_axiom(~i_ge_0, i_ge_ls, l_ge_zero, mk_eq(le, zero, false));
}
@ -1947,8 +2005,8 @@ void theory_seq::add_at_axiom(expr* e) {
expr* s, *i;
VERIFY(m_util.str.is_at(e, s, i));
expr_ref x(m), y(m), lx(m), le(m), xey(m), zero(m), one(m), len_e(m), len_x(m);
x = mk_skolem(m_at_left, s);
y = mk_skolem(m_at_right, s);
x = mk_skolem(m_at_left, s, i);
y = mk_skolem(m_at_right, s, i);
xey = mk_concat(x, e, y);
zero = m_autil.mk_int(0);
one = m_autil.mk_int(1);
@ -2027,6 +2085,15 @@ literal theory_seq::mk_eq_empty(expr* _e) {
expr_ref e(_e, m);
SASSERT(m_util.is_seq(e));
expr_ref emp(m);
zstring s;
if (m_util.str.is_string(e, s)) {
if (s.length() == 0) {
return true_literal;
}
else {
return false_literal;
}
}
emp = m_util.str.mk_empty(m.get_sort(e));
return mk_equals(e, emp);
}
@ -2034,10 +2101,11 @@ literal theory_seq::mk_eq_empty(expr* _e) {
void theory_seq::add_axiom(literal l1, literal l2, literal l3, literal l4) {
context& ctx = get_context();
literal_vector lits;
if (l1 != null_literal) { ctx.mark_as_relevant(l1); lits.push_back(l1); }
if (l2 != null_literal) { ctx.mark_as_relevant(l2); lits.push_back(l2); }
if (l3 != null_literal) { ctx.mark_as_relevant(l3); lits.push_back(l3); }
if (l4 != null_literal) { ctx.mark_as_relevant(l4); lits.push_back(l4); }
if (l1 == true_literal || l2 == true_literal || l3 == true_literal || l4 == true_literal) return;
if (l1 != null_literal && l1 != false_literal) { ctx.mark_as_relevant(l1); lits.push_back(l1); }
if (l2 != null_literal && l2 != false_literal) { ctx.mark_as_relevant(l2); lits.push_back(l2); }
if (l3 != null_literal && l3 != false_literal) { ctx.mark_as_relevant(l3); lits.push_back(l3); }
if (l4 != null_literal && l4 != false_literal) { ctx.mark_as_relevant(l4); lits.push_back(l4); }
TRACE("seq", ctx.display_literals_verbose(tout << "axiom: ", lits.size(), lits.c_ptr()); tout << "\n";);
m_new_propagation = true;
++m_stats.m_add_axiom;
@ -2077,8 +2145,8 @@ void theory_seq::propagate_eq(literal lit, expr* e1, expr* e2, bool add_to_eqs)
}
TRACE("seq",
tout << mk_pp(ctx.bool_var2expr(lit.var()), m) << " => "
<< mk_pp(e1, m) << " = " << mk_pp(e2, m) << "\n";);
ctx.display_literals_verbose(tout, 1, &lit);
tout << " => " << mk_pp(e1, m) << " = " << mk_pp(e2, m) << "\n";);
justification* js =
ctx.mk_justification(
ext_theory_eq_propagation_justification(
@ -2121,7 +2189,7 @@ void theory_seq::assign_eh(bool_var v, bool is_true) {
propagate_non_empty(lit, e1);
// lit => e1 = first ++ (unit last)
expr_ref f1 = mk_skolem(m_seq_first, e1);
expr_ref f1 = mk_first(e1);
expr_ref f2 = mk_last(e1);
f = mk_concat(f1, m_util.str.mk_unit(f2));
propagate_eq(lit, e1, f, true);
@ -2231,6 +2299,7 @@ void theory_seq::push_scope_eh() {
}
void theory_seq::pop_scope_eh(unsigned num_scopes) {
context& ctx = get_context();
m_trail_stack.pop_scope(num_scopes);
theory::pop_scope_eh(num_scopes);
m_dm.pop_scope(num_scopes);
@ -2240,6 +2309,10 @@ void theory_seq::pop_scope_eh(unsigned num_scopes) {
m_nqs.pop_scope(num_scopes);
m_atoms.resize(m_atoms_lim[m_atoms_lim.size()-num_scopes]);
m_atoms_lim.shrink(m_atoms_lim.size()-num_scopes);
m_rewrite.reset();
if (ctx.get_base_level() > ctx.get_scope_level() - num_scopes) {
m_replay.reset();
}
}
void theory_seq::restart_eh() {
@ -2566,7 +2639,8 @@ bool theory_seq::add_prefix2prefix(expr* e) {
return false;
}
expr_ref emp(m_util.str.mk_empty(m.get_sort(e1)), m);
switch (assume_equality(e2, emp)) {
literal e2_is_emp = mk_eq_empty(e2);
switch (ctx.get_assignment(e2_is_emp)) {
case l_true:
return false; // done
case l_undef:
@ -2574,16 +2648,19 @@ bool theory_seq::add_prefix2prefix(expr* e) {
default:
break;
}
expr_ref head1(m), tail1(m), head2(m), tail2(m);
expr_ref head1(m), tail1(m), head2(m), tail2(m), conc(m);
mk_decompose(e1, head1, tail1);
mk_decompose(e2, head2, tail2);
conc = mk_concat(head2, tail2);
propagate_eq(~e2_is_emp, e2, conc, true);
literal lit = mk_eq(head1, head2, false);
switch (ctx.get_assignment(lit)) {
case l_true: {
literal_vector lits;
lits.push_back(~ctx.get_literal(e));
lits.push_back(~mk_eq(e2, emp, false));
lits.push_back(~e2_is_emp);
lits.push_back(lit);
propagate_lit(0, lits.size(), lits.c_ptr(), ~mk_literal(m_util.str.mk_prefix(tail1, tail2)));
return false;
@ -2610,28 +2687,32 @@ bool theory_seq::add_suffix2suffix(expr* e) {
}
expr_ref emp(m_util.str.mk_empty(m.get_sort(e1)), m);
switch (assume_equality(e2, emp)) {
literal e2_is_emp = mk_eq_empty(e2);
switch (ctx.get_assignment(e2_is_emp)) {
case l_true:
TRACE("seq", tout << mk_pp(e, m) << " " << mk_pp(e2, m) << " is empty\n";);
return false; // done
case l_undef:
ctx.force_phase(mk_eq(e2, emp, false));
TRACE("seq", tout << mk_pp(e, m) << " " << mk_pp(e2, m) << " is unassigned\n";);
ctx.force_phase(e2_is_emp);
return true; // retry
case l_false:
break;
}
expr_ref first2 = mk_skolem(m_seq_first, e2);
expr_ref first2 = mk_first(e2);
expr_ref last2 = mk_last(e2);
expr_ref first1 = mk_skolem(m_seq_first, e1);
expr_ref first1 = mk_first(e1);
expr_ref last1 = mk_last(e1);
expr_ref conc = mk_concat(first2, m_util.str.mk_unit(last2));
propagate_eq(~mk_eq(e2, emp, false), e2, conc);
propagate_eq(~e2_is_emp, e2, conc, true);
literal last_eq = mk_eq(last1, last2, false);
switch (ctx.get_assignment(last_eq)) {
case l_false:
TRACE("seq", tout << mk_pp(e, m) << " " << last1 << " = " << last2 << " is false\n";);
return false; // done
case l_undef:
TRACE("seq", tout << mk_pp(e, m) << " " << last1 << " = " << last2 << " is unassigned\n";);
ctx.force_phase(~last_eq);
return true;
case l_true:
@ -2640,9 +2721,10 @@ bool theory_seq::add_suffix2suffix(expr* e) {
literal_vector lits;
lits.push_back(~ctx.get_literal(e));
lits.push_back(~mk_eq(e2, emp, false));
lits.push_back(~e2_is_emp);
lits.push_back(last_eq);
propagate_lit(0, lits.size(), lits.c_ptr(), ~mk_literal(m_util.str.mk_suffix(first1, first2)));
TRACE("seq", tout << mk_pp(e, m) << " saturate\n";);
return false;
}

View file

@ -192,6 +192,7 @@ namespace smt {
expr_ref m_e;
public:
replay_length_coherence(ast_manager& m, expr* e) : m_e(e, m) {}
virtual ~replay_length_coherence() {}
virtual void operator()(theory_seq& th) {
th.check_length_coherence(m_e);
m_e.reset();
@ -202,6 +203,7 @@ namespace smt {
expr_ref m_e;
public:
replay_axiom(ast_manager& m, expr* e) : m_e(e, m) {}
virtual ~replay_axiom() {}
virtual void operator()(theory_seq& th) {
th.enque_axiom(m_e);
m_e.reset();
@ -239,6 +241,7 @@ namespace smt {
unsigned m_solve_nqs;
unsigned m_solve_eqs;
unsigned m_add_axiom;
unsigned m_extensionality;
};
ast_manager& m;
dependency_manager m_dm;
@ -312,6 +315,7 @@ namespace smt {
bool check_length_coherence(expr* e);
bool propagate_length_coherence(expr* e);
bool check_extensionality();
bool solve_eqs(unsigned start);
bool solve_eq(expr_ref_vector const& l, expr_ref_vector const& r, dependency* dep);
bool simplify_eq(expr_ref_vector& l, expr_ref_vector& r, dependency* dep);
@ -334,7 +338,7 @@ namespace smt {
void propagate_lit(dependency* dep, literal lit) { propagate_lit(dep, 0, 0, lit); }
void propagate_lit(dependency* dep, unsigned n, literal const* lits, literal lit);
void propagate_eq(dependency* dep, enode* n1, enode* n2);
void propagate_eq(literal lit, expr* e1, expr* e2, bool add_to_eqs = false);
void propagate_eq(literal lit, expr* e1, expr* e2, bool add_to_eqs);
void set_conflict(dependency* dep, literal_vector const& lits = literal_vector());
u_map<unsigned> m_branch_start;
@ -353,6 +357,7 @@ namespace smt {
bool is_tail(expr* a, expr*& s, unsigned& idx) const;
expr_ref mk_nth(expr* s, expr* idx);
expr_ref mk_last(expr* e);
expr_ref mk_first(expr* e);
expr_ref canonize(expr* e, dependency*& eqs);
bool canonize(expr* e, expr_ref_vector& es, dependency*& eqs);
bool canonize(expr_ref_vector const& es, expr_ref_vector& result, dependency*& eqs);

View file

@ -51,6 +51,7 @@ public:
virtual void get_model(model_ref & m) = 0;
virtual proof * get_proof() = 0;
virtual std::string reason_unknown() const = 0;
virtual void set_reason_unknown(char const* msg) = 0;
virtual void get_labels(svector<symbol> & r) = 0;
virtual ast_manager& get_manager() = 0;
};
@ -75,6 +76,7 @@ struct simple_check_sat_result : public check_sat_result {
virtual proof * get_proof();
virtual std::string reason_unknown() const;
virtual void get_labels(svector<symbol> & r);
virtual void set_reason_unknown(char const* msg) { m_unknown = msg; }
};
#endif

View file

@ -297,6 +297,11 @@ public:
return m_solver2->reason_unknown();
}
virtual void set_reason_unknown(char const* msg) {
m_solver1->set_reason_unknown(msg);
m_solver2->set_reason_unknown(msg);
}
virtual void get_labels(svector<symbol> & r) {
if (m_use_solver1_results)
return m_solver1->get_labels(r);

View file

@ -65,6 +65,7 @@ public:
virtual void get_model(model_ref & m);
virtual proof * get_proof();
virtual std::string reason_unknown() const;
virtual void set_reason_unknown(char const* msg);
virtual void get_labels(svector<symbol> & r) {}
virtual void set_progress_callback(progress_callback * callback) {}
@ -225,6 +226,12 @@ std::string tactic2solver::reason_unknown() const {
return std::string("unknown");
}
void tactic2solver::set_reason_unknown(char const* msg) {
if (m_result.get()) {
m_result->set_reason_unknown(msg);
}
}
unsigned tactic2solver::get_num_assertions() const {
return m_assertions.size();
}

View file

@ -384,7 +384,7 @@ void fpa2bv_model_converter::convert(model * bv_mdl, model * float_mdl) {
if (!seen.contains(f))
{
TRACE("fpa2bv_mc", tout << "Keeping: " << mk_ismt2_pp(f, m) << std::endl;);
func_interp * val = bv_mdl->get_func_interp(f);
func_interp * val = bv_mdl->get_func_interp(f)->copy();
float_mdl->register_decl(f, val);
}
}