mirror of
https://github.com/Z3Prover/z3
synced 2025-06-04 13:21:22 +00:00
Merge pull request #2 from wintersteiger/lackr
Imported latest master branch.
This commit is contained in:
commit
7f7185ce02
14 changed files with 616 additions and 91 deletions
|
@ -130,4 +130,8 @@ extern "C" {
|
||||||
Z3_CATCH_RETURN(0.0);
|
Z3_CATCH_RETURN(0.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
__uint64 Z3_API Z3_get_estimated_alloc_size(void) {
|
||||||
|
return memory::get_allocation_size();
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -4419,6 +4419,9 @@ extern "C" {
|
||||||
\brief Interface to simplifier.
|
\brief Interface to simplifier.
|
||||||
|
|
||||||
Provides an interface to the AST simplifier used by Z3.
|
Provides an interface to the AST simplifier used by Z3.
|
||||||
|
It returns an AST object which is equal to the argument.
|
||||||
|
The returned AST is simplified using algebraic simplificaiton rules,
|
||||||
|
such as constant propagation (propagating true/false over logical connectives).
|
||||||
|
|
||||||
def_API('Z3_simplify', AST, (_in(CONTEXT), _in(AST)))
|
def_API('Z3_simplify', AST, (_in(CONTEXT), _in(AST)))
|
||||||
*/
|
*/
|
||||||
|
@ -5964,6 +5967,13 @@ extern "C" {
|
||||||
*/
|
*/
|
||||||
double Z3_API Z3_stats_get_double_value(Z3_context c, Z3_stats s, unsigned idx);
|
double Z3_API Z3_stats_get_double_value(Z3_context c, Z3_stats s, unsigned idx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
\brief Return the estimated allocated memory in bytes.
|
||||||
|
|
||||||
|
def_API('Z3_get_estimated_alloc_size', UINT64, ())
|
||||||
|
*/
|
||||||
|
__uint64 Z3_API Z3_get_estimated_alloc_size(void);
|
||||||
|
|
||||||
/*@}*/
|
/*@}*/
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
|
|
|
@ -743,7 +743,14 @@ void bit_blaster_tpl<Cfg>::mk_srem(unsigned sz, expr * const * a_bits, expr * co
|
||||||
mk_abs(sz, a_bits, abs_a_bits);
|
mk_abs(sz, a_bits, abs_a_bits);
|
||||||
mk_abs(sz, b_bits, abs_b_bits);
|
mk_abs(sz, b_bits, abs_b_bits);
|
||||||
expr_ref_vector urem_bits(m());
|
expr_ref_vector urem_bits(m());
|
||||||
mk_urem(sz, abs_a_bits.c_ptr(), abs_b_bits.c_ptr(), urem_bits);
|
numeral n_b;
|
||||||
|
unsigned shift;
|
||||||
|
// a urem 2^n -> a & ((2^n)-1)
|
||||||
|
if (is_numeral(sz, abs_b_bits.c_ptr(), n_b) && n_b.is_power_of_two(shift)) {
|
||||||
|
mk_zero_extend(shift, abs_a_bits.c_ptr(), sz - shift, urem_bits);
|
||||||
|
} else {
|
||||||
|
mk_urem(sz, abs_a_bits.c_ptr(), abs_b_bits.c_ptr(), urem_bits);
|
||||||
|
}
|
||||||
expr_ref_vector neg_urem_bits(m());
|
expr_ref_vector neg_urem_bits(m());
|
||||||
mk_neg(sz, urem_bits.c_ptr(), neg_urem_bits);
|
mk_neg(sz, urem_bits.c_ptr(), neg_urem_bits);
|
||||||
mk_multiplexer(a_msb, sz, neg_urem_bits.c_ptr(), urem_bits.c_ptr(), out_bits);
|
mk_multiplexer(a_msb, sz, neg_urem_bits.c_ptr(), urem_bits.c_ptr(), out_bits);
|
||||||
|
|
|
@ -36,6 +36,7 @@ expr_ref sym_expr::accept(expr* e) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case t_char:
|
case t_char:
|
||||||
|
SASSERT(m.get_sort(e) == m.get_sort(m_t));
|
||||||
result = m.mk_eq(e, m_t);
|
result = m.mk_eq(e, m_t);
|
||||||
break;
|
break;
|
||||||
case t_range: {
|
case t_range: {
|
||||||
|
@ -792,8 +793,8 @@ bool seq_rewriter::is_sequence(expr* e, expr_ref_vector& seq) {
|
||||||
else if (m_util.str.is_empty(e)) {
|
else if (m_util.str.is_empty(e)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
else if (m_util.str.is_unit(e)) {
|
else if (m_util.str.is_unit(e, e1)) {
|
||||||
seq.push_back(e);
|
seq.push_back(e1);
|
||||||
}
|
}
|
||||||
else if (m_util.str.is_concat(e, e1, e2)) {
|
else if (m_util.str.is_concat(e, e1, e2)) {
|
||||||
todo.push_back(e1);
|
todo.push_back(e1);
|
||||||
|
@ -1420,6 +1421,7 @@ expr* seq_rewriter::concat_non_empty(unsigned n, expr* const* as) {
|
||||||
|
|
||||||
bool seq_rewriter::set_empty(unsigned sz, expr* const* es, bool all, expr_ref_vector& lhs, expr_ref_vector& rhs) {
|
bool seq_rewriter::set_empty(unsigned sz, expr* const* es, bool all, expr_ref_vector& lhs, expr_ref_vector& rhs) {
|
||||||
zstring s;
|
zstring s;
|
||||||
|
expr* emp = 0;
|
||||||
for (unsigned i = 0; i < sz; ++i) {
|
for (unsigned i = 0; i < sz; ++i) {
|
||||||
if (m_util.str.is_unit(es[i])) {
|
if (m_util.str.is_unit(es[i])) {
|
||||||
if (all) return false;
|
if (all) return false;
|
||||||
|
@ -1434,7 +1436,8 @@ bool seq_rewriter::set_empty(unsigned sz, expr* const* es, bool all, expr_ref_ve
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
lhs.push_back(m_util.str.mk_empty(m().get_sort(es[i])));
|
emp = emp?emp:m_util.str.mk_empty(m().get_sort(es[i]));
|
||||||
|
lhs.push_back(emp);
|
||||||
rhs.push_back(es[i]);
|
rhs.push_back(es[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,10 @@ static bool is_hex_digit(char ch, unsigned& d) {
|
||||||
d = 10 + ch - 'A';
|
d = 10 + ch - 'A';
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
if ('a' <= ch && ch <= 'f') {
|
||||||
|
d = 10 + ch - 'a';
|
||||||
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,6 +89,7 @@ static bool is_escape_char(char const *& s, unsigned& result) {
|
||||||
s += 2;
|
s += 2;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
zstring::zstring(encoding enc): m_encoding(enc) {}
|
zstring::zstring(encoding enc): m_encoding(enc) {}
|
||||||
|
|
|
@ -1069,14 +1069,7 @@ namespace datalog {
|
||||||
func_decl_set::iterator it = rels.begin(), end = rels.end();
|
func_decl_set::iterator it = rels.begin(), end = rels.end();
|
||||||
for (; it != end; ++it) {
|
for (; it != end; ++it) {
|
||||||
func_decl* f = *it;
|
func_decl* f = *it;
|
||||||
out << "(declare-rel " << f->get_name() << " (";
|
display_rel_decl(out, f);
|
||||||
for (unsigned i = 0; i < f->get_arity(); ++i) {
|
|
||||||
ast_smt2_pp(out, f->get_domain(i), env);
|
|
||||||
if (i + 1 < f->get_arity()) {
|
|
||||||
out << " ";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
out << "))\n";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (use_fixedpoint_extensions && do_declare_vars) {
|
if (use_fixedpoint_extensions && do_declare_vars) {
|
||||||
|
@ -1120,9 +1113,29 @@ namespace datalog {
|
||||||
}
|
}
|
||||||
if (use_fixedpoint_extensions) {
|
if (use_fixedpoint_extensions) {
|
||||||
for (unsigned i = 0; i < queries.size(); ++i) {
|
for (unsigned i = 0; i < queries.size(); ++i) {
|
||||||
out << "(query ";
|
expr* q = queries[i].get();
|
||||||
PP(queries[i].get());
|
func_decl_ref fn(m);
|
||||||
out << ")\n";
|
if (is_query(q)) {
|
||||||
|
fn = to_app(q)->get_decl();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
m_free_vars(q);
|
||||||
|
m_free_vars.set_default_sort(m.mk_bool_sort());
|
||||||
|
sort* const* domain = m_free_vars.c_ptr();
|
||||||
|
expr_ref qfn(m);
|
||||||
|
expr_ref_vector args(m);
|
||||||
|
fn = m.mk_fresh_func_decl(symbol("q"), symbol(""), m_free_vars.size(), domain, m.mk_bool_sort());
|
||||||
|
display_rel_decl(out, fn);
|
||||||
|
for (unsigned j = 0; j < m_free_vars.size(); ++j) {
|
||||||
|
args.push_back(m.mk_var(j, m_free_vars[j]));
|
||||||
|
}
|
||||||
|
qfn = m.mk_implies(q, m.mk_app(fn, args.size(), args.c_ptr()));
|
||||||
|
|
||||||
|
out << "(assert ";
|
||||||
|
PP(qfn);
|
||||||
|
out << ")\n";
|
||||||
|
}
|
||||||
|
out << "(query " << fn->get_name() << ")\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -1139,6 +1152,35 @@ namespace datalog {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void context::display_rel_decl(std::ostream& out, func_decl* f) {
|
||||||
|
smt2_pp_environment_dbg env(m);
|
||||||
|
out << "(declare-rel " << f->get_name() << " (";
|
||||||
|
for (unsigned i = 0; i < f->get_arity(); ++i) {
|
||||||
|
ast_smt2_pp(out, f->get_domain(i), env);
|
||||||
|
if (i + 1 < f->get_arity()) {
|
||||||
|
out << " ";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << "))\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
bool context::is_query(expr* q) {
|
||||||
|
if (!is_app(q) || !is_predicate(to_app(q)->get_decl())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
app* a = to_app(q);
|
||||||
|
for (unsigned i = 0; i < a->get_num_args(); ++i) {
|
||||||
|
if (!is_var(a->get_arg(i))) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
var* v = to_var(a->get_arg(i));
|
||||||
|
if (v->get_idx() != i) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void context::declare_vars(expr_ref_vector& rules, mk_fresh_name& fresh_names, std::ostream& out) {
|
void context::declare_vars(expr_ref_vector& rules, mk_fresh_name& fresh_names, std::ostream& out) {
|
||||||
//
|
//
|
||||||
|
|
|
@ -581,6 +581,9 @@ namespace datalog {
|
||||||
//undefined and private copy constructor and operator=
|
//undefined and private copy constructor and operator=
|
||||||
context(const context&);
|
context(const context&);
|
||||||
context& operator=(const context&);
|
context& operator=(const context&);
|
||||||
|
|
||||||
|
bool is_query(expr* e);
|
||||||
|
void display_rel_decl(std::ostream& out, func_decl* f);
|
||||||
};
|
};
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -847,6 +847,9 @@ namespace smt {
|
||||||
setup_AUFLIA(false);
|
setup_AUFLIA(false);
|
||||||
setup_datatypes();
|
setup_datatypes();
|
||||||
setup_bv();
|
setup_bv();
|
||||||
|
setup_dl();
|
||||||
|
setup_seq();
|
||||||
|
setup_card();
|
||||||
setup_fpa();
|
setup_fpa();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -64,6 +64,34 @@ bool theory_seq::solution_map::is_root(expr* e) const {
|
||||||
return !m_map.contains(e);
|
return !m_map.contains(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// e1 -> ... -> e2
|
||||||
|
// e2 -> e3
|
||||||
|
// e1 -> .... -> e3
|
||||||
|
|
||||||
|
// e1 -> ... x, e2 -> ... x
|
||||||
|
void theory_seq::solution_map::find_rec(expr* e, svector<std::pair<expr*, dependency*> >& finds) {
|
||||||
|
dependency* d = 0;
|
||||||
|
std::pair<expr*, dependency*> value(e, d);
|
||||||
|
do {
|
||||||
|
e = value.first;
|
||||||
|
d = m_dm.mk_join(d, value.second);
|
||||||
|
finds.push_back(value);
|
||||||
|
}
|
||||||
|
while (m_map.find(e, value));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool theory_seq::solution_map::find1(expr* e, expr*& r, dependency*& d) {
|
||||||
|
std::pair<expr*, dependency*> value;
|
||||||
|
if (m_map.find(e, value)) {
|
||||||
|
d = m_dm.mk_join(d, value.second);
|
||||||
|
r = value.first;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
expr* theory_seq::solution_map::find(expr* e, dependency*& d) {
|
expr* theory_seq::solution_map::find(expr* e, dependency*& d) {
|
||||||
std::pair<expr*, dependency*> value;
|
std::pair<expr*, dependency*> value;
|
||||||
d = 0;
|
d = 0;
|
||||||
|
@ -183,9 +211,9 @@ theory_seq::theory_seq(ast_manager& m):
|
||||||
m_indexof_left = "seq.indexof.left";
|
m_indexof_left = "seq.indexof.left";
|
||||||
m_indexof_right = "seq.indexof.right";
|
m_indexof_right = "seq.indexof.right";
|
||||||
m_aut_step = "aut.step";
|
m_aut_step = "aut.step";
|
||||||
m_extract_prefix = "seq.extract.prefix";
|
m_pre = "seq.pre"; // (seq.pre s l): prefix of string s of length l
|
||||||
m_at_left = "seq.at.left";
|
m_post = "seq.post"; // (seq.post s l): suffix of string s of length l
|
||||||
m_at_right = "seq.at.right";
|
m_eq = "seq.eq";
|
||||||
}
|
}
|
||||||
|
|
||||||
theory_seq::~theory_seq() {
|
theory_seq::~theory_seq() {
|
||||||
|
@ -215,21 +243,21 @@ final_check_status theory_seq::final_check_eh() {
|
||||||
TRACE("seq", tout << ">>check_length_coherence\n";);
|
TRACE("seq", tout << ">>check_length_coherence\n";);
|
||||||
return FC_CONTINUE;
|
return FC_CONTINUE;
|
||||||
}
|
}
|
||||||
if (propagate_automata()) {
|
|
||||||
++m_stats.m_propagate_automata;
|
|
||||||
TRACE("seq", tout << ">>propagate_automata\n";);
|
|
||||||
return FC_CONTINUE;
|
|
||||||
}
|
|
||||||
if (!check_extensionality()) {
|
if (!check_extensionality()) {
|
||||||
++m_stats.m_extensionality;
|
++m_stats.m_extensionality;
|
||||||
TRACE("seq", tout << ">>extensionality\n";);
|
TRACE("seq", tout << ">>extensionality\n";);
|
||||||
return FC_CONTINUE;
|
return FC_CONTINUE;
|
||||||
}
|
}
|
||||||
|
if (propagate_automata()) {
|
||||||
|
++m_stats.m_propagate_automata;
|
||||||
|
TRACE("seq", tout << ">>propagate_automata\n";);
|
||||||
|
return FC_CONTINUE;
|
||||||
|
}
|
||||||
if (is_solved()) {
|
if (is_solved()) {
|
||||||
TRACE("seq", tout << ">>is_solved\n";);
|
TRACE("seq", tout << ">>is_solved\n";);
|
||||||
return FC_DONE;
|
return FC_DONE;
|
||||||
}
|
}
|
||||||
|
TRACE("seq", tout << ">>give_up\n";);
|
||||||
return FC_GIVEUP;
|
return FC_GIVEUP;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,7 +479,7 @@ bool theory_seq::check_length_coherence(expr* e) {
|
||||||
propagate_is_conc(e, conc);
|
propagate_is_conc(e, conc);
|
||||||
assume_equality(tail, emp);
|
assume_equality(tail, emp);
|
||||||
}
|
}
|
||||||
if (!get_context().at_base_level()) {
|
else if (!get_context().at_base_level()) {
|
||||||
m_trail_stack.push(push_replay(alloc(replay_length_coherence, m, e)));
|
m_trail_stack.push(push_replay(alloc(replay_length_coherence, m, e)));
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -501,11 +529,17 @@ bool theory_seq::is_tail(expr* e, expr*& s, unsigned& idx) const {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool theory_seq::is_eq(expr* e, expr*& a, expr*& b) const {
|
bool theory_seq::is_eq(expr* e, expr*& a, expr*& b) const {
|
||||||
return is_skolem(symbol("seq.eq"), e) &&
|
return is_skolem(m_eq, e) &&
|
||||||
(a = to_app(e)->get_arg(0), b = to_app(e)->get_arg(1), true);
|
(a = to_app(e)->get_arg(0), b = to_app(e)->get_arg(1), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool theory_seq::is_pre(expr* e, expr*& s, expr*& i) {
|
||||||
|
return is_skolem(m_pre, e) && (s = to_app(e)->get_arg(0), i = to_app(e)->get_arg(1), true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
expr_ref theory_seq::mk_nth(expr* s, expr* idx) {
|
expr_ref theory_seq::mk_nth(expr* s, expr* idx) {
|
||||||
sort* char_sort = 0;
|
sort* char_sort = 0;
|
||||||
VERIFY(m_util.is_seq(m.get_sort(s), char_sort));
|
VERIFY(m_util.is_seq(m.get_sort(s), char_sort));
|
||||||
|
@ -573,29 +607,41 @@ bool theory_seq::check_extensionality() {
|
||||||
unsigned sz = get_num_vars();
|
unsigned sz = get_num_vars();
|
||||||
unsigned_vector seqs;
|
unsigned_vector seqs;
|
||||||
for (unsigned v = 0; v < sz; ++v) {
|
for (unsigned v = 0; v < sz; ++v) {
|
||||||
enode* n = get_enode(v);
|
enode* n1 = get_enode(v);
|
||||||
expr* o1 = n->get_owner();
|
expr* o1 = n1->get_owner();
|
||||||
if (n != n->get_root()) {
|
if (n1 != n1->get_root()) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!seqs.empty() && ctx.is_relevant(n) && m_util.is_seq(o1) && ctx.is_shared(n)) {
|
if (!seqs.empty() && ctx.is_relevant(n1) && m_util.is_seq(o1) && ctx.is_shared(n1)) {
|
||||||
dependency* dep = 0;
|
dependency* dep = 0;
|
||||||
expr_ref e1 = canonize(o1, dep);
|
expr_ref e1 = canonize(o1, dep);
|
||||||
for (unsigned i = 0; i < seqs.size(); ++i) {
|
for (unsigned i = 0; i < seqs.size(); ++i) {
|
||||||
enode* n2 = get_enode(seqs[i]);
|
enode* n2 = get_enode(seqs[i]);
|
||||||
expr* o2 = n2->get_owner();
|
expr* o2 = n2->get_owner();
|
||||||
if (m_exclude.contains(o1, o2)) {
|
if (m.get_sort(o1) != m.get_sort(o2)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (ctx.is_diseq(n1, n2) || m_exclude.contains(o1, o2)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
expr_ref e2 = canonize(n2->get_owner(), dep);
|
expr_ref e2 = canonize(n2->get_owner(), dep);
|
||||||
m_lhs.reset(); m_rhs.reset();
|
m_lhs.reset(); m_rhs.reset();
|
||||||
bool change = false;
|
bool change = false;
|
||||||
if (!m_seq_rewrite.reduce_eq(o1, o2, m_lhs, m_rhs, change)) {
|
if (!m_seq_rewrite.reduce_eq(e1, e2, m_lhs, m_rhs, change)) {
|
||||||
m_exclude.update(o1, o2);
|
m_exclude.update(o1, o2);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
TRACE("seq", tout << mk_pp(o1, m) << " = " << mk_pp(o2, m) << "\n";);
|
bool excluded = false;
|
||||||
ctx.assume_eq(n, n2);
|
for (unsigned j = 0; !excluded && j < m_lhs.size(); ++j) {
|
||||||
|
if (m_exclude.contains(m_lhs[j].get(), m_rhs[j].get())) {
|
||||||
|
excluded = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (excluded) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TRACE("seq", tout << m_lhs << " = " << m_rhs << "\n";);
|
||||||
|
ctx.assume_eq(n1, n2);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -670,7 +716,7 @@ void theory_seq::set_conflict(dependency* dep, literal_vector const& _lits) {
|
||||||
enode_pair_vector eqs;
|
enode_pair_vector eqs;
|
||||||
literal_vector lits(_lits);
|
literal_vector lits(_lits);
|
||||||
linearize(dep, eqs, lits);
|
linearize(dep, eqs, lits);
|
||||||
TRACE("seq", ctx.display_literals_verbose(tout, lits.size(), lits.c_ptr()); if (!lits.empty()) tout << "\n"; display_deps(tout, dep); ;);
|
TRACE("seq", display_deps(tout, lits, eqs););
|
||||||
m_new_propagation = true;
|
m_new_propagation = true;
|
||||||
ctx.set_conflict(
|
ctx.set_conflict(
|
||||||
ctx.mk_justification(
|
ctx.mk_justification(
|
||||||
|
@ -720,6 +766,7 @@ bool theory_seq::simplify_eq(expr_ref_vector& ls, expr_ref_vector& rs, dependenc
|
||||||
context& ctx = get_context();
|
context& ctx = get_context();
|
||||||
expr_ref_vector lhs(m), rhs(m);
|
expr_ref_vector lhs(m), rhs(m);
|
||||||
bool changed = false;
|
bool changed = false;
|
||||||
|
TRACE("seq", tout << ls << " = " << rs << "\n";);
|
||||||
if (!m_seq_rewrite.reduce_eq(ls, rs, lhs, rhs, changed)) {
|
if (!m_seq_rewrite.reduce_eq(ls, rs, lhs, rhs, changed)) {
|
||||||
// equality is inconsistent.
|
// equality is inconsistent.
|
||||||
TRACE("seq", tout << ls << " != " << rs << "\n";);
|
TRACE("seq", tout << ls << " != " << rs << "\n";);
|
||||||
|
@ -739,9 +786,10 @@ bool theory_seq::simplify_eq(expr_ref_vector& ls, expr_ref_vector& rs, dependenc
|
||||||
expr_ref li(lhs[i].get(), m);
|
expr_ref li(lhs[i].get(), m);
|
||||||
expr_ref ri(rhs[i].get(), m);
|
expr_ref ri(rhs[i].get(), m);
|
||||||
if (solve_unit_eq(li, ri, deps)) {
|
if (solve_unit_eq(li, ri, deps)) {
|
||||||
// skip
|
// no-op
|
||||||
}
|
}
|
||||||
else if (m_util.is_seq(li) || m_util.is_re(li)) {
|
else if (m_util.is_seq(li) || m_util.is_re(li)) {
|
||||||
|
reduce_length(li, ri);
|
||||||
m_eqs.push_back(mk_eqdep(li, ri, deps));
|
m_eqs.push_back(mk_eqdep(li, ri, deps));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -769,6 +817,23 @@ bool theory_seq::solve_unit_eq(expr_ref_vector const& l, expr_ref_vector const&
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool theory_seq::reduce_length(expr* l, expr* r) {
|
||||||
|
expr* l2, *r2;
|
||||||
|
expr_ref len1(m), len2(m);
|
||||||
|
literal_vector lits;
|
||||||
|
m_util.str.is_concat(l, l, l2);
|
||||||
|
m_util.str.is_concat(r, r, r2);
|
||||||
|
if (get_length(l, len1, lits) &&
|
||||||
|
get_length(r, len2, lits) && len1 == len2) {
|
||||||
|
TRACE("seq", tout << "Propagate equal lengths\n";);
|
||||||
|
//propagate_eq(lits, l, r, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool theory_seq::solve_unit_eq(expr* l, expr* r, dependency* deps) {
|
bool theory_seq::solve_unit_eq(expr* l, expr* r, dependency* deps) {
|
||||||
if (l == r) {
|
if (l == r) {
|
||||||
return true;
|
return true;
|
||||||
|
@ -996,6 +1061,58 @@ bool theory_seq::solve_binary_eq(expr_ref_vector const& ls, expr_ref_vector cons
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool theory_seq::get_length(expr* e, expr_ref& len, literal_vector& lits) {
|
||||||
|
context& ctx = get_context();
|
||||||
|
expr* s, *i, *l;
|
||||||
|
if (m_util.str.is_extract(e, s, i, l)) {
|
||||||
|
// 0 <= i <= len(s), 0 <= l, i + l <= len(s)
|
||||||
|
expr_ref zero(m_autil.mk_int(0), m);
|
||||||
|
expr_ref ls(m_util.str.mk_length(s), m);
|
||||||
|
expr_ref ls_minus_i_l(mk_sub(mk_sub(ls, i),l), m);
|
||||||
|
literal i_ge_0 = mk_literal(m_autil.mk_ge(i, zero));
|
||||||
|
literal i_lt_len_s = ~mk_literal(m_autil.mk_ge(mk_sub(i, 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));
|
||||||
|
if (ctx.get_assignment(i_ge_0) == l_true &&
|
||||||
|
ctx.get_assignment(i_lt_len_s) == l_true &&
|
||||||
|
ctx.get_assignment(li_ge_ls) == l_true &&
|
||||||
|
ctx.get_assignment(l_ge_zero) == l_true) {
|
||||||
|
len = l;
|
||||||
|
lits.push_back(i_ge_0); lits.push_back(i_lt_len_s); lits.push_back(li_ge_ls); lits.push_back(l_ge_zero);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_util.str.is_at(e, s, i)) {
|
||||||
|
// has length 1 if 0 <= i < len(s)
|
||||||
|
expr_ref zero(m_autil.mk_int(0), m);
|
||||||
|
literal i_ge_0 = mk_literal(m_autil.mk_ge(i, zero));
|
||||||
|
literal i_lt_len_s = ~mk_literal(m_autil.mk_ge(mk_sub(i, m_util.str.mk_length(s)), zero));
|
||||||
|
if (ctx.get_assignment(i_ge_0) == l_true &&
|
||||||
|
ctx.get_assignment(i_lt_len_s) == l_true) {
|
||||||
|
len = m_autil.mk_int(1);
|
||||||
|
lits.push_back(i_ge_0); lits.push_back(i_lt_len_s);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (is_pre(e, s, i)) {
|
||||||
|
expr_ref zero(m_autil.mk_int(0), m);
|
||||||
|
literal i_ge_0 = mk_literal(m_autil.mk_ge(i, zero));
|
||||||
|
literal i_lt_len_s = ~mk_literal(m_autil.mk_ge(mk_sub(i, m_util.str.mk_length(s)), zero));
|
||||||
|
if (ctx.get_assignment(i_ge_0) == l_true &&
|
||||||
|
ctx.get_assignment(i_lt_len_s) == l_true) {
|
||||||
|
len = i;
|
||||||
|
lits.push_back(i_ge_0); lits.push_back(i_lt_len_s);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_util.str.is_unit(e)) {
|
||||||
|
len = m_autil.mk_int(1);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
bool theory_seq::solve_nqs(unsigned i) {
|
bool theory_seq::solve_nqs(unsigned i) {
|
||||||
context & ctx = get_context();
|
context & ctx = get_context();
|
||||||
for (; !ctx.inconsistent() && i < m_nqs.size(); ++i) {
|
for (; !ctx.inconsistent() && i < m_nqs.size(); ++i) {
|
||||||
|
@ -1046,7 +1163,7 @@ bool theory_seq::solve_ne(unsigned idx) {
|
||||||
change = canonize(n.rs(i), rs, deps) || change;
|
change = canonize(n.rs(i), rs, deps) || change;
|
||||||
|
|
||||||
if (!m_seq_rewrite.reduce_eq(ls, rs, lhs, rhs, change)) {
|
if (!m_seq_rewrite.reduce_eq(ls, rs, lhs, rhs, change)) {
|
||||||
TRACE("seq", display_disequation(tout << "reduces to false", n););
|
TRACE("seq", display_disequation(tout << "reduces to false: ", n););
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else if (!change) {
|
else if (!change) {
|
||||||
|
@ -1144,16 +1261,181 @@ bool theory_seq::solve_ne(unsigned idx) {
|
||||||
if (updated) {
|
if (updated) {
|
||||||
if (num_undef_lits == 0 && new_ls.empty()) {
|
if (num_undef_lits == 0 && new_ls.empty()) {
|
||||||
TRACE("seq", tout << "conflict\n";);
|
TRACE("seq", tout << "conflict\n";);
|
||||||
|
|
||||||
|
dependency* deps1 = 0;
|
||||||
|
if (explain_eq(n.l(), n.r(), deps1)) {
|
||||||
|
new_lits.reset();
|
||||||
|
new_lits.push_back(~mk_eq(n.l(), n.r(), false));
|
||||||
|
new_deps = deps1;
|
||||||
|
TRACE("seq", tout << "conflict explained\n";);
|
||||||
|
}
|
||||||
set_conflict(new_deps, new_lits);
|
set_conflict(new_deps, new_lits);
|
||||||
SASSERT(m_new_propagation);
|
SASSERT(m_new_propagation);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_nqs.push_back(ne(new_ls, new_rs, new_lits, new_deps));
|
m_nqs.push_back(ne(n.l(), n.r(), new_ls, new_rs, new_lits, new_deps));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return updated;
|
return updated;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
theory_seq::cell* theory_seq::mk_cell(cell* p, expr* e, dependency* d) {
|
||||||
|
cell* c = alloc(cell, p, e, d);
|
||||||
|
m_all_cells.push_back(c);
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
void theory_seq::unfold(cell* c, ptr_vector<cell>& cons) {
|
||||||
|
dependency* dep = 0;
|
||||||
|
expr* a, *e1, *e2;
|
||||||
|
if (m_rep.find1(c->m_expr, a, dep)) {
|
||||||
|
cell* c1 = mk_cell(c, a, m_dm.mk_join(dep, c->m_dep));
|
||||||
|
unfold(c1, cons);
|
||||||
|
}
|
||||||
|
else if (m_util.str.is_concat(c->m_expr, e1, e2)) {
|
||||||
|
cell* c1 = mk_cell(c, e1, c->m_dep);
|
||||||
|
cell* c2 = mk_cell(0, e2, 0);
|
||||||
|
unfold(c1, cons);
|
||||||
|
unfold(c2, cons);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
cons.push_back(c);
|
||||||
|
}
|
||||||
|
c->m_last = cons.size()-1;
|
||||||
|
}
|
||||||
|
//
|
||||||
|
// a -> a1.a2, a2 -> a3.a4 -> ...
|
||||||
|
// b -> b1.b2, b2 -> b3.a4
|
||||||
|
//
|
||||||
|
// e1
|
||||||
|
//
|
||||||
|
|
||||||
|
void theory_seq::display_explain(std::ostream& out, unsigned indent, expr* e) {
|
||||||
|
expr* e1, *e2, *a;
|
||||||
|
dependency* dep = 0;
|
||||||
|
smt2_pp_environment_dbg env(m);
|
||||||
|
params_ref p;
|
||||||
|
for (unsigned i = 0; i < indent; ++i) out << " ";
|
||||||
|
ast_smt2_pp(out, e, env, p, indent);
|
||||||
|
out << "\n";
|
||||||
|
|
||||||
|
if (m_rep.find1(e, a, dep)) {
|
||||||
|
display_explain(out, indent + 1, a);
|
||||||
|
}
|
||||||
|
else if (m_util.str.is_concat(e, e1, e2)) {
|
||||||
|
display_explain(out, indent + 1, e1);
|
||||||
|
display_explain(out, indent + 1, e2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool theory_seq::explain_eq(expr* e1, expr* e2, dependency*& dep) {
|
||||||
|
|
||||||
|
if (e1 == e2) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
expr* a1, *a2;
|
||||||
|
ptr_vector<cell> v1, v2;
|
||||||
|
unsigned cells_sz = m_all_cells.size();
|
||||||
|
cell* c1 = mk_cell(0, e1, 0);
|
||||||
|
cell* c2 = mk_cell(0, e2, 0);
|
||||||
|
unfold(c1, v1);
|
||||||
|
unfold(c2, v2);
|
||||||
|
unsigned i = 0, j = 0;
|
||||||
|
|
||||||
|
TRACE("seq",
|
||||||
|
tout << "1:\n";
|
||||||
|
display_explain(tout, 0, e1);
|
||||||
|
tout << "2:\n";
|
||||||
|
display_explain(tout, 0, e2););
|
||||||
|
|
||||||
|
bool result = true;
|
||||||
|
while (i < v1.size() || j < v2.size()) {
|
||||||
|
if (i == v1.size()) {
|
||||||
|
while (j < v2.size() && m_util.str.is_empty(v2[j]->m_expr)) {
|
||||||
|
dep = m_dm.mk_join(dep, v2[j]->m_dep);
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
result = j == v2.size();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (j == v2.size()) {
|
||||||
|
while (i < v1.size() && m_util.str.is_empty(v1[i]->m_expr)) {
|
||||||
|
dep = m_dm.mk_join(dep, v1[i]->m_dep);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
result = i == v1.size();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
cell* c1 = v1[i];
|
||||||
|
cell* c2 = v2[j];
|
||||||
|
e1 = c1->m_expr;
|
||||||
|
e2 = c2->m_expr;
|
||||||
|
if (e1 == e2) {
|
||||||
|
if (c1->m_parent && c2->m_parent &&
|
||||||
|
c1->m_parent->m_expr == c2->m_parent->m_expr) {
|
||||||
|
TRACE("seq", tout << "parent: " << mk_pp(e1, m) << " " << mk_pp(c1->m_parent->m_expr, m) << "\n";);
|
||||||
|
c1 = c1->m_parent;
|
||||||
|
c2 = c2->m_parent;
|
||||||
|
v1[c1->m_last] = c1;
|
||||||
|
i = c1->m_last;
|
||||||
|
v2[c2->m_last] = c2;
|
||||||
|
j = c2->m_last;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
dep = m_dm.mk_join(dep, c1->m_dep);
|
||||||
|
dep = m_dm.mk_join(dep, c2->m_dep);
|
||||||
|
++i;
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (m_util.str.is_empty(e1)) {
|
||||||
|
dep = m_dm.mk_join(dep, c1->m_dep);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
else if (m_util.str.is_empty(e2)) {
|
||||||
|
dep = m_dm.mk_join(dep, c2->m_dep);
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
else if (m_util.str.is_unit(e1, a1) &&
|
||||||
|
m_util.str.is_unit(e2, a2)) {
|
||||||
|
if (explain_eq(a1, a2, dep)) {
|
||||||
|
++i;
|
||||||
|
++j;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
TRACE("seq", tout << "Could not solve " << mk_pp(e1, m) << " = " << mk_pp(e2, m) << "\n";);
|
||||||
|
result = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_all_cells.resize(cells_sz);
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
bool theory_seq::explain_empty(expr_ref_vector& es, dependency*& dep) {
|
||||||
|
while (!es.empty()) {
|
||||||
|
expr* e = es.back();
|
||||||
|
if (m_util.str.is_empty(e)) {
|
||||||
|
es.pop_back();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
expr* a;
|
||||||
|
if (m_rep.find1(e, a, dep)) {
|
||||||
|
es.pop_back();
|
||||||
|
m_util.str.get_concat(a, es);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
TRACE("seq", tout << "Could not set to empty: " << es << "\n";);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
bool theory_seq::simplify_and_solve_eqs() {
|
bool theory_seq::simplify_and_solve_eqs() {
|
||||||
context & ctx = get_context();
|
context & ctx = get_context();
|
||||||
|
@ -1294,18 +1576,44 @@ void theory_seq::display_disequation(std::ostream& out, ne const& e) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void theory_seq::display_deps(std::ostream& out, literal_vector const& lits, enode_pair_vector const& eqs) const {
|
||||||
|
context& ctx = get_context();
|
||||||
|
smt2_pp_environment_dbg env(m);
|
||||||
|
params_ref p;
|
||||||
|
for (unsigned i = 0; i < eqs.size(); ++i) {
|
||||||
|
out << " (= ";
|
||||||
|
ast_smt2_pp(out, eqs[i].first->get_owner(), env, p, 5);
|
||||||
|
out << "\n ";
|
||||||
|
ast_smt2_pp(out, eqs[i].second->get_owner(), env, p, 5);
|
||||||
|
out << ")\n";
|
||||||
|
}
|
||||||
|
for (unsigned i = 0; i < lits.size(); ++i) {
|
||||||
|
literal l = lits[i];
|
||||||
|
if (l == true_literal) {
|
||||||
|
out << " true";
|
||||||
|
}
|
||||||
|
else if (l == false_literal) {
|
||||||
|
out << " false";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
expr* e = ctx.bool_var2expr(l.var());
|
||||||
|
if (l.sign()) {
|
||||||
|
ast_smt2_pp(out << " (not ", e, env, p, 7);
|
||||||
|
out << ")";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ast_smt2_pp(out << " ", e, env, p, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
out << "\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void theory_seq::display_deps(std::ostream& out, dependency* dep) const {
|
void theory_seq::display_deps(std::ostream& out, dependency* dep) const {
|
||||||
literal_vector lits;
|
literal_vector lits;
|
||||||
enode_pair_vector eqs;
|
enode_pair_vector eqs;
|
||||||
linearize(dep, eqs, lits);
|
linearize(dep, eqs, lits);
|
||||||
for (unsigned i = 0; i < eqs.size(); ++i) {
|
display_deps(out, lits, eqs);
|
||||||
out << " " << mk_pp(eqs[i].first->get_owner(), m) << " = " << mk_pp(eqs[i].second->get_owner(), m) << "\n";
|
|
||||||
}
|
|
||||||
for (unsigned i = 0; i < lits.size(); ++i) {
|
|
||||||
literal lit = lits[i];
|
|
||||||
get_context().display_literals_verbose(out << " ", 1, &lit);
|
|
||||||
out << "\n";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void theory_seq::collect_statistics(::statistics & st) const {
|
void theory_seq::collect_statistics(::statistics & st) const {
|
||||||
|
@ -1534,6 +1842,9 @@ expr_ref theory_seq::expand(expr* e0, dependency*& eqs) {
|
||||||
else if (m_util.str.is_contains(e, e1, e2)) {
|
else if (m_util.str.is_contains(e, e1, e2)) {
|
||||||
result = m_util.str.mk_contains(expand(e1, deps), expand(e2, deps));
|
result = m_util.str.mk_contains(expand(e1, deps), expand(e2, deps));
|
||||||
}
|
}
|
||||||
|
else if (m_util.str.is_unit(e, e1)) {
|
||||||
|
result = m_util.str.mk_unit(expand(e1, deps));
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
result = e;
|
result = e;
|
||||||
}
|
}
|
||||||
|
@ -1954,12 +2265,30 @@ bool theory_seq::get_length(expr* e, rational& val) {
|
||||||
void theory_seq::add_extract_axiom(expr* e) {
|
void theory_seq::add_extract_axiom(expr* e) {
|
||||||
expr* s, *i, *l;
|
expr* s, *i, *l;
|
||||||
VERIFY(m_util.str.is_extract(e, s, i, l));
|
VERIFY(m_util.str.is_extract(e, s, i, l));
|
||||||
expr_ref x(mk_skolem(m_extract_prefix, s, e), m);
|
if (is_tail(s, i, l)) {
|
||||||
|
add_tail_axiom(e, s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (is_drop_last(s, i, l)) {
|
||||||
|
add_drop_last_axiom(e, s);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (is_extract_prefix0(s, i, l)) {
|
||||||
|
add_extract_prefix_axiom(e, s, l);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (is_extract_suffix(s, i, l)) {
|
||||||
|
add_extract_suffix_axiom(e, s, i);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
expr_ref x(mk_skolem(m_pre, s, i), m);
|
||||||
expr_ref ls(m_util.str.mk_length(s), m);
|
expr_ref ls(m_util.str.mk_length(s), m);
|
||||||
expr_ref lx(m_util.str.mk_length(x), m);
|
expr_ref lx(m_util.str.mk_length(x), m);
|
||||||
expr_ref le(m_util.str.mk_length(e), m);
|
expr_ref le(m_util.str.mk_length(e), m);
|
||||||
expr_ref ls_minus_i_l(mk_sub(mk_sub(ls, i),l), m);
|
expr_ref ls_minus_i_l(mk_sub(mk_sub(ls, i), l), m);
|
||||||
|
expr_ref y(mk_skolem(m_post, s, ls_minus_i_l), m);
|
||||||
expr_ref xe = mk_concat(x, e);
|
expr_ref xe = mk_concat(x, e);
|
||||||
|
expr_ref xey = mk_concat(x, e, y);
|
||||||
expr_ref zero(m_autil.mk_int(0), m);
|
expr_ref zero(m_autil.mk_int(0), m);
|
||||||
|
|
||||||
literal i_ge_0 = mk_literal(m_autil.mk_ge(i, zero));
|
literal i_ge_0 = mk_literal(m_autil.mk_ge(i, zero));
|
||||||
|
@ -1967,13 +2296,91 @@ void theory_seq::add_extract_axiom(expr* e) {
|
||||||
literal li_ge_ls = mk_literal(m_autil.mk_ge(ls_minus_i_l, 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));
|
literal l_ge_zero = mk_literal(m_autil.mk_ge(l, zero));
|
||||||
|
|
||||||
add_axiom(~i_ge_0, ~i_le_ls, mk_literal(m_util.str.mk_prefix(xe, s)));
|
// add_axiom(~i_ge_0, ~i_le_ls, mk_literal(m_util.str.mk_prefix(xe, s)));
|
||||||
|
add_axiom(~i_ge_0, ~i_le_ls, mk_seq_eq(xey, s));
|
||||||
add_axiom(~i_ge_0, ~i_le_ls, mk_eq(lx, i, false));
|
add_axiom(~i_ge_0, ~i_le_ls, mk_eq(lx, i, false));
|
||||||
add_axiom(~i_ge_0, ~i_le_ls, ~l_ge_zero, ~li_ge_ls, mk_eq(le, l, false));
|
add_axiom(~i_ge_0, ~i_le_ls, ~l_ge_zero, ~li_ge_ls, mk_eq(le, l, false));
|
||||||
add_axiom(~i_ge_0, ~i_le_ls, li_ge_ls, mk_eq(le, mk_sub(ls, i), false));
|
add_axiom(~i_ge_0, ~i_le_ls, li_ge_ls, mk_eq(le, mk_sub(ls, i), false));
|
||||||
add_axiom(~i_ge_0, ~i_le_ls, l_ge_zero, mk_eq(le, zero, false));
|
add_axiom(~i_ge_0, ~i_le_ls, l_ge_zero, mk_eq(le, zero, false));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void theory_seq::add_tail_axiom(expr* e, expr* s) {
|
||||||
|
expr_ref head(m), tail(m);
|
||||||
|
mk_decompose(s, head, tail);
|
||||||
|
add_axiom(mk_eq_empty(s), mk_seq_eq(s, mk_concat(head, e)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void theory_seq::add_drop_last_axiom(expr* e, expr* s) {
|
||||||
|
add_axiom(mk_eq_empty(s), mk_seq_eq(s, mk_concat(e, m_util.str.mk_unit(mk_last(s)))));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool theory_seq::is_drop_last(expr* s, expr* i, expr* l) {
|
||||||
|
rational i1;
|
||||||
|
if (!m_autil.is_numeral(i, i1) || !i1.is_zero()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
expr_ref l2(m), l1(l, m);
|
||||||
|
l2 = m_autil.mk_sub(m_util.str.mk_length(s), m_autil.mk_int(1));
|
||||||
|
m_rewrite(l1);
|
||||||
|
m_rewrite(l2);
|
||||||
|
return l1 == l2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool theory_seq::is_tail(expr* s, expr* i, expr* l) {
|
||||||
|
rational i1;
|
||||||
|
if (!m_autil.is_numeral(i, i1) || !i1.is_one()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
expr_ref l2(m), l1(l, m);
|
||||||
|
l2 = m_autil.mk_sub(m_util.str.mk_length(s), m_autil.mk_int(1));
|
||||||
|
m_rewrite(l1);
|
||||||
|
m_rewrite(l2);
|
||||||
|
return l1 == l2;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool theory_seq::is_extract_prefix0(expr* s, expr* i, expr* l) {
|
||||||
|
rational i1;
|
||||||
|
return m_autil.is_numeral(i, i1) && i1.is_zero();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool theory_seq::is_extract_suffix(expr* s, expr* i, expr* l) {
|
||||||
|
expr_ref len(m_autil.mk_add(l, i), m);
|
||||||
|
m_rewrite(len);
|
||||||
|
return m_util.str.is_length(len, l) && l == s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
0 <= l <= len(s) => s = ey & l = len(e)
|
||||||
|
*/
|
||||||
|
void theory_seq::add_extract_prefix_axiom(expr* e, expr* s, expr* l) {
|
||||||
|
expr_ref le(m_util.str.mk_length(e), m);
|
||||||
|
expr_ref ls(m_util.str.mk_length(s), m);
|
||||||
|
expr_ref ls_minus_l(mk_sub(ls, l), m);
|
||||||
|
expr_ref y(mk_skolem(m_post, s, ls_minus_l), m);
|
||||||
|
expr_ref zero(m_autil.mk_int(0), m);
|
||||||
|
expr_ref ey = mk_concat(e, y);
|
||||||
|
literal l_ge_0 = mk_literal(m_autil.mk_ge(l, zero));
|
||||||
|
literal l_le_s = mk_literal(m_autil.mk_le(mk_sub(l, ls), zero));
|
||||||
|
add_axiom(~l_ge_0, ~l_le_s, mk_seq_eq(s, ey));
|
||||||
|
add_axiom(~l_ge_0, ~l_le_s, mk_eq(l, le, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
0 <= i <= len(s) => s = xe & i = len(x)
|
||||||
|
*/
|
||||||
|
void theory_seq::add_extract_suffix_axiom(expr* e, expr* s, expr* i) {
|
||||||
|
expr_ref x(mk_skolem(m_pre, s, i), m);
|
||||||
|
expr_ref lx(m_util.str.mk_length(x), m);
|
||||||
|
expr_ref ls(m_util.str.mk_length(s), m);
|
||||||
|
expr_ref zero(m_autil.mk_int(0), m);
|
||||||
|
expr_ref xe = mk_concat(x, e);
|
||||||
|
literal i_ge_0 = mk_literal(m_autil.mk_ge(i, zero));
|
||||||
|
literal i_le_s = mk_literal(m_autil.mk_le(mk_sub(i, ls), zero));
|
||||||
|
add_axiom(~i_ge_0, ~i_le_s, mk_seq_eq(s, xe));
|
||||||
|
add_axiom(~i_ge_0, ~i_le_s, mk_eq(i, lx, false));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
let e = at(s, i)
|
let e = at(s, i)
|
||||||
|
|
||||||
|
@ -1983,14 +2390,14 @@ void theory_seq::add_extract_axiom(expr* e) {
|
||||||
void theory_seq::add_at_axiom(expr* e) {
|
void theory_seq::add_at_axiom(expr* e) {
|
||||||
expr* s, *i;
|
expr* s, *i;
|
||||||
VERIFY(m_util.str.is_at(e, 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);
|
expr_ref len_e(m_util.str.mk_length(e), m);
|
||||||
x = mk_skolem(m_at_left, s, i);
|
expr_ref len_s(m_util.str.mk_length(s), m);
|
||||||
y = mk_skolem(m_at_right, s, i);
|
expr_ref zero(m_autil.mk_int(0), m);
|
||||||
xey = mk_concat(x, e, y);
|
expr_ref one(m_autil.mk_int(1), m);
|
||||||
zero = m_autil.mk_int(0);
|
expr_ref x = mk_skolem(m_pre, s, i);
|
||||||
one = m_autil.mk_int(1);
|
expr_ref y = mk_skolem(m_post, s, mk_sub(mk_sub(len_s, i), one));
|
||||||
len_e = m_util.str.mk_length(e);
|
expr_ref xey = mk_concat(x, e, y);
|
||||||
len_x = m_util.str.mk_length(x);
|
expr_ref len_x(m_util.str.mk_length(x), m);
|
||||||
|
|
||||||
literal i_ge_0 = mk_literal(m_autil.mk_ge(i, zero));
|
literal i_ge_0 = mk_literal(m_autil.mk_ge(i, zero));
|
||||||
literal i_ge_len_s = mk_literal(m_autil.mk_ge(mk_sub(i, m_util.str.mk_length(s)), zero));
|
literal i_ge_len_s = mk_literal(m_autil.mk_ge(mk_sub(i, m_util.str.mk_length(s)), zero));
|
||||||
|
@ -2057,7 +2464,7 @@ literal theory_seq::mk_literal(expr* _e) {
|
||||||
|
|
||||||
literal theory_seq::mk_seq_eq(expr* a, expr* b) {
|
literal theory_seq::mk_seq_eq(expr* a, expr* b) {
|
||||||
SASSERT(m_util.is_seq(a));
|
SASSERT(m_util.is_seq(a));
|
||||||
return mk_literal(mk_skolem(symbol("seq.eq"), a, b, 0, m.mk_bool_sort()));
|
return mk_literal(mk_skolem(m_eq, a, b, 0, m.mk_bool_sort()));
|
||||||
}
|
}
|
||||||
|
|
||||||
literal theory_seq::mk_eq_empty(expr* _e) {
|
literal theory_seq::mk_eq_empty(expr* _e) {
|
||||||
|
@ -2116,8 +2523,13 @@ bool theory_seq::is_skolem(symbol const& s, expr* e) const {
|
||||||
return m_util.is_skolem(e) && to_app(e)->get_decl()->get_parameter(0).get_symbol() == s;
|
return m_util.is_skolem(e) && to_app(e)->get_decl()->get_parameter(0).get_symbol() == s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void theory_seq::propagate_eq(literal lit, expr* e1, expr* e2, bool add_to_eqs) {
|
void theory_seq::propagate_eq(literal lit, expr* e1, expr* e2, bool add_to_eqs) {
|
||||||
|
literal_vector lits;
|
||||||
|
lits.push_back(lit);
|
||||||
|
propagate_eq(lits, e1, e2, add_to_eqs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void theory_seq::propagate_eq(literal_vector const& lits, expr* e1, expr* e2, bool add_to_eqs) {
|
||||||
context& ctx = get_context();
|
context& ctx = get_context();
|
||||||
|
|
||||||
enode* n1 = ensure_enode(e1);
|
enode* n1 = ensure_enode(e1);
|
||||||
|
@ -2128,18 +2540,21 @@ void theory_seq::propagate_eq(literal lit, expr* e1, expr* e2, bool add_to_eqs)
|
||||||
ctx.mark_as_relevant(n1);
|
ctx.mark_as_relevant(n1);
|
||||||
ctx.mark_as_relevant(n2);
|
ctx.mark_as_relevant(n2);
|
||||||
if (add_to_eqs) {
|
if (add_to_eqs) {
|
||||||
SASSERT(l_true == ctx.get_assignment(lit));
|
dependency* deps = 0;
|
||||||
dependency* deps = m_dm.mk_leaf(assumption(lit));
|
for (unsigned i = 0; i < lits.size(); ++i) {
|
||||||
|
literal lit = lits[i];
|
||||||
|
SASSERT(l_true == ctx.get_assignment(lit));
|
||||||
|
deps = m_dm.mk_join(deps, m_dm.mk_leaf(assumption(lit)));
|
||||||
|
}
|
||||||
new_eq_eh(deps, n1, n2);
|
new_eq_eh(deps, n1, n2);
|
||||||
|
|
||||||
}
|
}
|
||||||
TRACE("seq",
|
TRACE("seq",
|
||||||
ctx.display_literals_verbose(tout, 1, &lit);
|
ctx.display_literals_verbose(tout, lits.size(), lits.c_ptr());
|
||||||
tout << " => " << mk_pp(e1, m) << " = " << mk_pp(e2, m) << "\n";);
|
tout << " => " << mk_pp(e1, m) << " = " << mk_pp(e2, m) << "\n";);
|
||||||
justification* js =
|
justification* js =
|
||||||
ctx.mk_justification(
|
ctx.mk_justification(
|
||||||
ext_theory_eq_propagation_justification(
|
ext_theory_eq_propagation_justification(
|
||||||
get_id(), ctx.get_region(), 1, &lit, 0, 0, n1, n2));
|
get_id(), ctx.get_region(), lits.size(), lits.c_ptr(), 0, 0, n1, n2));
|
||||||
|
|
||||||
m_new_propagation = true;
|
m_new_propagation = true;
|
||||||
ctx.assign_eq(n1, n2, eq_justification(js));
|
ctx.assign_eq(n1, n2, eq_justification(js));
|
||||||
|
|
|
@ -81,6 +81,8 @@ namespace smt {
|
||||||
bool find_cache(expr* v, expr_dep& r) { return m_cache.find(v, r); }
|
bool find_cache(expr* v, expr_dep& r) { return m_cache.find(v, r); }
|
||||||
expr* find(expr* e, dependency*& d);
|
expr* find(expr* e, dependency*& d);
|
||||||
expr* find(expr* e);
|
expr* find(expr* e);
|
||||||
|
bool find1(expr* a, expr*& b, dependency*& dep);
|
||||||
|
void find_rec(expr* e, svector<std::pair<expr*, dependency*> >& finds);
|
||||||
bool is_root(expr* e) const;
|
bool is_root(expr* e) const;
|
||||||
void cache(expr* e, expr* r, dependency* d);
|
void cache(expr* e, expr* r, dependency* d);
|
||||||
void reset_cache() { m_cache.reset(); }
|
void reset_cache() { m_cache.reset(); }
|
||||||
|
@ -142,31 +144,35 @@ namespace smt {
|
||||||
return eq(m_eq_id++, ls, rs, dep);
|
return eq(m_eq_id++, ls, rs, dep);
|
||||||
}
|
}
|
||||||
|
|
||||||
class ne {
|
class ne {
|
||||||
vector<expr_ref_vector> m_lhs;
|
expr_ref m_l, m_r;
|
||||||
vector<expr_ref_vector> m_rhs;
|
vector<expr_ref_vector> m_lhs, m_rhs;
|
||||||
literal_vector m_lits;
|
literal_vector m_lits;
|
||||||
dependency* m_dep;
|
dependency* m_dep;
|
||||||
public:
|
public:
|
||||||
ne(expr_ref const& l, expr_ref const& r, dependency* dep):
|
ne(expr_ref const& l, expr_ref const& r, dependency* dep):
|
||||||
m_dep(dep) {
|
m_l(l), m_r(r), m_dep(dep) {
|
||||||
expr_ref_vector ls(l.get_manager()); ls.push_back(l);
|
expr_ref_vector ls(l.get_manager()); ls.push_back(l);
|
||||||
expr_ref_vector rs(r.get_manager()); rs.push_back(r);
|
expr_ref_vector rs(r.get_manager()); rs.push_back(r);
|
||||||
m_lhs.push_back(ls);
|
m_lhs.push_back(ls);
|
||||||
m_rhs.push_back(rs);
|
m_rhs.push_back(rs);
|
||||||
}
|
}
|
||||||
|
|
||||||
ne(vector<expr_ref_vector> const& l, vector<expr_ref_vector> const& r, literal_vector const& lits, dependency* dep):
|
ne(expr_ref const& _l, expr_ref const& _r, vector<expr_ref_vector> const& l, vector<expr_ref_vector> const& r, literal_vector const& lits, dependency* dep):
|
||||||
|
m_l(_l), m_r(_r),
|
||||||
m_lhs(l),
|
m_lhs(l),
|
||||||
m_rhs(r),
|
m_rhs(r),
|
||||||
m_lits(lits),
|
m_lits(lits),
|
||||||
m_dep(dep) {}
|
m_dep(dep) {}
|
||||||
|
|
||||||
ne(ne const& other):
|
ne(ne const& other):
|
||||||
|
m_l(other.m_l), m_r(other.m_r),
|
||||||
m_lhs(other.m_lhs), m_rhs(other.m_rhs), m_lits(other.m_lits), m_dep(other.m_dep) {}
|
m_lhs(other.m_lhs), m_rhs(other.m_rhs), m_lits(other.m_lits), m_dep(other.m_dep) {}
|
||||||
|
|
||||||
ne& operator=(ne const& other) {
|
ne& operator=(ne const& other) {
|
||||||
if (this != &other) {
|
if (this != &other) {
|
||||||
|
m_l = other.m_l;
|
||||||
|
m_r = other.m_r;
|
||||||
m_lhs.reset(); m_lhs.append(other.m_lhs);
|
m_lhs.reset(); m_lhs.append(other.m_lhs);
|
||||||
m_rhs.reset(); m_rhs.append(other.m_rhs);
|
m_rhs.reset(); m_rhs.append(other.m_rhs);
|
||||||
m_lits.reset(); m_lits.append(other.m_lits);
|
m_lits.reset(); m_lits.append(other.m_lits);
|
||||||
|
@ -181,6 +187,8 @@ namespace smt {
|
||||||
literal_vector const& lits() const { return m_lits; }
|
literal_vector const& lits() const { return m_lits; }
|
||||||
literal lits(unsigned i) const { return m_lits[i]; }
|
literal lits(unsigned i) const { return m_lits[i]; }
|
||||||
dependency* dep() const { return m_dep; }
|
dependency* dep() const { return m_dep; }
|
||||||
|
expr_ref const& l() const { return m_l; }
|
||||||
|
expr_ref const& r() const { return m_r; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class apply {
|
class apply {
|
||||||
|
@ -268,7 +276,7 @@ namespace smt {
|
||||||
stats m_stats;
|
stats m_stats;
|
||||||
symbol m_prefix, m_suffix, m_contains_left, m_contains_right, m_accept, m_reject;
|
symbol m_prefix, m_suffix, m_contains_left, m_contains_right, m_accept, m_reject;
|
||||||
symbol m_tail, m_nth, m_seq_first, m_seq_last, m_indexof_left, m_indexof_right, m_aut_step;
|
symbol m_tail, m_nth, m_seq_first, m_seq_last, m_indexof_left, m_indexof_right, m_aut_step;
|
||||||
symbol m_extract_prefix, m_at_left, m_at_right;
|
symbol m_pre, m_post, m_eq;
|
||||||
ptr_vector<expr> m_todo;
|
ptr_vector<expr> m_todo;
|
||||||
expr_ref_vector m_ls, m_rs, m_lhs, m_rhs;
|
expr_ref_vector m_ls, m_rs, m_lhs, m_rhs;
|
||||||
|
|
||||||
|
@ -326,6 +334,9 @@ namespace smt {
|
||||||
bool solve_binary_eq(expr_ref_vector const& l, expr_ref_vector const& r, dependency* dep);
|
bool solve_binary_eq(expr_ref_vector const& l, expr_ref_vector const& r, dependency* dep);
|
||||||
bool propagate_max_length(expr* l, expr* r, dependency* dep);
|
bool propagate_max_length(expr* l, expr* r, dependency* dep);
|
||||||
|
|
||||||
|
bool get_length(expr* s, expr_ref& len, literal_vector& lits);
|
||||||
|
bool reduce_length(expr* l, expr* r);
|
||||||
|
|
||||||
expr_ref mk_empty(sort* s) { return expr_ref(m_util.str.mk_empty(s), m); }
|
expr_ref mk_empty(sort* s) { return expr_ref(m_util.str.mk_empty(s), m); }
|
||||||
expr_ref mk_concat(unsigned n, expr*const* es) { return expr_ref(m_util.str.mk_concat(n, es), m); }
|
expr_ref mk_concat(unsigned n, expr*const* es) { return expr_ref(m_util.str.mk_concat(n, es), m); }
|
||||||
expr_ref mk_concat(expr_ref_vector const& es, sort* s) { if (es.empty()) return mk_empty(s); return mk_concat(es.size(), es.c_ptr()); }
|
expr_ref mk_concat(expr_ref_vector const& es, sort* s) { if (es.empty()) return mk_empty(s); return mk_concat(es.size(), es.c_ptr()); }
|
||||||
|
@ -334,12 +345,27 @@ namespace smt {
|
||||||
bool solve_nqs(unsigned i);
|
bool solve_nqs(unsigned i);
|
||||||
bool solve_ne(unsigned i);
|
bool solve_ne(unsigned i);
|
||||||
|
|
||||||
|
struct cell {
|
||||||
|
cell* m_parent;
|
||||||
|
expr* m_expr;
|
||||||
|
dependency* m_dep;
|
||||||
|
unsigned m_last;
|
||||||
|
cell(cell* p, expr* e, dependency* d): m_parent(p), m_expr(e), m_dep(d), m_last(0) {}
|
||||||
|
};
|
||||||
|
scoped_ptr_vector<cell> m_all_cells;
|
||||||
|
cell* mk_cell(cell* p, expr* e, dependency* d);
|
||||||
|
void unfold(cell* c, ptr_vector<cell>& cons);
|
||||||
|
void display_explain(std::ostream& out, unsigned indent, expr* e);
|
||||||
|
bool explain_eq(expr* e1, expr* e2, dependency*& dep);
|
||||||
|
bool explain_empty(expr_ref_vector& es, dependency*& dep);
|
||||||
|
|
||||||
// asserting consequences
|
// asserting consequences
|
||||||
void linearize(dependency* dep, enode_pair_vector& eqs, literal_vector& lits) const;
|
void linearize(dependency* dep, enode_pair_vector& eqs, literal_vector& lits) const;
|
||||||
void propagate_lit(dependency* dep, literal lit) { propagate_lit(dep, 0, 0, lit); }
|
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_lit(dependency* dep, unsigned n, literal const* lits, literal lit);
|
||||||
void propagate_eq(dependency* dep, enode* n1, enode* n2);
|
void propagate_eq(dependency* dep, enode* n1, enode* n2);
|
||||||
void propagate_eq(literal lit, expr* e1, expr* e2, bool add_to_eqs);
|
void propagate_eq(literal lit, expr* e1, expr* e2, bool add_to_eqs);
|
||||||
|
void propagate_eq(literal_vector const& lits, expr* e1, expr* e2, bool add_to_eqs);
|
||||||
void set_conflict(dependency* dep, literal_vector const& lits = literal_vector());
|
void set_conflict(dependency* dep, literal_vector const& lits = literal_vector());
|
||||||
|
|
||||||
u_map<unsigned> m_branch_start;
|
u_map<unsigned> m_branch_start;
|
||||||
|
@ -357,6 +383,7 @@ namespace smt {
|
||||||
bool is_nth(expr* a) const;
|
bool is_nth(expr* a) const;
|
||||||
bool is_tail(expr* a, expr*& s, unsigned& idx) const;
|
bool is_tail(expr* a, expr*& s, unsigned& idx) const;
|
||||||
bool is_eq(expr* e, expr*& a, expr*& b) const;
|
bool is_eq(expr* e, expr*& a, expr*& b) const;
|
||||||
|
bool is_pre(expr* e, expr*& s, expr*& i);
|
||||||
expr_ref mk_nth(expr* s, expr* idx);
|
expr_ref mk_nth(expr* s, expr* idx);
|
||||||
expr_ref mk_last(expr* e);
|
expr_ref mk_last(expr* e);
|
||||||
expr_ref mk_first(expr* e);
|
expr_ref mk_first(expr* e);
|
||||||
|
@ -376,6 +403,15 @@ namespace smt {
|
||||||
void add_replace_axiom(expr* e);
|
void add_replace_axiom(expr* e);
|
||||||
void add_extract_axiom(expr* e);
|
void add_extract_axiom(expr* e);
|
||||||
void add_length_axiom(expr* n);
|
void add_length_axiom(expr* n);
|
||||||
|
void add_tail_axiom(expr* e, expr* s);
|
||||||
|
void add_drop_last_axiom(expr* e, expr* s);
|
||||||
|
void add_extract_prefix_axiom(expr* e, expr* s, expr* l);
|
||||||
|
void add_extract_suffix_axiom(expr* e, expr* s, expr* i);
|
||||||
|
bool is_tail(expr* s, expr* i, expr* l);
|
||||||
|
bool is_drop_last(expr* s, expr* i, expr* l);
|
||||||
|
bool is_extract_prefix0(expr* s, expr* i, expr* l);
|
||||||
|
bool is_extract_suffix(expr* s, expr* i, expr* l);
|
||||||
|
|
||||||
|
|
||||||
bool has_length(expr *e) const { return m_length.contains(e); }
|
bool has_length(expr *e) const { return m_length.contains(e); }
|
||||||
void add_length(expr* e);
|
void add_length(expr* e);
|
||||||
|
@ -445,6 +481,7 @@ namespace smt {
|
||||||
void display_disequations(std::ostream& out) const;
|
void display_disequations(std::ostream& out) const;
|
||||||
void display_disequation(std::ostream& out, ne const& e) const;
|
void display_disequation(std::ostream& out, ne const& e) const;
|
||||||
void display_deps(std::ostream& out, dependency* deps) const;
|
void display_deps(std::ostream& out, dependency* deps) const;
|
||||||
|
void display_deps(std::ostream& out, literal_vector const& lits, enode_pair_vector const& eqs) const;
|
||||||
public:
|
public:
|
||||||
theory_seq(ast_manager& m);
|
theory_seq(ast_manager& m);
|
||||||
virtual ~theory_seq();
|
virtual ~theory_seq();
|
||||||
|
|
|
@ -190,14 +190,14 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) {
|
virtual lbool check_sat(unsigned num_assumptions, expr * const * assumptions) {
|
||||||
m_check_sat_executed = true;
|
m_check_sat_executed = true;
|
||||||
|
m_use_solver1_results = false;
|
||||||
|
|
||||||
if (get_num_assumptions() != 0 ||
|
if (get_num_assumptions() != 0 ||
|
||||||
num_assumptions > 0 || // assumptions were provided
|
num_assumptions > 0 || // assumptions were provided
|
||||||
m_ignore_solver1) {
|
m_ignore_solver1) {
|
||||||
// must use incremental solver
|
// must use incremental solver
|
||||||
switch_inc_mode();
|
switch_inc_mode();
|
||||||
m_use_solver1_results = false;
|
|
||||||
return m_solver2->check_sat(num_assumptions, assumptions);
|
return m_solver2->check_sat(num_assumptions, assumptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -206,7 +206,6 @@ public:
|
||||||
IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 2 (without a timeout)\")\n";);
|
IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 2 (without a timeout)\")\n";);
|
||||||
lbool r = m_solver2->check_sat(0, 0);
|
lbool r = m_solver2->check_sat(0, 0);
|
||||||
if (r != l_undef || !use_solver1_when_undef()) {
|
if (r != l_undef || !use_solver1_when_undef()) {
|
||||||
m_use_solver1_results = false;
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -219,7 +218,6 @@ public:
|
||||||
r = m_solver2->check_sat(0, 0);
|
r = m_solver2->check_sat(0, 0);
|
||||||
}
|
}
|
||||||
if ((r != l_undef || !use_solver1_when_undef()) && !eh.m_canceled) {
|
if ((r != l_undef || !use_solver1_when_undef()) && !eh.m_canceled) {
|
||||||
m_use_solver1_results = false;
|
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
if (eh.m_canceled) {
|
if (eh.m_canceled) {
|
||||||
|
@ -227,7 +225,6 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"solver 2 failed, trying solver1\")\n";);
|
IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"solver 2 failed, trying solver1\")\n";);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 1\")\n";);
|
IF_VERBOSE(PS_VB_LVL, verbose_stream() << "(combined-solver \"using solver 1\")\n";);
|
||||||
|
|
|
@ -75,7 +75,7 @@ class ufbv_rewriter_tactic : public tactic {
|
||||||
void updt_params(params_ref const & p) {
|
void updt_params(params_ref const & p) {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
imp * m_imp;
|
imp * m_imp;
|
||||||
params_ref m_params;
|
params_ref m_params;
|
||||||
|
|
||||||
|
@ -88,7 +88,7 @@ public:
|
||||||
virtual tactic * translate(ast_manager & m) {
|
virtual tactic * translate(ast_manager & m) {
|
||||||
return alloc(ufbv_rewriter_tactic, m, m_params);
|
return alloc(ufbv_rewriter_tactic, m, m_params);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual ~ufbv_rewriter_tactic() {
|
virtual ~ufbv_rewriter_tactic() {
|
||||||
dealloc(m_imp);
|
dealloc(m_imp);
|
||||||
}
|
}
|
||||||
|
@ -103,19 +103,19 @@ public:
|
||||||
insert_produce_models(r);
|
insert_produce_models(r);
|
||||||
insert_produce_proofs(r);
|
insert_produce_proofs(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void operator()(goal_ref const & in,
|
virtual void operator()(goal_ref const & in,
|
||||||
goal_ref_buffer & result,
|
goal_ref_buffer & result,
|
||||||
model_converter_ref & mc,
|
model_converter_ref & mc,
|
||||||
proof_converter_ref & pc,
|
proof_converter_ref & pc,
|
||||||
expr_dependency_ref & core) {
|
expr_dependency_ref & core) {
|
||||||
(*m_imp)(in, result, mc, pc, core);
|
(*m_imp)(in, result, mc, pc, core);
|
||||||
}
|
}
|
||||||
|
|
||||||
virtual void cleanup() {
|
virtual void cleanup() {
|
||||||
ast_manager & m = m_imp->m();
|
ast_manager & m = m_imp->m();
|
||||||
imp * d = alloc(imp, m, m_params);
|
imp * d = alloc(imp, m, m_params);
|
||||||
std::swap(d, m_imp);
|
std::swap(d, m_imp);
|
||||||
dealloc(d);
|
dealloc(d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,4 +25,8 @@ class tactic;
|
||||||
|
|
||||||
tactic * mk_ufbv_rewriter_tactic(ast_manager & m, params_ref const & p = params_ref());
|
tactic * mk_ufbv_rewriter_tactic(ast_manager & m, params_ref const & p = params_ref());
|
||||||
|
|
||||||
|
/*
|
||||||
|
ADD_TACTIC("ufbv-rewriter", "Applies UFBV-specific rewriting rules, mainly demodulation.", "mk_quasi_macros_tactic(m, p)")
|
||||||
|
*/
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -46,11 +46,6 @@ public:
|
||||||
out_of_memory_error();
|
out_of_memory_error();
|
||||||
};
|
};
|
||||||
|
|
||||||
class exceeded_memory_allocations : public z3_error {
|
|
||||||
public:
|
|
||||||
exceeded_memory_allocations();
|
|
||||||
};
|
|
||||||
|
|
||||||
class memory {
|
class memory {
|
||||||
public:
|
public:
|
||||||
static bool is_out_of_memory();
|
static bool is_out_of_memory();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue