mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
synchronize fork
This commit is contained in:
commit
820c14ed06
430 changed files with 19930 additions and 13462 deletions
|
@ -63,7 +63,7 @@ void cached_var_subst::operator()(quantifier * qa, unsigned num_bindings, smt::e
|
|||
|
||||
SASSERT(entry->get_data().m_value == 0);
|
||||
try {
|
||||
m_proc(qa->get_expr(), new_key->m_num_bindings, new_key->m_bindings, result);
|
||||
result = m_proc(qa->get_expr(), new_key->m_num_bindings, new_key->m_bindings);
|
||||
}
|
||||
catch (...) {
|
||||
// CMW: The var_subst reducer was interrupted and m_instances is
|
||||
|
|
|
@ -20,9 +20,10 @@ Revision History:
|
|||
|
||||
namespace smt {
|
||||
|
||||
fingerprint::fingerprint(region & r, void * d, unsigned d_h, unsigned n, enode * const * args):
|
||||
fingerprint::fingerprint(region & r, void * d, unsigned d_h, expr* def, unsigned n, enode * const * args):
|
||||
m_data(d),
|
||||
m_data_hash(d_h),
|
||||
m_def(def),
|
||||
m_num_args(n),
|
||||
m_args(nullptr) {
|
||||
m_args = new (r) enode*[n];
|
||||
|
@ -50,8 +51,18 @@ namespace smt {
|
|||
m_dummy.m_args = m_tmp.c_ptr();
|
||||
return &m_dummy;
|
||||
}
|
||||
|
||||
std::ostream& operator<<(std::ostream& out, fingerprint const& f) {
|
||||
out << f.get_data_hash() << " " << " num_args " << f.get_num_args() << " ";
|
||||
for (enode const * arg : f) {
|
||||
out << " " << arg->get_owner_id();
|
||||
}
|
||||
out << "\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
fingerprint * fingerprint_set::insert(void * data, unsigned data_hash, unsigned num_args, enode * const * args) {
|
||||
fingerprint * fingerprint_set::insert(void * data, unsigned data_hash, unsigned num_args, enode * const * args, expr* def) {
|
||||
fingerprint * d = mk_dummy(data, data_hash, num_args, args);
|
||||
if (m_set.contains(d))
|
||||
return nullptr;
|
||||
|
@ -66,11 +77,10 @@ namespace smt {
|
|||
tout << "\n";);
|
||||
return nullptr;
|
||||
}
|
||||
TRACE("fingerprint_bug", tout << "2) inserting: " << data_hash << " num_args: " << num_args;
|
||||
for (unsigned i = 0; i < num_args; i++) tout << " " << args[i]->get_owner_id();
|
||||
tout << "\n";);
|
||||
fingerprint * f = new (m_region) fingerprint(m_region, data, data_hash, num_args, d->m_args);
|
||||
TRACE("fingerprint_bug", tout << "2) inserting: " << *d;);
|
||||
fingerprint * f = new (m_region) fingerprint(m_region, data, data_hash, def, num_args, d->m_args);
|
||||
m_fingerprints.push_back(f);
|
||||
m_defs.push_back(def);
|
||||
m_set.insert(f);
|
||||
return f;
|
||||
}
|
||||
|
@ -89,6 +99,7 @@ namespace smt {
|
|||
void fingerprint_set::reset() {
|
||||
m_set.reset();
|
||||
m_fingerprints.reset();
|
||||
m_defs.reset();
|
||||
}
|
||||
|
||||
void fingerprint_set::push_scope() {
|
||||
|
@ -104,20 +115,15 @@ namespace smt {
|
|||
for (unsigned i = old_size; i < size; i++)
|
||||
m_set.erase(m_fingerprints[i]);
|
||||
m_fingerprints.shrink(old_size);
|
||||
m_defs.shrink(old_size);
|
||||
m_scopes.shrink(new_lvl);
|
||||
}
|
||||
|
||||
void fingerprint_set::display(std::ostream & out) const {
|
||||
out << "fingerprints:\n";
|
||||
SASSERT(m_set.size() == m_fingerprints.size());
|
||||
ptr_vector<fingerprint>::const_iterator it = m_fingerprints.begin();
|
||||
ptr_vector<fingerprint>::const_iterator end = m_fingerprints.end();
|
||||
for (; it != end; ++it) {
|
||||
fingerprint const * f = *it;
|
||||
out << f->get_data() << " #" << f->get_data_hash();
|
||||
for (unsigned i = 0; i < f->get_num_args(); i++)
|
||||
out << " #" << f->get_arg(i)->get_owner_id();
|
||||
out << "\n";
|
||||
for (fingerprint const * f : m_fingerprints) {
|
||||
out << f->get_data() << " " << *f;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -126,10 +132,7 @@ namespace smt {
|
|||
\brief Slow function for checking if there is a fingerprint congruent to (data args[0] ... args[num_args-1])
|
||||
*/
|
||||
bool fingerprint_set::slow_contains(void const * data, unsigned data_hash, unsigned num_args, enode * const * args) const {
|
||||
ptr_vector<fingerprint>::const_iterator it = m_fingerprints.begin();
|
||||
ptr_vector<fingerprint>::const_iterator end = m_fingerprints.end();
|
||||
for (; it != end; ++it) {
|
||||
fingerprint const * f = *it;
|
||||
for (fingerprint const* f : m_fingerprints) {
|
||||
if (f->get_data() != data)
|
||||
continue;
|
||||
if (f->get_num_args() != num_args)
|
||||
|
@ -139,12 +142,7 @@ namespace smt {
|
|||
if (f->get_arg(i)->get_root() != args[i]->get_root())
|
||||
break;
|
||||
if (i == num_args) {
|
||||
TRACE("missing_instance_detail", tout << "found instance data: " << data << "=" << f->get_data() << " hash: " << f->get_data_hash();
|
||||
for (unsigned i = 0; i < num_args; i++) {
|
||||
tout << " " << f->get_arg(i)->get_owner_id() << ":" << f->get_arg(i)->get_root()->get_owner_id() << "="
|
||||
<< args[i]->get_owner_id() << ":" << args[i]->get_root()->get_owner_id();
|
||||
}
|
||||
tout << "\n";);
|
||||
TRACE("missing_instance_detail", tout << "found instance data: " << data << "=" << *f;);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ Revision History:
|
|||
#define FINGERPRINTS_H_
|
||||
|
||||
#include "smt/smt_enode.h"
|
||||
#include "util/util.h"
|
||||
|
||||
namespace smt {
|
||||
|
||||
|
@ -27,18 +28,23 @@ namespace smt {
|
|||
protected:
|
||||
void * m_data;
|
||||
unsigned m_data_hash;
|
||||
expr* m_def;
|
||||
unsigned m_num_args;
|
||||
enode * * m_args;
|
||||
|
||||
friend class fingerprint_set;
|
||||
fingerprint() {}
|
||||
public:
|
||||
fingerprint(region & r, void * d, unsigned d_hash, unsigned n, enode * const * args);
|
||||
fingerprint(region & r, void * d, unsigned d_hash, expr* def, unsigned n, enode * const * args);
|
||||
void * get_data() const { return m_data; }
|
||||
expr * get_def() const { return m_def; }
|
||||
unsigned get_data_hash() const { return m_data_hash; }
|
||||
unsigned get_num_args() const { return m_num_args; }
|
||||
enode * const * get_args() const { return m_args; }
|
||||
enode * get_arg(unsigned idx) const { SASSERT(idx < m_num_args); return m_args[idx]; }
|
||||
enode * const * begin() const { return m_args; }
|
||||
enode * const * end() const { return begin() + get_num_args(); }
|
||||
friend std::ostream& operator<<(std::ostream& out, fingerprint const& f);
|
||||
};
|
||||
|
||||
class fingerprint_set {
|
||||
|
@ -60,6 +66,7 @@ namespace smt {
|
|||
region & m_region;
|
||||
set m_set;
|
||||
ptr_vector<fingerprint> m_fingerprints;
|
||||
expr_ref_vector m_defs;
|
||||
unsigned_vector m_scopes;
|
||||
ptr_vector<enode> m_tmp;
|
||||
fingerprint m_dummy;
|
||||
|
@ -67,8 +74,8 @@ namespace smt {
|
|||
fingerprint * mk_dummy(void * data, unsigned data_hash, unsigned num_args, enode * const * args);
|
||||
|
||||
public:
|
||||
fingerprint_set(region & r):m_region(r) {}
|
||||
fingerprint * insert(void * data, unsigned data_hash, unsigned num_args, enode * const * args);
|
||||
fingerprint_set(ast_manager& m, region & r): m_region(r), m_defs(m) {}
|
||||
fingerprint * insert(void * data, unsigned data_hash, unsigned num_args, enode * const * args, expr* def);
|
||||
unsigned size() const { return m_fingerprints.size(); }
|
||||
bool contains(void * data, unsigned data_hash, unsigned num_args, enode * const * args);
|
||||
void reset();
|
||||
|
|
100
src/smt/mam.cpp
100
src/smt/mam.cpp
|
@ -16,15 +16,16 @@ Author:
|
|||
Revision History:
|
||||
|
||||
--*/
|
||||
#include "smt/mam.h"
|
||||
#include "smt/smt_context.h"
|
||||
#include <algorithm>
|
||||
|
||||
#include "util/pool.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "util/trail.h"
|
||||
#include "util/stopwatch.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include<algorithm>
|
||||
#include "smt/mam.h"
|
||||
#include "smt/smt_context.h"
|
||||
|
||||
// #define _PROFILE_MAM
|
||||
|
||||
|
@ -569,9 +570,8 @@ namespace smt {
|
|||
if (m_context) {
|
||||
ast_manager & m = m_context->get_manager();
|
||||
out << "patterns:\n";
|
||||
for (expr* p : m_patterns) {
|
||||
out << mk_pp(p, m) << "\n";
|
||||
}
|
||||
for (app* a : m_patterns)
|
||||
out << mk_pp(a, m) << "\n";
|
||||
}
|
||||
#endif
|
||||
out << "function: " << m_root_lbl->get_name();
|
||||
|
@ -1482,8 +1482,8 @@ namespace smt {
|
|||
}
|
||||
if (num_instr > SIMPLE_SEQ_THRESHOLD || (curr != nullptr && curr->m_opcode == CHOOSE))
|
||||
simple = false;
|
||||
for (unsigned reg : m_to_reset)
|
||||
m_registers[reg] = 0;
|
||||
for (unsigned r : m_to_reset)
|
||||
m_registers[r] = 0;
|
||||
return weight;
|
||||
}
|
||||
|
||||
|
@ -2001,30 +2001,32 @@ namespace smt {
|
|||
TRACE("trigger_bug", tout << "execute for code tree:\n"; t->display(tout););
|
||||
init(t);
|
||||
if (t->filter_candidates()) {
|
||||
for (enode * app : t->get_candidates()) {
|
||||
for (enode* app : t->get_candidates()) {
|
||||
if (!app->is_marked() && app->is_cgr()) {
|
||||
execute_core(t, app);
|
||||
if (m_context.resource_limits_exceeded() || !execute_core(t, app))
|
||||
return;
|
||||
app->set_mark();
|
||||
}
|
||||
}
|
||||
for (enode * app : t->get_candidates()) {
|
||||
for (enode* app : t->get_candidates()) {
|
||||
if (app->is_marked())
|
||||
app->unset_mark();
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (enode * app : t->get_candidates()) {
|
||||
for (enode* app : t->get_candidates()) {
|
||||
TRACE("trigger_bug", tout << "candidate\n" << mk_ismt2_pp(app->get_owner(), m_ast_manager) << "\n";);
|
||||
if (app->is_cgr()) {
|
||||
TRACE("trigger_bug", tout << "is_cgr\n";);
|
||||
execute_core(t, app);
|
||||
if (m_context.resource_limits_exceeded() || !execute_core(t, app))
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// init(t) must be invoked before execute_core
|
||||
void execute_core(code_tree * t, enode * n);
|
||||
bool execute_core(code_tree * t, enode * n);
|
||||
|
||||
// Return the min, max generation of the enodes in m_pattern_instances.
|
||||
|
||||
|
@ -2253,7 +2255,7 @@ namespace smt {
|
|||
display_instr_input_reg(out, m_pc);
|
||||
}
|
||||
|
||||
void interpreter::execute_core(code_tree * t, enode * n) {
|
||||
bool interpreter::execute_core(code_tree * t, enode * n) {
|
||||
TRACE("trigger_bug", tout << "interpreter::execute_core\n"; t->display(tout); tout << "\nenode\n" << mk_ismt2_pp(n->get_owner(), m_ast_manager) << "\n";);
|
||||
unsigned since_last_check = 0;
|
||||
|
||||
|
@ -2501,7 +2503,7 @@ namespace smt {
|
|||
#define ON_MATCH(NUM) \
|
||||
m_max_generation = std::max(m_max_generation, get_max_generation(NUM, m_bindings.begin())); \
|
||||
if (m_context.get_cancel_flag()) { \
|
||||
return; \
|
||||
return false; \
|
||||
} \
|
||||
m_mam.on_match(static_cast<const yield *>(m_pc)->m_qa, \
|
||||
static_cast<const yield *>(m_pc)->m_pat, \
|
||||
|
@ -2654,7 +2656,7 @@ namespace smt {
|
|||
#ifdef _PROFILE_MAM
|
||||
t->get_watch().stop();
|
||||
#endif
|
||||
return; // no more alternatives
|
||||
return true; // no more alternatives
|
||||
}
|
||||
backtrack_point & bp = m_backtrack_stack[m_top - 1];
|
||||
m_max_generation = bp.m_old_max_generation;
|
||||
|
@ -2682,7 +2684,7 @@ namespace smt {
|
|||
#ifdef _PROFILE_MAM
|
||||
t->get_watch().stop();
|
||||
#endif
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2800,11 +2802,12 @@ namespace smt {
|
|||
default:
|
||||
UNREACHABLE();
|
||||
}
|
||||
return false;
|
||||
} // end of execute_core
|
||||
|
||||
void display_trees(std::ostream & out, const ptr_vector<code_tree> & trees) {
|
||||
unsigned lbl = 0;
|
||||
for (code_tree* tree : trees) {
|
||||
for (code_tree * tree : trees) {
|
||||
if (tree) {
|
||||
out << "tree for f" << lbl << "\n";
|
||||
out << *tree;
|
||||
|
@ -3150,10 +3153,7 @@ namespace smt {
|
|||
m_trail_stack.push(set_bitvector_trail<mam_impl>(m_is_clbl, lbl_id));
|
||||
SASSERT(m_is_clbl[lbl_id]);
|
||||
unsigned h = m_lbl_hasher(lbl);
|
||||
enode_vector::const_iterator it = m_context.begin_enodes_of(lbl);
|
||||
enode_vector::const_iterator end = m_context.end_enodes_of(lbl);
|
||||
for (; it != end; ++it) {
|
||||
enode * app = *it;
|
||||
for (enode* app : m_context.enodes_of(lbl)) {
|
||||
if (m_context.is_relevant(app)) {
|
||||
update_lbls(app, h);
|
||||
TRACE("mam_bug", tout << "updating labels of: #" << app->get_owner_id() << "\n";
|
||||
|
@ -3195,10 +3195,7 @@ namespace smt {
|
|||
SASSERT(m_is_plbl[lbl_id]);
|
||||
SASSERT(is_plbl(lbl));
|
||||
unsigned h = m_lbl_hasher(lbl);
|
||||
enode_vector::const_iterator it = m_context.begin_enodes_of(lbl);
|
||||
enode_vector::const_iterator end = m_context.end_enodes_of(lbl);
|
||||
for (; it != end; ++it) {
|
||||
enode * app = *it;
|
||||
for (enode * app : m_context.enodes_of(lbl)) {
|
||||
if (m_context.is_relevant(app))
|
||||
update_children_plbls(app, h);
|
||||
}
|
||||
|
@ -3684,18 +3681,12 @@ namespace smt {
|
|||
approx_set & plbls = r1->get_plbls();
|
||||
approx_set & clbls = r2->get_lbls();
|
||||
if (!plbls.empty() && !clbls.empty()) {
|
||||
approx_set::iterator it1 = plbls.begin();
|
||||
approx_set::iterator end1 = plbls.end();
|
||||
for (; it1 != end1; ++it1) {
|
||||
for (unsigned plbl1 : plbls) {
|
||||
if (m_context.get_cancel_flag()) {
|
||||
break;
|
||||
}
|
||||
unsigned plbl1 = *it1;
|
||||
SASSERT(plbls.may_contain(plbl1));
|
||||
approx_set::iterator it2 = clbls.begin();
|
||||
approx_set::iterator end2 = clbls.end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
unsigned lbl2 = *it2;
|
||||
for (unsigned lbl2 : clbls) {
|
||||
SASSERT(clbls.may_contain(lbl2));
|
||||
collect_parents(r1, m_pc[plbl1][lbl2]);
|
||||
}
|
||||
|
@ -3706,14 +3697,12 @@ namespace smt {
|
|||
void match_new_patterns() {
|
||||
TRACE("mam_new_pat", tout << "matching new patterns:\n";);
|
||||
m_tmp_trees_to_delete.reset();
|
||||
svector<qp_pair>::iterator it1 = m_new_patterns.begin();
|
||||
svector<qp_pair>::iterator end1 = m_new_patterns.end();
|
||||
for (; it1 != end1; ++it1) {
|
||||
for (auto const& kv : m_new_patterns) {
|
||||
if (m_context.get_cancel_flag()) {
|
||||
break;
|
||||
}
|
||||
quantifier * qa = it1->first;
|
||||
app * mp = it1->second;
|
||||
quantifier * qa = kv.first;
|
||||
app * mp = kv.second;
|
||||
SASSERT(m_ast_manager.is_pattern(mp));
|
||||
app * p = to_app(mp->get_arg(0));
|
||||
func_decl * lbl = p->get_decl();
|
||||
|
@ -3730,19 +3719,13 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
|
||||
ptr_vector<func_decl>::iterator it2 = m_tmp_trees_to_delete.begin();
|
||||
ptr_vector<func_decl>::iterator end2 = m_tmp_trees_to_delete.end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
func_decl * lbl = *it2;
|
||||
for (func_decl * lbl : m_tmp_trees_to_delete) {
|
||||
unsigned lbl_id = lbl->get_decl_id();
|
||||
code_tree * tmp_tree = m_tmp_trees[lbl_id];
|
||||
SASSERT(tmp_tree != 0);
|
||||
SASSERT(m_context.get_num_enodes_of(lbl) > 0);
|
||||
m_interpreter.init(tmp_tree);
|
||||
enode_vector::const_iterator it3 = m_context.begin_enodes_of(lbl);
|
||||
enode_vector::const_iterator end3 = m_context.end_enodes_of(lbl);
|
||||
for (; it3 != end3; ++it3) {
|
||||
enode * app = *it3;
|
||||
for (enode * app : m_context.enodes_of(lbl)) {
|
||||
if (m_context.is_relevant(app))
|
||||
m_interpreter.execute_core(tmp_tree, app);
|
||||
}
|
||||
|
@ -3831,10 +3814,7 @@ namespace smt {
|
|||
|
||||
void pop_scope(unsigned num_scopes) override {
|
||||
if (!m_to_match.empty()) {
|
||||
ptr_vector<code_tree>::iterator it = m_to_match.begin();
|
||||
ptr_vector<code_tree>::iterator end = m_to_match.end();
|
||||
for (; it != end; ++it) {
|
||||
code_tree * t = *it;
|
||||
for (code_tree* t : m_to_match) {
|
||||
t->reset_candidates();
|
||||
}
|
||||
m_to_match.reset();
|
||||
|
@ -3867,10 +3847,7 @@ namespace smt {
|
|||
|
||||
void match() override {
|
||||
TRACE("trigger_bug", tout << "match\n"; display(tout););
|
||||
ptr_vector<code_tree>::iterator it = m_to_match.begin();
|
||||
ptr_vector<code_tree>::iterator end = m_to_match.end();
|
||||
for (; it != end; ++it) {
|
||||
code_tree * t = *it;
|
||||
for (code_tree* t : m_to_match) {
|
||||
SASSERT(t->has_candidates());
|
||||
m_interpreter.execute(t);
|
||||
t->reset_candidates();
|
||||
|
@ -3891,10 +3868,7 @@ namespace smt {
|
|||
if (t) {
|
||||
m_interpreter.init(t);
|
||||
func_decl * lbl = t->get_root_lbl();
|
||||
enode_vector::const_iterator it2 = m_context.begin_enodes_of(lbl);
|
||||
enode_vector::const_iterator end2 = m_context.end_enodes_of(lbl);
|
||||
for (; it2 != end2; ++it2) {
|
||||
enode * curr = *it2;
|
||||
for (enode * curr : m_context.enodes_of(lbl)) {
|
||||
if (use_irrelevant || m_context.is_relevant(curr))
|
||||
m_interpreter.execute_core(t, curr);
|
||||
}
|
||||
|
@ -3931,7 +3905,7 @@ namespace smt {
|
|||
#endif
|
||||
unsigned min_gen, max_gen;
|
||||
m_interpreter.get_min_max_top_generation(min_gen, max_gen);
|
||||
m_context.add_instance(qa, pat, num_bindings, bindings, max_generation, min_gen, max_gen, used_enodes);
|
||||
m_context.add_instance(qa, pat, num_bindings, bindings, nullptr, max_generation, min_gen, max_gen, used_enodes);
|
||||
}
|
||||
|
||||
bool is_shared(enode * n) const override {
|
||||
|
|
|
@ -8,6 +8,7 @@ z3_add_component(smt_params
|
|||
theory_array_params.cpp
|
||||
theory_bv_params.cpp
|
||||
theory_pb_params.cpp
|
||||
theory_seq_params.cpp
|
||||
theory_str_params.cpp
|
||||
COMPONENT_DEPENDENCIES
|
||||
ast
|
||||
|
|
|
@ -26,6 +26,7 @@ Revision History:
|
|||
#include "smt/params/theory_array_params.h"
|
||||
#include "smt/params/theory_bv_params.h"
|
||||
#include "smt/params/theory_str_params.h"
|
||||
#include "smt/params/theory_seq_params.h"
|
||||
#include "smt/params/theory_pb_params.h"
|
||||
#include "smt/params/theory_datatype_params.h"
|
||||
#include "smt/params/preprocessor_params.h"
|
||||
|
@ -79,6 +80,7 @@ struct smt_params : public preprocessor_params,
|
|||
public theory_array_params,
|
||||
public theory_bv_params,
|
||||
public theory_str_params,
|
||||
public theory_seq_params,
|
||||
public theory_pb_params,
|
||||
public theory_datatype_params {
|
||||
bool m_display_proof;
|
||||
|
|
|
@ -71,6 +71,7 @@ def_module_params(module_name='smt',
|
|||
('theory_case_split', BOOL, False, 'Allow the context to use heuristics involving theory case splits, which are a set of literals of which exactly one can be assigned True. If this option is false, the context will generate extra axioms to enforce this instead.'),
|
||||
('string_solver', SYMBOL, 'seq', 'solver for string/sequence theories. options are: \'z3str3\' (specialized string solver), \'seq\' (sequence solver), \'auto\' (use static features to choose best solver)'),
|
||||
('core.validate', BOOL, False, 'validate unsat core produced by SMT context'),
|
||||
('seq.split_w_len', BOOL, True, 'enable splitting guided by length constraints'),
|
||||
('str.strong_arrangements', BOOL, True, 'assert equivalences instead of implications when generating string arrangement axioms'),
|
||||
('str.aggressive_length_testing', BOOL, False, 'prioritize testing concrete length values over generating more options'),
|
||||
('str.aggressive_value_testing', BOOL, False, 'prioritize testing concrete string constant values over generating more options'),
|
||||
|
|
|
@ -25,11 +25,11 @@ Revision History:
|
|||
enum arith_solver_id {
|
||||
AS_NO_ARITH, // 0
|
||||
AS_DIFF_LOGIC, // 1
|
||||
AS_ARITH, // 2
|
||||
AS_OLD_ARITH, // 2
|
||||
AS_DENSE_DIFF_LOGIC, // 3
|
||||
AS_UTVPI, // 4
|
||||
AS_OPTINF, // 5
|
||||
AS_LRA // 6
|
||||
AS_NEW_ARITH // 6
|
||||
};
|
||||
|
||||
enum bound_prop_mode {
|
||||
|
@ -113,7 +113,7 @@ struct theory_arith_params {
|
|||
theory_arith_params(params_ref const & p = params_ref()):
|
||||
m_arith_eq2ineq(false),
|
||||
m_arith_process_all_eqs(false),
|
||||
m_arith_mode(AS_ARITH),
|
||||
m_arith_mode(AS_NEW_ARITH),
|
||||
m_arith_auto_config_simplex(false),
|
||||
m_arith_blands_rule_threshold(1000),
|
||||
m_arith_propagate_eqs(true),
|
||||
|
|
|
@ -40,6 +40,7 @@ struct theory_array_params {
|
|||
bool m_array_always_prop_upward;
|
||||
bool m_array_lazy_ieq;
|
||||
unsigned m_array_lazy_ieq_delay;
|
||||
bool m_array_fake_support; // fake support for all array operations to pretend they are satisfiable.
|
||||
|
||||
theory_array_params():
|
||||
m_array_canonize_simplify(false),
|
||||
|
@ -52,7 +53,8 @@ struct theory_array_params {
|
|||
m_array_cg(false),
|
||||
m_array_always_prop_upward(true), // UPWARDs filter is broken... TODO: fix it
|
||||
m_array_lazy_ieq(false),
|
||||
m_array_lazy_ieq_delay(10) {
|
||||
m_array_lazy_ieq_delay(10),
|
||||
m_array_fake_support(false) {
|
||||
}
|
||||
|
||||
|
||||
|
|
23
src/smt/params/theory_seq_params.cpp
Normal file
23
src/smt/params/theory_seq_params.cpp
Normal file
|
@ -0,0 +1,23 @@
|
|||
/*++
|
||||
Copyright (c) 2018 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
theory_seq_params.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
Parameters for sequence theory plugin
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#include "smt/params/theory_seq_params.h"
|
||||
#include "smt/params/smt_params_helper.hpp"
|
||||
|
||||
void theory_seq_params::updt_params(params_ref const & _p) {
|
||||
smt_params_helper p(_p);
|
||||
m_split_w_len = p.seq_split_w_len();
|
||||
}
|
38
src/smt/params/theory_seq_params.h
Normal file
38
src/smt/params/theory_seq_params.h
Normal file
|
@ -0,0 +1,38 @@
|
|||
/*++
|
||||
Copyright (c) 2018 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
theory_seq_params.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Parameters for sequence theory plugin
|
||||
|
||||
Revision History:
|
||||
|
||||
|
||||
--*/
|
||||
|
||||
#ifndef THEORY_SEQ_PARAMS_H
|
||||
#define THEORY_SEQ_PARAMS_H
|
||||
|
||||
#include "util/params.h"
|
||||
|
||||
struct theory_seq_params {
|
||||
/*
|
||||
* Enable splitting guided by length constraints
|
||||
*/
|
||||
bool m_split_w_len;
|
||||
|
||||
|
||||
theory_seq_params(params_ref const & p = params_ref()):
|
||||
m_split_w_len(true)
|
||||
{
|
||||
updt_params(p);
|
||||
}
|
||||
|
||||
void updt_params(params_ref const & p);
|
||||
};
|
||||
|
||||
#endif /* THEORY_SEQ_PARAMS_H */
|
|
@ -17,11 +17,11 @@ Revision History:
|
|||
|
||||
--*/
|
||||
|
||||
#include "smt/proto_model/array_factory.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "smt/proto_model/proto_model.h"
|
||||
#include "model/func_interp.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "model/func_interp.h"
|
||||
#include "smt/proto_model/array_factory.h"
|
||||
#include "smt/proto_model/proto_model.h"
|
||||
|
||||
func_decl * mk_aux_decl_for_array_sort(ast_manager & m, sort * s) {
|
||||
ptr_buffer<sort> domain;
|
||||
|
@ -67,9 +67,13 @@ expr * array_factory::get_some_value(sort * s) {
|
|||
return *(set->begin());
|
||||
func_interp * fi;
|
||||
expr * val = mk_array_interp(s, fi);
|
||||
#if 0
|
||||
ptr_buffer<expr> args;
|
||||
get_some_args_for(s, args);
|
||||
fi->insert_entry(args.c_ptr(), m_model.get_some_value(get_array_range(s)));
|
||||
#else
|
||||
fi->set_else(m_model.get_some_value(get_array_range(s)));
|
||||
#endif
|
||||
return val;
|
||||
}
|
||||
|
||||
|
@ -143,9 +147,13 @@ expr * array_factory::get_fresh_value(sort * s) {
|
|||
// easy case
|
||||
func_interp * fi;
|
||||
expr * val = mk_array_interp(s, fi);
|
||||
#if 0
|
||||
ptr_buffer<expr> args;
|
||||
get_some_args_for(s, args);
|
||||
fi->insert_entry(args.c_ptr(), range_val);
|
||||
#else
|
||||
fi->set_else(range_val);
|
||||
#endif
|
||||
return val;
|
||||
}
|
||||
else {
|
||||
|
|
|
@ -18,13 +18,15 @@ Revision History:
|
|||
--*/
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/well_sorted.h"
|
||||
#include "ast/used_symbols.h"
|
||||
#include "ast/for_each_expr.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "model/model_params.hpp"
|
||||
#include "model/model_v2_pp.h"
|
||||
#include "smt/proto_model/proto_model.h"
|
||||
|
||||
|
||||
proto_model::proto_model(ast_manager & m, params_ref const & p):
|
||||
model_core(m),
|
||||
m_eval(*this),
|
||||
|
@ -75,7 +77,7 @@ expr * proto_model::mk_some_interp_for(func_decl * d) {
|
|||
register_decl(d, r);
|
||||
}
|
||||
else {
|
||||
func_interp * new_fi = alloc(func_interp, m_manager, d->get_arity());
|
||||
func_interp * new_fi = alloc(func_interp, m, d->get_arity());
|
||||
new_fi->set_else(r);
|
||||
register_decl(d, new_fi);
|
||||
}
|
||||
|
@ -86,6 +88,7 @@ expr * proto_model::mk_some_interp_for(func_decl * d) {
|
|||
bool proto_model::eval(expr * e, expr_ref & result, bool model_completion) {
|
||||
m_eval.set_model_completion(model_completion);
|
||||
m_eval.set_expand_array_equalities(false);
|
||||
TRACE("model_evaluator", model_v2_pp(tout, *this, true););
|
||||
try {
|
||||
m_eval(e, result);
|
||||
return true;
|
||||
|
@ -120,10 +123,10 @@ void proto_model::cleanup_func_interp(func_interp * fi, func_decl_set & found_au
|
|||
if (fi->is_partial())
|
||||
return;
|
||||
expr * fi_else = fi->get_else();
|
||||
TRACE("model_bug", tout << "cleaning up:\n" << mk_pp(fi_else, m_manager) << "\n";);
|
||||
TRACE("model_bug", tout << "cleaning up:\n" << mk_pp(fi_else, m) << "\n";);
|
||||
|
||||
obj_map<expr, expr*> cache;
|
||||
expr_ref_vector trail(m_manager);
|
||||
expr_ref_vector trail(m);
|
||||
ptr_buffer<expr, 128> todo;
|
||||
ptr_buffer<expr> args;
|
||||
todo.push_back(fi_else);
|
||||
|
@ -165,7 +168,7 @@ void proto_model::cleanup_func_interp(func_interp * fi, func_decl_set & found_au
|
|||
TRACE("model_bug", tout << f->get_name() << "\n";);
|
||||
found_aux_fs.insert(f);
|
||||
}
|
||||
expr_ref new_t(m_manager);
|
||||
expr_ref new_t(m);
|
||||
new_t = m_rewrite.mk_app(f, args.size(), args.c_ptr());
|
||||
if (t != new_t.get())
|
||||
trail.push_back(new_t);
|
||||
|
@ -235,7 +238,7 @@ value_factory * proto_model::get_factory(family_id fid) {
|
|||
}
|
||||
|
||||
void proto_model::freeze_universe(sort * s) {
|
||||
SASSERT(m_manager.is_uninterp(s));
|
||||
SASSERT(m.is_uninterp(s));
|
||||
m_user_sort_factory->freeze_universe(s);
|
||||
}
|
||||
|
||||
|
@ -270,11 +273,11 @@ sort * proto_model::get_uninterpreted_sort(unsigned idx) const {
|
|||
in the model.
|
||||
*/
|
||||
bool proto_model::is_finite(sort * s) const {
|
||||
return m_manager.is_uninterp(s) && m_user_sort_factory->is_finite(s);
|
||||
return m.is_uninterp(s) && m_user_sort_factory->is_finite(s);
|
||||
}
|
||||
|
||||
expr * proto_model::get_some_value(sort * s) {
|
||||
if (m_manager.is_uninterp(s)) {
|
||||
if (m.is_uninterp(s)) {
|
||||
return m_user_sort_factory->get_some_value(s);
|
||||
}
|
||||
else {
|
||||
|
@ -288,7 +291,7 @@ expr * proto_model::get_some_value(sort * s) {
|
|||
}
|
||||
|
||||
bool proto_model::get_some_values(sort * s, expr_ref & v1, expr_ref & v2) {
|
||||
if (m_manager.is_uninterp(s)) {
|
||||
if (m.is_uninterp(s)) {
|
||||
return m_user_sort_factory->get_some_values(s, v1, v2);
|
||||
}
|
||||
else {
|
||||
|
@ -302,7 +305,7 @@ bool proto_model::get_some_values(sort * s, expr_ref & v1, expr_ref & v2) {
|
|||
}
|
||||
|
||||
expr * proto_model::get_fresh_value(sort * s) {
|
||||
if (m_manager.is_uninterp(s)) {
|
||||
if (m.is_uninterp(s)) {
|
||||
return m_user_sort_factory->get_fresh_value(s);
|
||||
}
|
||||
else {
|
||||
|
@ -318,8 +321,8 @@ expr * proto_model::get_fresh_value(sort * s) {
|
|||
}
|
||||
|
||||
void proto_model::register_value(expr * n) {
|
||||
sort * s = m_manager.get_sort(n);
|
||||
if (m_manager.is_uninterp(s)) {
|
||||
sort * s = m.get_sort(n);
|
||||
if (m.is_uninterp(s)) {
|
||||
m_user_sort_factory->register_value(n);
|
||||
}
|
||||
else {
|
||||
|
@ -374,15 +377,15 @@ void proto_model::complete_partial_funcs(bool use_fresh) {
|
|||
|
||||
model * proto_model::mk_model() {
|
||||
TRACE("proto_model", model_v2_pp(tout << "mk_model\n", *this););
|
||||
model * m = alloc(model, m_manager);
|
||||
model * mdl = alloc(model, m);
|
||||
|
||||
for (auto const& kv : m_interp) {
|
||||
m->register_decl(kv.m_key, kv.m_value);
|
||||
mdl->register_decl(kv.m_key, kv.m_value);
|
||||
}
|
||||
|
||||
for (auto const& kv : m_finterp) {
|
||||
m->register_decl(kv.m_key, kv.m_value);
|
||||
m_manager.dec_ref(kv.m_key);
|
||||
mdl->register_decl(kv.m_key, kv.m_value);
|
||||
m.dec_ref(kv.m_key);
|
||||
}
|
||||
|
||||
m_finterp.reset(); // m took the ownership of the func_interp's
|
||||
|
@ -390,10 +393,11 @@ model * proto_model::mk_model() {
|
|||
unsigned sz = get_num_uninterpreted_sorts();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
sort * s = get_uninterpreted_sort(i);
|
||||
TRACE("proto_model", tout << "copying uninterpreted sorts...\n" << mk_pp(s, m_manager) << "\n";);
|
||||
TRACE("proto_model", tout << "copying uninterpreted sorts...\n" << mk_pp(s, m) << "\n";);
|
||||
ptr_vector<expr> const& buf = get_universe(s);
|
||||
m->register_usort(s, buf.size(), buf.c_ptr());
|
||||
mdl->register_usort(s, buf.size(), buf.c_ptr());
|
||||
}
|
||||
|
||||
return m;
|
||||
return mdl;
|
||||
}
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ Revision History:
|
|||
#include "util/params.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
|
||||
|
||||
class proto_model : public model_core {
|
||||
plugin_manager<value_factory> m_factories;
|
||||
user_sort_factory * m_user_sort_factory;
|
||||
|
|
|
@ -148,7 +148,7 @@ namespace smt {
|
|||
}
|
||||
|
||||
void qi_queue::instantiate() {
|
||||
unsigned since_last_check = 0;
|
||||
unsigned since_last_check = 0;
|
||||
for (entry & curr : m_new_entries) {
|
||||
fingerprint * f = curr.m_qb;
|
||||
quantifier * qa = static_cast<quantifier*>(f->get_data());
|
||||
|
@ -169,7 +169,6 @@ namespace smt {
|
|||
// Periodically check if we didn't run out of time/memory.
|
||||
if (since_last_check++ > 100) {
|
||||
if (m_context.resource_limits_exceeded()) {
|
||||
// verbose_stream() << "EXCEEDED...\n";
|
||||
break;
|
||||
}
|
||||
since_last_check = 0;
|
||||
|
@ -182,16 +181,7 @@ namespace smt {
|
|||
void qi_queue::display_instance_profile(fingerprint * f, quantifier * q, unsigned num_bindings, enode * const * bindings, unsigned proof_id, unsigned generation) {
|
||||
if (m_manager.has_trace_stream()) {
|
||||
m_manager.trace_stream() << "[instance] ";
|
||||
#if 1
|
||||
m_manager.trace_stream() << static_cast<void*>(f);
|
||||
#else
|
||||
for (unsigned i = 0; i < num_bindings; i++) {
|
||||
// I don't want to use mk_pp because it creates expressions for pretty printing.
|
||||
// This nasty side-effect may change the behavior of Z3.
|
||||
m_manager.trace_stream() << " #" << bindings[i]->get_owner_id();
|
||||
}
|
||||
|
||||
#endif
|
||||
if (m_manager.proofs_enabled())
|
||||
m_manager.trace_stream() << " #" << proof_id;
|
||||
m_manager.trace_stream() << " ; " << generation;
|
||||
|
@ -208,10 +198,7 @@ namespace smt {
|
|||
|
||||
ent.m_instantiated = true;
|
||||
|
||||
TRACE("qi_queue_profile",
|
||||
tout << q->get_qid() << ", gen: " << generation;
|
||||
for (unsigned i = 0; i < num_bindings; i++) tout << " #" << bindings[i]->get_owner_id();
|
||||
tout << "\n";);
|
||||
TRACE("qi_queue_profile", tout << q->get_qid() << ", gen: " << generation << " " << *f;);
|
||||
|
||||
if (m_checker.is_sat(q->get_expr(), num_bindings, bindings)) {
|
||||
TRACE("checker", tout << "instance already satisfied\n";);
|
||||
|
@ -288,6 +275,9 @@ namespace smt {
|
|||
unsigned gen = get_new_gen(q, generation, ent.m_cost);
|
||||
display_instance_profile(f, q, num_bindings, bindings, proof_id, gen);
|
||||
m_context.internalize_instance(lemma, pr1, gen);
|
||||
if (f->get_def()) {
|
||||
m_context.internalize(f->get_def(), true);
|
||||
}
|
||||
TRACE_CODE({
|
||||
static unsigned num_useless = 0;
|
||||
if (m_manager.is_or(lemma)) {
|
||||
|
@ -412,10 +402,7 @@ namespace smt {
|
|||
void qi_queue::display_delayed_instances_stats(std::ostream & out) const {
|
||||
obj_map<quantifier, delayed_qa_info> qa2info;
|
||||
ptr_vector<quantifier> qas;
|
||||
svector<entry>::const_iterator it = m_delayed_entries.begin();
|
||||
svector<entry>::const_iterator end = m_delayed_entries.end();
|
||||
for (; it != end; ++it) {
|
||||
entry const & e = *it;
|
||||
for (entry const & e : m_delayed_entries) {
|
||||
if (e.m_instantiated)
|
||||
continue;
|
||||
quantifier * qa = static_cast<quantifier*>(e.m_qb->get_data());
|
||||
|
@ -433,10 +420,7 @@ namespace smt {
|
|||
}
|
||||
qa2info.insert(qa, info);
|
||||
}
|
||||
ptr_vector<quantifier>::iterator it2 = qas.begin();
|
||||
ptr_vector<quantifier>::iterator end2 = qas.end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
quantifier * qa = *it2;
|
||||
for (quantifier * qa : qas) {
|
||||
delayed_qa_info info;
|
||||
qa2info.find(qa, info);
|
||||
out << qa->get_qid() << ": " << info.m_num << " [" << info.m_min_cost << ", " << info.m_max_cost << "]\n";
|
||||
|
|
|
@ -53,7 +53,7 @@ namespace smt {
|
|||
m_flushing(false),
|
||||
m_progress_callback(nullptr),
|
||||
m_next_progress_sample(0),
|
||||
m_fingerprints(m_region),
|
||||
m_fingerprints(m, m_region),
|
||||
m_b_internalized_stack(m),
|
||||
m_e_internalized_stack(m),
|
||||
m_final_check_idx(0),
|
||||
|
@ -1598,7 +1598,7 @@ namespace smt {
|
|||
for (literal lit : m_assigned_literals) {
|
||||
expr_ref e(m_manager);
|
||||
literal2expr(lit, e);
|
||||
assignments.push_back(e);
|
||||
assignments.push_back(std::move(e));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1789,9 +1789,9 @@ namespace smt {
|
|||
return m_fingerprints.contains(q, q->get_id(), num_bindings, bindings);
|
||||
}
|
||||
|
||||
bool context::add_instance(quantifier * q, app * pat, unsigned num_bindings, enode * const * bindings, unsigned max_generation,
|
||||
bool context::add_instance(quantifier * q, app * pat, unsigned num_bindings, enode * const * bindings, expr* def, unsigned max_generation,
|
||||
unsigned min_top_generation, unsigned max_top_generation, vector<std::tuple<enode *, enode *>> & used_enodes) {
|
||||
return m_qmanager->add_instance(q, pat, num_bindings, bindings, max_generation, min_top_generation, max_top_generation, used_enodes);
|
||||
return m_qmanager->add_instance(q, pat, num_bindings, bindings, def, max_generation, min_top_generation, max_top_generation, used_enodes);
|
||||
}
|
||||
|
||||
void context::rescale_bool_var_activity() {
|
||||
|
@ -2936,7 +2936,7 @@ namespace smt {
|
|||
void context::assert_expr_core(expr * e, proof * pr) {
|
||||
if (get_cancel_flag()) return;
|
||||
SASSERT(is_well_sorted(m_manager, e));
|
||||
TRACE("begin_assert_expr", tout << mk_pp(e, m_manager) << "\n";);
|
||||
TRACE("begin_assert_expr", tout << this << " " << mk_pp(e, m_manager) << "\n";);
|
||||
TRACE("begin_assert_expr_ll", tout << mk_ll_pp(e, m_manager) << "\n";);
|
||||
pop_to_base_lvl();
|
||||
if (pr == nullptr)
|
||||
|
@ -3767,6 +3767,7 @@ namespace smt {
|
|||
}
|
||||
|
||||
m_stats.m_num_final_checks++;
|
||||
TRACE("final_check_stats", tout << "m_stats.m_num_final_checks = " << m_stats.m_num_final_checks << "\n";);
|
||||
|
||||
final_check_status ok = m_qmanager->final_check_eh(false);
|
||||
if (ok != FC_DONE)
|
||||
|
@ -4184,7 +4185,7 @@ namespace smt {
|
|||
SASSERT(get_justification(guess.var()).get_kind() == b_justification::AXIOM);
|
||||
expr_ref lit(m_manager);
|
||||
literal2expr(guess, lit);
|
||||
result.push_back(lit);
|
||||
result.push_back(std::move(lit));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4405,9 +4406,9 @@ namespace smt {
|
|||
for (unsigned i = 0; !get_cancel_flag() && i < m_asserted_formulas.get_num_formulas(); ++i) {
|
||||
expr* e = m_asserted_formulas.get_formula(i);
|
||||
if (is_quantifier(e)) {
|
||||
TRACE("context", tout << mk_pp(e, m) << "\n";);
|
||||
quantifier* q = to_quantifier(e);
|
||||
if (!m.is_rec_fun_def(q)) continue;
|
||||
TRACE("context", tout << mk_pp(e, m) << "\n";);
|
||||
SASSERT(q->get_num_patterns() == 2);
|
||||
expr* fn = to_app(q->get_pattern(0))->get_arg(0);
|
||||
expr* body = to_app(q->get_pattern(1))->get_arg(0);
|
||||
|
@ -4421,7 +4422,7 @@ namespace smt {
|
|||
expr_ref bodyr(m);
|
||||
var_subst sub(m, true);
|
||||
TRACE("context", tout << expr_ref(q, m) << " " << subst << "\n";);
|
||||
sub(body, subst.size(), subst.c_ptr(), bodyr);
|
||||
bodyr = sub(body, subst.size(), subst.c_ptr());
|
||||
func_decl* f = to_app(fn)->get_decl();
|
||||
func_interp* fi = alloc(func_interp, m, f->get_arity());
|
||||
fi->set_else(bodyr);
|
||||
|
|
|
@ -117,6 +117,7 @@ namespace smt {
|
|||
plugin_manager<theory> m_theories; // mapping from theory_id -> theory
|
||||
ptr_vector<theory> m_theory_set; // set of theories for fast traversal
|
||||
vector<enode_vector> m_decl2enodes; // decl -> enode (for decls with arity > 0)
|
||||
enode_vector m_empty_vector;
|
||||
cg_table m_cg_table;
|
||||
dyn_ack_manager m_dyn_ack_manager;
|
||||
struct new_eq {
|
||||
|
@ -457,6 +458,8 @@ namespace smt {
|
|||
theory * get_theory(theory_id th_id) const {
|
||||
return m_theories.get_plugin(th_id);
|
||||
}
|
||||
|
||||
ptr_vector<theory> const& theories() const { return m_theories.plugins(); }
|
||||
|
||||
ptr_vector<theory>::const_iterator begin_theories() const {
|
||||
return m_theories.begin();
|
||||
|
@ -518,6 +521,11 @@ namespace smt {
|
|||
return id < m_decl2enodes.size() ? m_decl2enodes[id].size() : 0;
|
||||
}
|
||||
|
||||
enode_vector const& enodes_of(func_decl const * d) const {
|
||||
unsigned id = d->get_decl_id();
|
||||
return id < m_decl2enodes.size() ? m_decl2enodes[id] : m_empty_vector;
|
||||
}
|
||||
|
||||
enode_vector::const_iterator begin_enodes_of(func_decl const * decl) const {
|
||||
unsigned id = decl->get_decl_id();
|
||||
return id < m_decl2enodes.size() ? m_decl2enodes[id].begin() : nullptr;
|
||||
|
@ -528,6 +536,8 @@ namespace smt {
|
|||
return id < m_decl2enodes.size() ? m_decl2enodes[id].end() : nullptr;
|
||||
}
|
||||
|
||||
ptr_vector<enode> const& enodes() const { return m_enodes; }
|
||||
|
||||
ptr_vector<enode>::const_iterator begin_enodes() const {
|
||||
return m_enodes.begin();
|
||||
}
|
||||
|
@ -554,8 +564,8 @@ namespace smt {
|
|||
return m_asserted_formulas.has_quantifiers();
|
||||
}
|
||||
|
||||
fingerprint * add_fingerprint(void * data, unsigned data_hash, unsigned num_args, enode * const * args) {
|
||||
return m_fingerprints.insert(data, data_hash, num_args, args);
|
||||
fingerprint * add_fingerprint(void * data, unsigned data_hash, unsigned num_args, enode * const * args, expr* def = 0) {
|
||||
return m_fingerprints.insert(data, data_hash, num_args, args, def);
|
||||
}
|
||||
|
||||
theory_id get_var_theory(bool_var v) const {
|
||||
|
@ -737,6 +747,8 @@ namespace smt {
|
|||
|
||||
void internalize_quantifier(quantifier * q, bool gate_ctx);
|
||||
|
||||
void internalize_lambda(quantifier * q);
|
||||
|
||||
void internalize_formula_core(app * n, bool gate_ctx);
|
||||
|
||||
void set_merge_tf(enode * n, bool_var v, bool is_new_var);
|
||||
|
@ -958,7 +970,7 @@ namespace smt {
|
|||
|
||||
bool contains_instance(quantifier * q, unsigned num_bindings, enode * const * bindings);
|
||||
|
||||
bool add_instance(quantifier * q, app * pat, unsigned num_bindings, enode * const * bindings, unsigned max_generation,
|
||||
bool add_instance(quantifier * q, app * pat, unsigned num_bindings, enode * const * bindings, expr* def, unsigned max_generation,
|
||||
unsigned min_top_generation, unsigned max_top_generation, vector<std::tuple<enode *, enode*>> & used_enodes /*gives the equalities used for the pattern match, see mam.cpp for more info*/);
|
||||
|
||||
void set_global_generation(unsigned generation) { m_generation = generation; }
|
||||
|
@ -1104,8 +1116,6 @@ namespace smt {
|
|||
|
||||
void internalize_assertions();
|
||||
|
||||
void assert_assumption(expr * a);
|
||||
|
||||
bool validate_assumptions(expr_ref_vector const& asms);
|
||||
|
||||
void init_assumptions(expr_ref_vector const& asms);
|
||||
|
@ -1118,8 +1128,6 @@ namespace smt {
|
|||
|
||||
void reset_assumptions();
|
||||
|
||||
void reset_clause();
|
||||
|
||||
void add_theory_assumptions(expr_ref_vector & theory_assumptions);
|
||||
|
||||
lbool mk_unsat_core(lbool result);
|
||||
|
@ -1574,8 +1582,6 @@ namespace smt {
|
|||
|
||||
//proof * const * get_asserted_formula_proofs() const { return m_asserted_formulas.get_formula_proofs(); }
|
||||
|
||||
void get_assumptions_core(ptr_vector<expr> & result);
|
||||
|
||||
void get_assertions(ptr_vector<expr> & result) { m_asserted_formulas.get_assertions(result); }
|
||||
|
||||
void display(std::ostream & out) const;
|
||||
|
|
|
@ -409,11 +409,11 @@ namespace smt {
|
|||
for (unsigned i = 0; i < num_antecedents; i++) {
|
||||
literal l = antecedents[i];
|
||||
literal2expr(l, n);
|
||||
fmls.push_back(n);
|
||||
fmls.push_back(std::move(n));
|
||||
}
|
||||
if (consequent != false_literal) {
|
||||
literal2expr(~consequent, n);
|
||||
fmls.push_back(n);
|
||||
fmls.push_back(std::move(n));
|
||||
}
|
||||
if (logic != symbol::null) out << "(set-logic " << logic << ")\n";
|
||||
visitor.collect(fmls);
|
||||
|
|
|
@ -329,6 +329,9 @@ namespace smt {
|
|||
SASSERT(is_quantifier(n) || is_app(n));
|
||||
internalize_formula(n, gate_ctx);
|
||||
}
|
||||
else if (is_lambda(n)) {
|
||||
internalize_lambda(to_quantifier(n));
|
||||
}
|
||||
else {
|
||||
SASSERT(is_app(n));
|
||||
SASSERT(!gate_ctx);
|
||||
|
@ -514,7 +517,7 @@ namespace smt {
|
|||
CTRACE("internalize_quantifier_zero", q->get_weight() == 0, tout << mk_pp(q, m_manager) << "\n";);
|
||||
SASSERT(gate_ctx); // limitation of the current implementation
|
||||
SASSERT(!b_internalized(q));
|
||||
SASSERT(q->is_forall());
|
||||
SASSERT(is_forall(q));
|
||||
SASSERT(check_patterns(q));
|
||||
bool_var v = mk_bool_var(q);
|
||||
unsigned generation = m_generation;
|
||||
|
@ -528,6 +531,31 @@ namespace smt {
|
|||
m_qmanager->add(q, generation);
|
||||
}
|
||||
|
||||
void context::internalize_lambda(quantifier * q) {
|
||||
UNREACHABLE();
|
||||
|
||||
#if 0
|
||||
TRACE("internalize_quantifier", tout << mk_pp(q, m_manager) << "\n";);
|
||||
SASSERT(is_lambda(q));
|
||||
app_ref lam_name(m_manager.mk_fresh_const("lambda", m_manager.get_sort(q)), m_manager);
|
||||
enode * e = mk_enode(lam_name, true, false, false);
|
||||
expr_ref eq(m_manager), lam_app(m_manager);
|
||||
expr_ref_vector vars(m_manager);
|
||||
vars.push_back(lam_name);
|
||||
unsigned sz = q->get_num_decls();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
vars.push_back(m_manager.mk_var(sz - i - 1, q->get_decl_sort(i)));
|
||||
}
|
||||
array_util autil(m_manager);
|
||||
lam_app = autil.mk_select(vars.size(), vars.c_ptr());
|
||||
eq = m_manager.mk_eq(lam_app, q->get_expr());
|
||||
quantifier_ref fa(m_manager);
|
||||
expr * patterns[1] = { m_manager.mk_pattern(lam_name) };
|
||||
fa = m_manager.mk_forall(sz, q->get_decl_sorts(), q->get_decl_names(), eq, 0, m_manager.lambda_def_qid(), symbol::null, 1, patterns);
|
||||
internalize_quantifier(fa, true);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Internalize gates and (uninterpreted and equality) predicates.
|
||||
*/
|
||||
|
@ -821,7 +849,7 @@ namespace smt {
|
|||
std::cerr << v << " ::=\n" << mk_ll_pp(n, m_manager) << "<END-OF-FORMULA>\n";
|
||||
}
|
||||
#endif
|
||||
TRACE("mk_bool_var", tout << "creating boolean variable: " << v << " for:\n" << mk_pp(n, m_manager) << "\n";);
|
||||
TRACE("mk_bool_var", tout << "creating boolean variable: " << v << " for:\n" << mk_pp(n, m_manager) << " " << n->get_id() << "\n";);
|
||||
TRACE("mk_var_bug", tout << "mk_bool: " << v << "\n";);
|
||||
set_bool_var(id, v);
|
||||
m_bdata.reserve(v+1);
|
||||
|
|
|
@ -281,7 +281,7 @@ namespace smt {
|
|||
for (unsigned i = 0; i < m_num_literals; i++) {
|
||||
expr_ref l(m);
|
||||
ctx.literal2expr(m_literals[i], l);
|
||||
lits.push_back(l);
|
||||
lits.push_back(std::move(l));
|
||||
}
|
||||
if (lits.size() == 1)
|
||||
return m.mk_th_lemma(m_th_id, lits.get(0), 0, nullptr, m_params.size(), m_params.c_ptr());
|
||||
|
@ -407,12 +407,7 @@ namespace smt {
|
|||
for (unsigned i = 0; i < m_num_literals; i++) {
|
||||
bool sign = GET_TAG(m_literals[i]) != 0;
|
||||
expr * v = UNTAG(expr*, m_literals[i]);
|
||||
expr_ref l(m);
|
||||
if (sign)
|
||||
l = m.mk_not(v);
|
||||
else
|
||||
l = v;
|
||||
lits.push_back(l);
|
||||
lits.push_back(sign ? m.mk_not(v) : v);
|
||||
}
|
||||
if (lits.size() == 1)
|
||||
return m.mk_th_lemma(m_th_id, lits.get(0), 0, nullptr, m_params.size(), m_params.c_ptr());
|
||||
|
|
|
@ -15,12 +15,19 @@ Author:
|
|||
|
||||
Revision History:
|
||||
|
||||
- to support lambdas/array models:
|
||||
binding sk -> (as-array k!0)
|
||||
then include definition for k!0 as part of binding.
|
||||
Binding instance can be a pointer into m_pinned expressions.
|
||||
|
||||
--*/
|
||||
|
||||
#include "ast/normal_forms/pull_quant.h"
|
||||
#include "ast/for_each_expr.h"
|
||||
#include "ast/rewriter/var_subst.h"
|
||||
#include "ast/rewriter/rewriter_def.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "smt/smt_model_checker.h"
|
||||
#include "smt/smt_context.h"
|
||||
|
@ -54,8 +61,8 @@ namespace smt {
|
|||
}
|
||||
|
||||
void model_checker::set_qm(quantifier_manager & qm) {
|
||||
SASSERT(m_qm == 0);
|
||||
SASSERT(m_context == 0);
|
||||
SASSERT(m_qm == nullptr);
|
||||
SASSERT(m_context == nullptr);
|
||||
m_qm = &qm;
|
||||
m_context = &(m_qm->get_context());
|
||||
}
|
||||
|
@ -64,6 +71,13 @@ namespace smt {
|
|||
\brief Return a term in the context that evaluates to val.
|
||||
*/
|
||||
expr * model_checker::get_term_from_ctx(expr * val) {
|
||||
init_value2expr();
|
||||
expr * t = nullptr;
|
||||
m_value2expr.find(val, t);
|
||||
return t;
|
||||
}
|
||||
|
||||
void model_checker::init_value2expr() {
|
||||
if (m_value2expr.empty()) {
|
||||
// populate m_value2expr
|
||||
for (auto const& kv : *m_root2value) {
|
||||
|
@ -73,9 +87,28 @@ namespace smt {
|
|||
m_value2expr.insert(val, n->get_owner());
|
||||
}
|
||||
}
|
||||
expr * t = nullptr;
|
||||
m_value2expr.find(val, t);
|
||||
return t;
|
||||
}
|
||||
|
||||
expr_ref model_checker::replace_value_from_ctx(expr * e) {
|
||||
init_value2expr();
|
||||
struct beta_reducer_cfg : default_rewriter_cfg {
|
||||
model_checker& mc;
|
||||
beta_reducer_cfg(model_checker& mc):mc(mc) {}
|
||||
bool get_subst(expr * e, expr* & t, proof *& pr) {
|
||||
t = nullptr; pr = nullptr;
|
||||
mc.m_value2expr.find(e, t);
|
||||
return t != nullptr;
|
||||
}
|
||||
};
|
||||
struct beta_reducer : public rewriter_tpl<beta_reducer_cfg> {
|
||||
beta_reducer_cfg m_cfg;
|
||||
beta_reducer(model_checker& m):
|
||||
rewriter_tpl<beta_reducer_cfg>(m.m, false, m_cfg), m_cfg(m) {}
|
||||
};
|
||||
beta_reducer br(*this);
|
||||
expr_ref result(m);
|
||||
br(e, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -95,8 +128,6 @@ namespace smt {
|
|||
m_aux_context->assert_expr(fml);
|
||||
}
|
||||
|
||||
#define PP_DEPTH 8
|
||||
|
||||
/**
|
||||
\brief Assert the negation of q after applying the interpretation in m_curr_model to the uninterpreted symbols in q.
|
||||
|
||||
|
@ -123,9 +154,8 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
|
||||
expr_ref sk_body(m);
|
||||
var_subst s(m);
|
||||
s(tmp, subst_args.size(), subst_args.c_ptr(), sk_body);
|
||||
expr_ref sk_body = s(tmp, subst_args.size(), subst_args.c_ptr());
|
||||
expr_ref r(m);
|
||||
r = m.mk_not(sk_body);
|
||||
TRACE("model_checker", tout << "mk_neg_q_m:\n" << mk_ismt2_pp(r, m) << "\n";);
|
||||
|
@ -133,37 +163,35 @@ namespace smt {
|
|||
}
|
||||
|
||||
bool model_checker::add_instance(quantifier * q, model * cex, expr_ref_vector & sks, bool use_inv) {
|
||||
if (cex == nullptr) {
|
||||
if (cex == nullptr || sks.empty()) {
|
||||
TRACE("model_checker", tout << "no model is available\n";);
|
||||
return false;
|
||||
}
|
||||
array_util autil(m);
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
// Remark: sks were created for the flat version of q.
|
||||
SASSERT(sks.size() >= num_decls);
|
||||
expr_ref_vector bindings(m);
|
||||
expr_ref_vector bindings(m), defs(m);
|
||||
expr_ref def(m);
|
||||
bindings.resize(num_decls);
|
||||
unsigned max_generation = 0;
|
||||
for (unsigned i = 0; i < num_decls; i++) {
|
||||
expr * sk = sks.get(num_decls - i - 1);
|
||||
func_decl * sk_d = to_app(sk)->get_decl();
|
||||
expr_ref sk_value(m);
|
||||
sk_value = cex->get_const_interp(sk_d);
|
||||
if (sk_value == 0) {
|
||||
sk_value = cex->get_some_value(sk_d->get_range());
|
||||
if (sk_value == 0) {
|
||||
TRACE("model_checker", tout << "Could not get value for " << sk_d->get_name() << "\n";);
|
||||
return false; // get_some_value failed... giving up
|
||||
}
|
||||
TRACE("model_checker", tout << "Got some value " << sk_value << "\n";);
|
||||
expr_ref sk_value(cex->get_some_const_interp(sk_d), m);
|
||||
if (!sk_value) {
|
||||
TRACE("model_checker", tout << "Could not get value for " << sk_d->get_name() << "\n";);
|
||||
return false; // get_some_value failed... giving up
|
||||
}
|
||||
TRACE("model_checker", tout << "Got some value " << sk_value << "\n";);
|
||||
|
||||
if (use_inv) {
|
||||
unsigned sk_term_gen;
|
||||
expr * sk_term = m_model_finder.get_inv(q, i, sk_value, sk_term_gen);
|
||||
if (sk_term != nullptr) {
|
||||
TRACE("model_checker", tout << "Found inverse " << mk_pp(sk_term, m) << "\n";);
|
||||
SASSERT(!m.is_model_value(sk_term));
|
||||
if (sk_term_gen > max_generation)
|
||||
max_generation = sk_term_gen;
|
||||
max_generation = std::max(sk_term_gen, max_generation);
|
||||
sk_value = sk_term;
|
||||
}
|
||||
else {
|
||||
|
@ -181,39 +209,48 @@ namespace smt {
|
|||
TRACE("model_checker", tout << "value is private to model: " << sk_value << "\n";);
|
||||
return false;
|
||||
}
|
||||
func_decl * f = nullptr;
|
||||
if (autil.is_as_array(sk_value, f) && cex->get_func_interp(f)) {
|
||||
expr_ref body(cex->get_func_interp(f)->get_interp(), m);
|
||||
ptr_vector<sort> sorts(f->get_arity(), f->get_domain());
|
||||
svector<symbol> names;
|
||||
for (unsigned i = 0; i < f->get_arity(); ++i) {
|
||||
names.push_back(symbol(i));
|
||||
}
|
||||
defined_names dn(m);
|
||||
body = replace_value_from_ctx(body);
|
||||
body = m.mk_lambda(sorts.size(), sorts.c_ptr(), names.c_ptr(), body);
|
||||
// sk_value = m.mk_fresh_const(0, m.get_sort(sk_value)); // get rid of as-array
|
||||
body = dn.mk_definition(body, to_app(sk_value));
|
||||
defs.push_back(body);
|
||||
}
|
||||
bindings.set(num_decls - i - 1, sk_value);
|
||||
}
|
||||
|
||||
TRACE("model_checker", tout << q->get_qid() << " found (use_inv: " << use_inv << ") new instance: ";
|
||||
for (unsigned i = 0; i < num_decls; i++) {
|
||||
tout << mk_ismt2_pp(bindings[i].get(), m) << " ";
|
||||
}
|
||||
tout << "\n";);
|
||||
|
||||
TRACE("model_checker", tout << q->get_qid() << " found (use_inv: " << use_inv << ") new instance: " << bindings << "\n" << defs << "\n";);
|
||||
if (!defs.empty()) def = mk_and(defs);
|
||||
max_generation = std::max(m_qm->get_generation(q), max_generation);
|
||||
add_instance(q, bindings, max_generation);
|
||||
add_instance(q, bindings, max_generation, def.get());
|
||||
return true;
|
||||
}
|
||||
|
||||
void model_checker::add_instance(quantifier* q, expr_ref_vector const& bindings, unsigned max_generation) {
|
||||
void model_checker::add_instance(quantifier* q, expr_ref_vector const& bindings, unsigned max_generation, expr* def) {
|
||||
SASSERT(q->get_num_decls() == bindings.size());
|
||||
for (expr* b : bindings)
|
||||
m_pinned_exprs.push_back(b);
|
||||
unsigned offset = m_pinned_exprs.size();
|
||||
m_pinned_exprs.append(bindings);
|
||||
m_pinned_exprs.push_back(q);
|
||||
|
||||
void * mem = m_new_instances_region.allocate(instance::get_obj_size(q->get_num_decls()));
|
||||
instance * new_inst = new (mem) instance(q, bindings.c_ptr(), max_generation);
|
||||
m_new_instances.push_back(new_inst);
|
||||
m_pinned_exprs.push_back(def);
|
||||
m_new_instances.push_back(instance(q, offset, def, max_generation));
|
||||
}
|
||||
|
||||
void model_checker::operator()(expr *n) {
|
||||
if (m.is_model_value(n) || m_autil.is_as_array(n)) {
|
||||
if (m.is_model_value(n) /*|| m_autil.is_as_array(n)*/) {
|
||||
throw is_model_value();
|
||||
}
|
||||
}
|
||||
|
||||
bool model_checker::contains_model_value(expr* n) {
|
||||
if (m.is_model_value(n) || m_autil.is_as_array(n)) {
|
||||
if (m.is_model_value(n) /*|| m_autil.is_as_array(n)*/) {
|
||||
return true;
|
||||
}
|
||||
if (is_app(n) && to_app(n)->get_num_args() == 0) {
|
||||
|
@ -231,16 +268,13 @@ namespace smt {
|
|||
|
||||
|
||||
bool model_checker::add_blocking_clause(model * cex, expr_ref_vector & sks) {
|
||||
SASSERT(cex != 0);
|
||||
SASSERT(cex != nullptr);
|
||||
expr_ref_buffer diseqs(m);
|
||||
for (expr * sk : sks) {
|
||||
func_decl * sk_d = to_app(sk)->get_decl();
|
||||
expr_ref sk_value(m);
|
||||
sk_value = cex->get_const_interp(sk_d);
|
||||
if (sk_value == 0) {
|
||||
sk_value = cex->get_some_value(sk_d->get_range());
|
||||
if (sk_value == 0)
|
||||
return false; // get_some_value failed... aborting add_blocking_clause
|
||||
expr_ref sk_value(cex->get_some_const_interp(sk_d), m);
|
||||
if (!sk_value) {
|
||||
return false; // get_some_value failed... aborting add_blocking_clause
|
||||
}
|
||||
diseqs.push_back(m.mk_not(m.mk_eq(sk, sk_value)));
|
||||
}
|
||||
|
@ -251,40 +285,43 @@ namespace smt {
|
|||
return true;
|
||||
}
|
||||
|
||||
struct scoped_ctx_push {
|
||||
context* c;
|
||||
scoped_ctx_push(context* c): c(c) { c->push(); }
|
||||
~scoped_ctx_push() { c->pop(1); }
|
||||
};
|
||||
|
||||
/**
|
||||
\brief Return true if q is satisfied by m_curr_model.
|
||||
*/
|
||||
bool model_checker::check(quantifier * q) {
|
||||
SASSERT(!m_aux_context->relevancy());
|
||||
m_aux_context->push();
|
||||
scoped_ctx_push _push(m_aux_context.get());
|
||||
|
||||
quantifier * flat_q = get_flat_quantifier(q);
|
||||
TRACE("model_checker", tout << "model checking:\n" << mk_ismt2_pp(q->get_expr(), m) << "\n" <<
|
||||
mk_ismt2_pp(flat_q->get_expr(), m) << "\n";);
|
||||
TRACE("model_checker", tout << "model checking:\n" << expr_ref(q->get_expr(), m) << "\n" << expr_ref(flat_q->get_expr(), m) << "\n";);
|
||||
expr_ref_vector sks(m);
|
||||
|
||||
assert_neg_q_m(flat_q, sks);
|
||||
TRACE("model_checker", tout << "skolems:\n";
|
||||
for (expr* sk : sks) {
|
||||
tout << mk_ismt2_pp(sk, m) << " " << mk_pp(m.get_sort(sk), m) << "\n";
|
||||
});
|
||||
TRACE("model_checker", tout << "skolems:\n" << sks << "\n";);
|
||||
|
||||
flet<bool> l(m_aux_context->get_fparams().m_array_fake_support, true);
|
||||
lbool r = m_aux_context->check();
|
||||
TRACE("model_checker", tout << "[complete] model-checker result: " << to_sat_str(r) << "\n";);
|
||||
if (r != l_true) {
|
||||
m_aux_context->pop(1);
|
||||
if (r != l_true) {
|
||||
return r == l_false; // quantifier is satisfied by m_curr_model
|
||||
}
|
||||
|
||||
model_ref complete_cex;
|
||||
m_aux_context->get_model(complete_cex);
|
||||
|
||||
|
||||
// try to find new instances using instantiation sets.
|
||||
m_model_finder.restrict_sks_to_inst_set(m_aux_context.get(), q, sks);
|
||||
|
||||
|
||||
unsigned num_new_instances = 0;
|
||||
|
||||
|
||||
while (true) {
|
||||
flet<bool> l(m_aux_context->get_fparams().m_array_fake_support, true);
|
||||
lbool r = m_aux_context->check();
|
||||
TRACE("model_checker", tout << "[restricted] model-checker (" << (num_new_instances+1) << ") result: " << to_sat_str(r) << "\n";);
|
||||
if (r != l_true)
|
||||
|
@ -308,7 +345,6 @@ namespace smt {
|
|||
add_instance(q, complete_cex.get(), sks, false);
|
||||
}
|
||||
|
||||
m_aux_context->pop(1);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -318,33 +354,29 @@ namespace smt {
|
|||
expr* fn = to_app(q->get_pattern(0))->get_arg(0);
|
||||
SASSERT(is_app(fn));
|
||||
func_decl* f = to_app(fn)->get_decl();
|
||||
enode_vector::const_iterator it = m_context->begin_enodes_of(f);
|
||||
enode_vector::const_iterator end = m_context->end_enodes_of(f);
|
||||
|
||||
bool is_undef = false;
|
||||
expr_ref_vector args(m);
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
args.resize(num_decls, nullptr);
|
||||
var_subst sub(m);
|
||||
expr_ref tmp(m), result(m);
|
||||
for (; it != end; ++it) {
|
||||
if (m_context->is_relevant(*it)) {
|
||||
app* e = (*it)->get_owner();
|
||||
for (enode* n : m_context->enodes_of(f)) {
|
||||
if (m_context->is_relevant(n)) {
|
||||
app* e = n->get_owner();
|
||||
SASSERT(e->get_num_args() == num_decls);
|
||||
for (unsigned i = 0; i < num_decls; ++i) {
|
||||
args[i] = e->get_arg(i);
|
||||
}
|
||||
sub(q->get_expr(), num_decls, args.c_ptr(), tmp);
|
||||
tmp = sub(q->get_expr(), num_decls, args.c_ptr());
|
||||
m_curr_model->eval(tmp, result, true);
|
||||
if (strict_rec_fun ? !m.is_true(result) : m.is_false(result)) {
|
||||
add_instance(q, args, 0);
|
||||
add_instance(q, args, 0, nullptr);
|
||||
return false;
|
||||
}
|
||||
TRACE("model_checker", tout << tmp << "\nevaluates to:\n" << result << "\n";);
|
||||
// if (!m.is_true(result)) is_undef = true;
|
||||
TRACE("model_checker", tout << tmp << "\nevaluates to:\n" << result << "\n";);
|
||||
}
|
||||
}
|
||||
return !is_undef;
|
||||
return true;
|
||||
}
|
||||
|
||||
void model_checker::init_aux_context() {
|
||||
|
@ -360,7 +392,7 @@ namespace smt {
|
|||
}
|
||||
|
||||
bool model_checker::check(proto_model * md, obj_map<enode, app *> const & root2value) {
|
||||
SASSERT(md != 0);
|
||||
SASSERT(md != nullptr);
|
||||
|
||||
m_root2value = &root2value;
|
||||
|
||||
|
@ -391,7 +423,6 @@ namespace smt {
|
|||
|
||||
check_quantifiers(false, found_relevant, num_failures);
|
||||
|
||||
|
||||
if (found_relevant)
|
||||
m_iteration_idx++;
|
||||
|
||||
|
@ -416,35 +447,47 @@ namespace smt {
|
|||
return num_failures == 0;
|
||||
}
|
||||
|
||||
//
|
||||
// (repeated from defined_names.cpp)
|
||||
// NB. The pattern for lambdas is incomplete.
|
||||
// consider store(a, i, v) == \lambda j . if i = j then v else a[j]
|
||||
// the instantiation rules for store(a, i, v) are:
|
||||
// sotre(a, i, v)[j] = if i = j then v else a[j] with patterns {a[j], store(a, i, v)} { store(a, i, v)[j] }
|
||||
// The first pattern is not included.
|
||||
// TBD use a model-based scheme for exracting instantiations instead of
|
||||
// using multi-patterns.
|
||||
//
|
||||
|
||||
void model_checker::check_quantifiers(bool strict_rec_fun, bool& found_relevant, unsigned& num_failures) {
|
||||
ptr_vector<quantifier>::const_iterator it = m_qm->begin_quantifiers();
|
||||
ptr_vector<quantifier>::const_iterator end = m_qm->end_quantifiers();
|
||||
for (; it != end; ++it) {
|
||||
quantifier * q = *it;
|
||||
if(!m_qm->mbqi_enabled(q)) continue;
|
||||
for (quantifier * q : *m_qm) {
|
||||
if (!(m_qm->mbqi_enabled(q) &&
|
||||
m_context->is_relevant(q) &&
|
||||
m_context->get_assignment(q) == l_true &&
|
||||
!m.is_lambda_def(q))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
TRACE("model_checker",
|
||||
tout << "Check: " << mk_pp(q, m) << "\n";
|
||||
tout << m_context->get_assignment(q) << "\n";);
|
||||
|
||||
if (m_context->is_relevant(q) && m_context->get_assignment(q) == l_true) {
|
||||
if (m_params.m_mbqi_trace && q->get_qid() != symbol::null) {
|
||||
verbose_stream() << "(smt.mbqi :checking " << q->get_qid() << ")\n";
|
||||
}
|
||||
found_relevant = true;
|
||||
if (m.is_rec_fun_def(q)) {
|
||||
if (!check_rec_fun(q, strict_rec_fun)) {
|
||||
TRACE("model_checker", tout << "checking recursive function failed\n";);
|
||||
num_failures++;
|
||||
}
|
||||
}
|
||||
else if (!check(q)) {
|
||||
if (m_params.m_mbqi_trace || get_verbosity_level() >= 5) {
|
||||
IF_VERBOSE(0, verbose_stream() << "(smt.mbqi :failed " << q->get_qid() << ")\n");
|
||||
}
|
||||
TRACE("model_checker", tout << "checking quantifier " << mk_pp(q, m) << " failed\n";);
|
||||
if (m_params.m_mbqi_trace && q->get_qid() != symbol::null) {
|
||||
verbose_stream() << "(smt.mbqi :checking " << q->get_qid() << ")\n";
|
||||
}
|
||||
found_relevant = true;
|
||||
if (m.is_rec_fun_def(q)) {
|
||||
if (!check_rec_fun(q, strict_rec_fun)) {
|
||||
TRACE("model_checker", tout << "checking recursive function failed\n";);
|
||||
num_failures++;
|
||||
}
|
||||
}
|
||||
else if (!check(q)) {
|
||||
if (m_params.m_mbqi_trace || get_verbosity_level() >= 5) {
|
||||
IF_VERBOSE(0, verbose_stream() << "(smt.mbqi :failed " << q->get_qid() << ")\n");
|
||||
}
|
||||
TRACE("model_checker", tout << "checking quantifier " << mk_pp(q, m) << " failed\n";);
|
||||
num_failures++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -467,7 +510,6 @@ namespace smt {
|
|||
void model_checker::reset_new_instances() {
|
||||
m_pinned_exprs.reset();
|
||||
m_new_instances.reset();
|
||||
m_new_instances_region.reset();
|
||||
}
|
||||
|
||||
void model_checker::reset() {
|
||||
|
@ -478,32 +520,30 @@ namespace smt {
|
|||
TRACE("model_checker_bug_detail", tout << "assert_new_instances, inconsistent: " << m_context->inconsistent() << "\n";);
|
||||
ptr_buffer<enode> bindings;
|
||||
vector<std::tuple<enode *, enode *>> dummy;
|
||||
for (instance* inst : m_new_instances) {
|
||||
quantifier * q = inst->m_q;
|
||||
for (instance const& inst : m_new_instances) {
|
||||
quantifier * q = inst.m_q;
|
||||
if (m_context->b_internalized(q)) {
|
||||
bindings.reset();
|
||||
unsigned num_decls = q->get_num_decls();
|
||||
unsigned gen = inst->m_generation;
|
||||
unsigned gen = inst.m_generation;
|
||||
unsigned offset = inst.m_bindings_offset;
|
||||
for (unsigned i = 0; i < num_decls; i++) {
|
||||
expr * b = inst->m_bindings[i];
|
||||
expr * b = m_pinned_exprs.get(offset + i);
|
||||
if (!m_context->e_internalized(b)) {
|
||||
TRACE("model_checker_bug_detail", tout << "internalizing b:\n" << mk_pp(b, m) << "\n";);
|
||||
TRACE("model_checker", tout << "internalizing b:\n" << mk_pp(b, m) << "\n";);
|
||||
m_context->internalize(b, false, gen);
|
||||
}
|
||||
bindings.push_back(m_context->get_enode(b));
|
||||
}
|
||||
|
||||
if (inst.m_def) {
|
||||
m_context->internalize_assertion(inst.m_def, 0, gen);
|
||||
}
|
||||
|
||||
TRACE("model_checker_bug_detail", tout << "instantiating... q:\n" << mk_pp(q, m) << "\n";
|
||||
tout << "inconsistent: " << m_context->inconsistent() << "\n";
|
||||
tout << "bindings:\n";
|
||||
for (unsigned i = 0; i < num_decls; i++) {
|
||||
expr * b = inst->m_bindings[i];
|
||||
tout << mk_pp(b, m) << "\n";
|
||||
});
|
||||
TRACE("model_checker_instance",
|
||||
expr_ref inst_expr(m);
|
||||
instantiate(m, q, inst->m_bindings, inst_expr);
|
||||
tout << "(assert " << mk_ismt2_pp(inst_expr, m) << ")\n";);
|
||||
m_context->add_instance(q, nullptr, num_decls, bindings.c_ptr(), gen, gen, gen, dummy);
|
||||
tout << "bindings:\n" << expr_ref_vector(m, num_decls, m_pinned_exprs.c_ptr() + offset) << "\n";);
|
||||
m_context->add_instance(q, nullptr, num_decls, bindings.c_ptr(), inst.m_def, gen, gen, gen, dummy);
|
||||
TRACE("model_checker_bug_detail", tout << "after instantiating, inconsistent: " << m_context->inconsistent() << "\n";);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,12 +21,12 @@ Revision History:
|
|||
#ifndef SMT_MODEL_CHECKER_H_
|
||||
#define SMT_MODEL_CHECKER_H_
|
||||
|
||||
#include "util/obj_hashtable.h"
|
||||
#include "ast/ast.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
#include "util/obj_hashtable.h"
|
||||
#include "ast/normal_forms/defined_names.h"
|
||||
#include "smt/params/qi_params.h"
|
||||
#include "smt/params/smt_params.h"
|
||||
#include "util/region.h"
|
||||
|
||||
class proto_model;
|
||||
class model;
|
||||
|
@ -56,7 +56,9 @@ namespace smt {
|
|||
friend class instantiation_set;
|
||||
|
||||
void init_aux_context();
|
||||
void init_value2expr();
|
||||
expr * get_term_from_ctx(expr * val);
|
||||
expr_ref replace_value_from_ctx(expr * e);
|
||||
void restrict_to_universe(expr * sk, obj_hashtable<expr> const & universe);
|
||||
void assert_neg_q_m(quantifier * q, expr_ref_vector & sks);
|
||||
bool add_blocking_clause(model * cex, expr_ref_vector & sks);
|
||||
|
@ -67,15 +69,12 @@ namespace smt {
|
|||
struct instance {
|
||||
quantifier * m_q;
|
||||
unsigned m_generation;
|
||||
expr * m_bindings[0];
|
||||
static unsigned get_obj_size(unsigned num_bindings) { return sizeof(instance) + num_bindings * sizeof(expr*); }
|
||||
instance(quantifier * q, expr * const * bindings, unsigned gen):m_q(q), m_generation(gen) {
|
||||
memcpy(m_bindings, bindings, q->get_num_decls() * sizeof(expr*));
|
||||
}
|
||||
expr * m_def;
|
||||
unsigned m_bindings_offset;
|
||||
instance(quantifier * q, unsigned offset, expr* def, unsigned gen):m_q(q), m_generation(gen), m_def(def), m_bindings_offset(offset) {}
|
||||
};
|
||||
|
||||
region m_new_instances_region;
|
||||
ptr_vector<instance> m_new_instances;
|
||||
svector<instance> m_new_instances;
|
||||
expr_ref_vector m_pinned_exprs;
|
||||
bool add_instance(quantifier * q, model * cex, expr_ref_vector & sks, bool use_inv);
|
||||
void reset_new_instances();
|
||||
|
@ -86,7 +85,7 @@ namespace smt {
|
|||
struct is_model_value {};
|
||||
expr_mark m_visited;
|
||||
bool contains_model_value(expr * e);
|
||||
void add_instance(quantifier * q, expr_ref_vector const & bindings, unsigned max_generation);
|
||||
void add_instance(quantifier * q, expr_ref_vector const & bindings, unsigned max_generation, expr * def);
|
||||
|
||||
public:
|
||||
model_checker(ast_manager & m, qi_params const & p, model_finder & mf);
|
||||
|
|
|
@ -76,16 +76,16 @@ namespace smt {
|
|||
\brief Instantiation sets are the S_{k,j} sets in the Complete quantifier instantiation paper.
|
||||
*/
|
||||
class instantiation_set {
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
obj_map<expr, unsigned> m_elems; // and the associated generation
|
||||
obj_map<expr, expr *> m_inv;
|
||||
expr_mark m_visited;
|
||||
public:
|
||||
instantiation_set(ast_manager & m):m_manager(m) {}
|
||||
instantiation_set(ast_manager & m):m(m) {}
|
||||
|
||||
~instantiation_set() {
|
||||
for (auto const& kv : m_elems) {
|
||||
m_manager.dec_ref(kv.m_key);
|
||||
m.dec_ref(kv.m_key);
|
||||
}
|
||||
m_elems.reset();
|
||||
}
|
||||
|
@ -95,10 +95,10 @@ namespace smt {
|
|||
void insert(expr * n, unsigned generation) {
|
||||
if (m_elems.contains(n) || contains_model_value(n))
|
||||
return;
|
||||
TRACE("model_finder", tout << mk_pp(n, m_manager) << "\n";);
|
||||
m_manager.inc_ref(n);
|
||||
TRACE("model_finder", tout << mk_pp(n, m) << "\n";);
|
||||
m.inc_ref(n);
|
||||
m_elems.insert(n, generation);
|
||||
SASSERT(!m_manager.is_model_value(n));
|
||||
SASSERT(!m.is_model_value(n));
|
||||
}
|
||||
|
||||
void remove(expr * n) {
|
||||
|
@ -106,16 +106,16 @@ namespace smt {
|
|||
SASSERT(m_elems.contains(n));
|
||||
SASSERT(m_inv.empty());
|
||||
m_elems.erase(n);
|
||||
m_manager.dec_ref(n);
|
||||
m.dec_ref(n);
|
||||
}
|
||||
|
||||
void display(std::ostream & out) const {
|
||||
for (auto const& kv : m_elems) {
|
||||
out << mk_bounded_pp(kv.m_key, m_manager) << " [" << kv.m_value << "]\n";
|
||||
out << mk_bounded_pp(kv.m_key, m) << " [" << kv.m_value << "]\n";
|
||||
}
|
||||
out << "inverse:\n";
|
||||
for (auto const& kv : m_inv) {
|
||||
out << mk_bounded_pp(kv.m_key, m_manager) << " -> " << mk_bounded_pp(kv.m_value, m_manager) << "\n";
|
||||
out << mk_bounded_pp(kv.m_key, m) << " -> " << mk_bounded_pp(kv.m_value, m) << "\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -138,7 +138,7 @@ namespace smt {
|
|||
unsigned gen = kv.m_value;
|
||||
expr * t_val = ev.eval(t, true);
|
||||
if (!t_val) break;
|
||||
TRACE("model_finder", tout << mk_pp(t, m_manager) << " " << mk_pp(t_val, m_manager) << "\n";);
|
||||
TRACE("model_finder", tout << mk_pp(t, m) << " " << mk_pp(t_val, m) << "\n";);
|
||||
|
||||
expr * old_t = nullptr;
|
||||
if (m_inv.find(t_val, old_t)) {
|
||||
|
@ -161,13 +161,13 @@ namespace smt {
|
|||
|
||||
struct is_model_value {};
|
||||
void operator()(expr *n) {
|
||||
if (m_manager.is_model_value(n)) {
|
||||
if (m.is_model_value(n)) {
|
||||
throw is_model_value();
|
||||
}
|
||||
}
|
||||
|
||||
bool contains_model_value(expr* n) {
|
||||
if (m_manager.is_model_value(n)) {
|
||||
if (m.is_model_value(n)) {
|
||||
return true;
|
||||
}
|
||||
if (is_app(n) && to_app(n)->get_num_args() == 0) {
|
||||
|
@ -393,6 +393,7 @@ namespace smt {
|
|||
ast_manager & m;
|
||||
arith_util m_arith;
|
||||
bv_util m_bv;
|
||||
array_util m_array;
|
||||
ptr_vector<node> m_nodes;
|
||||
unsigned m_next_node_id;
|
||||
key2node m_uvars;
|
||||
|
@ -427,16 +428,16 @@ namespace smt {
|
|||
m_eval_cache_range.reset();
|
||||
}
|
||||
|
||||
node * mk_node(key2node & m, ast * n, unsigned i, sort * s) {
|
||||
node * mk_node(key2node & map, ast * n, unsigned i, sort * s) {
|
||||
node * r = nullptr;
|
||||
ast_idx_pair k(n, i);
|
||||
if (m.find(k, r)) {
|
||||
if (map.find(k, r)) {
|
||||
SASSERT(r->get_sort() == s);
|
||||
return r;
|
||||
}
|
||||
r = alloc(node, m_next_node_id, s);
|
||||
m_next_node_id++;
|
||||
m.insert(k, r);
|
||||
map.insert(k, r);
|
||||
m_nodes.push_back(r);
|
||||
return r;
|
||||
}
|
||||
|
@ -468,6 +469,7 @@ namespace smt {
|
|||
m(m),
|
||||
m_arith(m),
|
||||
m_bv(m),
|
||||
m_array(m),
|
||||
m_next_node_id(0),
|
||||
m_context(nullptr),
|
||||
m_ks(m),
|
||||
|
@ -651,6 +653,7 @@ namespace smt {
|
|||
a set of values.
|
||||
*/
|
||||
app * get_k_for(sort * s) {
|
||||
TRACE("model_finder", tout << sort_ref(s, m) << "\n";);
|
||||
SASSERT(is_infinite(s));
|
||||
app * r = nullptr;
|
||||
if (m_sort2k.find(s, r))
|
||||
|
@ -709,6 +712,7 @@ namespace smt {
|
|||
}
|
||||
|
||||
void set_projection_else(node * n) {
|
||||
TRACE("model_finder", n->display(tout, m););
|
||||
SASSERT(n->is_root());
|
||||
SASSERT(!n->is_mono_proj());
|
||||
instantiation_set const * s = n->get_instantiation_set();
|
||||
|
@ -856,7 +860,6 @@ namespace smt {
|
|||
bool is_signed = n->is_signed_proj();
|
||||
unsigned sz = values.size();
|
||||
SASSERT(sz > 0);
|
||||
func_decl * p = m.mk_fresh_func_decl(1, &s, s);
|
||||
expr * pi = values[sz - 1];
|
||||
expr_ref var(m);
|
||||
var = m.mk_var(0, s);
|
||||
|
@ -872,11 +875,14 @@ namespace smt {
|
|||
}
|
||||
func_interp * rpi = alloc(func_interp, m, 1);
|
||||
rpi->set_else(pi);
|
||||
func_decl * p = m.mk_fresh_func_decl(1, &s, s);
|
||||
TRACE("model_finder", tout << expr_ref(pi, m) << "\n";);
|
||||
m_model->register_aux_decl(p, rpi);
|
||||
n->set_proj(p);
|
||||
}
|
||||
|
||||
void mk_simple_proj(node * n) {
|
||||
TRACE("model_finder", n->display(tout, m););
|
||||
set_projection_else(n);
|
||||
ptr_buffer<expr> values;
|
||||
get_instantiation_set_values(n, values);
|
||||
|
@ -887,7 +893,7 @@ namespace smt {
|
|||
if (n->get_else()) {
|
||||
expr * else_val = eval(n->get_else(), true);
|
||||
pi->set_else(else_val);
|
||||
}
|
||||
}
|
||||
for (expr * v : values) {
|
||||
pi->insert_new_entry(&v, v);
|
||||
}
|
||||
|
@ -972,9 +978,8 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
expr_ref_vector trail(m);
|
||||
for (unsigned i = 0; i < need_fresh.size(); ++i) {
|
||||
for (node * n : need_fresh) {
|
||||
expr * e;
|
||||
node* n = need_fresh[i];
|
||||
sort* s = n->get_sort();
|
||||
if (!sort2elems.find(s, e)) {
|
||||
e = m.mk_fresh_const("elem", s);
|
||||
|
@ -1173,10 +1178,7 @@ namespace smt {
|
|||
|
||||
void populate_inst_sets(quantifier * q, auf_solver & s, context * ctx) override {
|
||||
node * A_f_i = s.get_A_f_i(m_f, m_arg_i);
|
||||
enode_vector::const_iterator it = ctx->begin_enodes_of(m_f);
|
||||
enode_vector::const_iterator end = ctx->end_enodes_of(m_f);
|
||||
for (; it != end; it++) {
|
||||
enode * n = *it;
|
||||
for (enode * n : ctx->enodes_of(m_f)) {
|
||||
if (ctx->is_relevant(n)) {
|
||||
// Remark: it is incorrect to use
|
||||
// n->get_arg(m_arg_i)->get_root()
|
||||
|
@ -1203,10 +1205,7 @@ namespace smt {
|
|||
instantiation_set * s = uvar_inst_sets[m_var_j];
|
||||
SASSERT(s != 0);
|
||||
|
||||
enode_vector::const_iterator it = ctx->begin_enodes_of(m_f);
|
||||
enode_vector::const_iterator end = ctx->end_enodes_of(m_f);
|
||||
for (; it != end; it++) {
|
||||
enode * n = *it;
|
||||
for (enode * n : ctx->enodes_of(m_f)) {
|
||||
if (ctx->is_relevant(n)) {
|
||||
enode * e_arg = n->get_arg(m_arg_i);
|
||||
expr * arg = e_arg->get_owner();
|
||||
|
@ -1255,10 +1254,7 @@ namespace smt {
|
|||
// there is no finite fixpoint... we just copy the i-th arguments of A_f_i - m_offset
|
||||
// hope for the best...
|
||||
node * S_j = s.get_uvar(q, m_var_j);
|
||||
enode_vector::const_iterator it = ctx->begin_enodes_of(m_f);
|
||||
enode_vector::const_iterator end = ctx->end_enodes_of(m_f);
|
||||
for (; it != end; it++) {
|
||||
enode * n = *it;
|
||||
for (enode * n : ctx->enodes_of(m_f)) {
|
||||
if (ctx->is_relevant(n)) {
|
||||
arith_rewriter arith_rw(ctx->get_manager());
|
||||
bv_util bv(ctx->get_manager());
|
||||
|
@ -1375,7 +1371,7 @@ namespace smt {
|
|||
|
||||
class select_var : public qinfo {
|
||||
protected:
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
array_util m_array;
|
||||
app * m_select; // It must satisfy is_auf_select... see bool is_auf_select(expr * t) const
|
||||
unsigned m_arg_i;
|
||||
|
@ -1384,6 +1380,7 @@ namespace smt {
|
|||
app * get_array() const { return to_app(m_select->get_arg(0)); }
|
||||
|
||||
func_decl * get_array_func_decl(app * ground_array, auf_solver & s) {
|
||||
TRACE("model_evaluator", tout << expr_ref(ground_array, m) << "\n";);
|
||||
expr * ground_array_interp = s.eval(ground_array, false);
|
||||
if (ground_array_interp != nullptr && m_array.is_as_array(ground_array_interp))
|
||||
return m_array.get_as_array_func_decl(ground_array_interp);
|
||||
|
@ -1391,7 +1388,7 @@ namespace smt {
|
|||
}
|
||||
|
||||
public:
|
||||
select_var(ast_manager & m, app * s, unsigned i, unsigned j):m_manager(m), m_array(m), m_select(s), m_arg_i(i), m_var_j(j) {}
|
||||
select_var(ast_manager & m, app * s, unsigned i, unsigned j):m(m), m_array(m), m_select(s), m_arg_i(i), m_var_j(j) {}
|
||||
~select_var() override {}
|
||||
|
||||
char const * get_kind() const override {
|
||||
|
@ -1406,7 +1403,7 @@ namespace smt {
|
|||
}
|
||||
|
||||
void display(std::ostream & out) const override {
|
||||
out << "(" << mk_bounded_pp(m_select, m_manager) << ":" << m_arg_i << " -> v!" << m_var_j << ")";
|
||||
out << "(" << mk_bounded_pp(m_select, m) << ":" << m_arg_i << " -> v!" << m_var_j << ")";
|
||||
}
|
||||
|
||||
void process_auf(quantifier * q, auf_solver & s, context * ctx) override {
|
||||
|
@ -1415,7 +1412,7 @@ namespace smt {
|
|||
TRACE("select_var",
|
||||
tout << "enodes matching: "; display(tout); tout << "\n";
|
||||
for (enode* n : arrays) {
|
||||
tout << "#" << n->get_owner()->get_id() << "\n" << mk_pp(n->get_owner(), m_manager) << "\n";
|
||||
tout << "#" << n->get_owner()->get_id() << "\n" << mk_pp(n->get_owner(), m) << "\n";
|
||||
});
|
||||
node * n1 = s.get_uvar(q, m_var_j);
|
||||
for (enode* n : arrays) {
|
||||
|
@ -1574,10 +1571,7 @@ namespace smt {
|
|||
// For uninterpreted sorts, we add all terms in the context.
|
||||
// See Section 4.1 in the paper "Complete Quantifier Instantiation"
|
||||
node * S_q_i = slv.get_uvar(q, m_var_i);
|
||||
ptr_vector<enode>::const_iterator it = ctx->begin_enodes();
|
||||
ptr_vector<enode>::const_iterator end = ctx->end_enodes();
|
||||
for (; it != end; ++it) {
|
||||
enode * n = *it;
|
||||
for (enode * n : ctx->enodes()) {
|
||||
if (ctx->is_relevant(n) && get_sort(n->get_owner()) == s) {
|
||||
S_q_i->insert(n->get_owner(), n->get_generation());
|
||||
}
|
||||
|
@ -1623,7 +1617,7 @@ namespace smt {
|
|||
|
||||
class cond_macro {
|
||||
protected:
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
func_decl * m_f;
|
||||
expr * m_def;
|
||||
expr * m_cond;
|
||||
|
@ -1633,7 +1627,7 @@ namespace smt {
|
|||
unsigned m_weight;
|
||||
public:
|
||||
cond_macro(ast_manager & m, func_decl * f, expr * def, expr * cond, bool ineq, bool satisfy_atom, bool hint, unsigned weight):
|
||||
m_manager(m),
|
||||
m(m),
|
||||
m_f(f),
|
||||
m_def(def),
|
||||
m_cond(cond),
|
||||
|
@ -1641,14 +1635,14 @@ namespace smt {
|
|||
m_satisfy_atom(satisfy_atom),
|
||||
m_hint(hint),
|
||||
m_weight(weight) {
|
||||
m_manager.inc_ref(m_def);
|
||||
m_manager.inc_ref(m_cond);
|
||||
m.inc_ref(m_def);
|
||||
m.inc_ref(m_cond);
|
||||
SASSERT(!m_hint || m_cond == 0);
|
||||
}
|
||||
|
||||
~cond_macro() {
|
||||
m_manager.dec_ref(m_def);
|
||||
m_manager.dec_ref(m_cond);
|
||||
m.dec_ref(m_def);
|
||||
m.dec_ref(m_cond);
|
||||
}
|
||||
|
||||
func_decl * get_f() const { return m_f; }
|
||||
|
@ -1657,7 +1651,7 @@ namespace smt {
|
|||
|
||||
expr * get_cond() const { return m_cond; }
|
||||
|
||||
bool is_unconditional() const { return m_cond == nullptr || m_manager.is_true(m_cond); }
|
||||
bool is_unconditional() const { return m_cond == nullptr || m.is_true(m_cond); }
|
||||
|
||||
bool satisfy_atom() const { return m_satisfy_atom; }
|
||||
|
||||
|
@ -1668,11 +1662,11 @@ namespace smt {
|
|||
}
|
||||
|
||||
void display(std::ostream & out) const {
|
||||
out << "[" << m_f->get_name() << " -> " << mk_bounded_pp(m_def, m_manager, 6);
|
||||
out << "[" << m_f->get_name() << " -> " << mk_bounded_pp(m_def, m, 6);
|
||||
if (m_hint)
|
||||
out << " *hint*";
|
||||
else
|
||||
out << " when " << mk_bounded_pp(m_cond, m_manager, 6);
|
||||
out << " when " << mk_bounded_pp(m_cond, m, 6);
|
||||
out << "] weight: " << m_weight;
|
||||
}
|
||||
|
||||
|
@ -1739,7 +1733,7 @@ namespace smt {
|
|||
m_has_x_eq_y(false),
|
||||
m_the_one(nullptr),
|
||||
m_uvar_inst_sets(nullptr) {
|
||||
if (has_quantifiers(q->get_expr())) {
|
||||
if (has_quantifiers(q->get_expr()) && !m.is_lambda_def(q)) {
|
||||
static bool displayed_flat_msg = false;
|
||||
if (!displayed_flat_msg) {
|
||||
// [Leo]: This warning message is not useful.
|
||||
|
@ -1758,7 +1752,7 @@ namespace smt {
|
|||
}
|
||||
CTRACE("model_finder_bug", has_quantifiers(m_flat_q->get_expr()),
|
||||
tout << mk_pp(q, m) << "\n" << mk_pp(m_flat_q, m) << "\n";);
|
||||
SASSERT(!has_quantifiers(m_flat_q->get_expr()));
|
||||
SASSERT(m.is_lambda_def(q) || !has_quantifiers(m_flat_q->get_expr()));
|
||||
}
|
||||
|
||||
~quantifier_info() {
|
||||
|
@ -1787,7 +1781,6 @@ namespace smt {
|
|||
|
||||
ptr_vector<cond_macro> const& macros() const { return m_cond_macros; }
|
||||
|
||||
|
||||
void set_the_one(func_decl * m) {
|
||||
m_the_one = m;
|
||||
}
|
||||
|
@ -1880,7 +1873,7 @@ namespace smt {
|
|||
*/
|
||||
class quantifier_analyzer {
|
||||
model_finder& m_mf;
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
macro_util m_mutil;
|
||||
array_util m_array_util;
|
||||
arith_util m_arith_util;
|
||||
|
@ -1909,7 +1902,7 @@ namespace smt {
|
|||
|
||||
bool is_var_plus_ground(expr * n, var * & v, expr_ref & t) {
|
||||
bool inv;
|
||||
TRACE("is_var_plus_ground", tout << mk_pp(n, m_manager) << "\n";
|
||||
TRACE("is_var_plus_ground", tout << mk_pp(n, m) << "\n";
|
||||
tout << "is_var_plus_ground: " << is_var_plus_ground(n, inv, v, t) << "\n";
|
||||
tout << "inv: " << inv << "\n";);
|
||||
return is_var_plus_ground(n, inv, v, t) && !inv;
|
||||
|
@ -1953,7 +1946,7 @@ namespace smt {
|
|||
|
||||
bool is_var_and_ground(expr * lhs, expr * rhs, var * & v, expr_ref & t, bool & inv) {
|
||||
inv = false; // true if invert the sign
|
||||
TRACE("is_var_and_ground", tout << "is_var_and_ground: " << mk_ismt2_pp(lhs, m_manager) << " " << mk_ismt2_pp(rhs, m_manager) << "\n";);
|
||||
TRACE("is_var_and_ground", tout << "is_var_and_ground: " << mk_ismt2_pp(lhs, m) << " " << mk_ismt2_pp(rhs, m) << "\n";);
|
||||
if (is_var(lhs) && is_ground(rhs)) {
|
||||
v = to_var(lhs);
|
||||
t = rhs;
|
||||
|
@ -1967,7 +1960,7 @@ namespace smt {
|
|||
return true;
|
||||
}
|
||||
else {
|
||||
expr_ref tmp(m_manager);
|
||||
expr_ref tmp(m);
|
||||
if (is_var_plus_ground(lhs, inv, v, tmp) && is_ground(rhs)) {
|
||||
if (inv)
|
||||
mk_sub(tmp, rhs, t);
|
||||
|
@ -1994,7 +1987,7 @@ namespace smt {
|
|||
bool is_x_eq_t_atom(expr * n, var * & v, expr_ref & t) {
|
||||
if (!is_app(n))
|
||||
return false;
|
||||
if (m_manager.is_eq(n))
|
||||
if (m.is_eq(n))
|
||||
return is_var_and_ground(to_app(n)->get_arg(0), to_app(n)->get_arg(1), v, t);
|
||||
return false;
|
||||
}
|
||||
|
@ -2030,7 +2023,7 @@ namespace smt {
|
|||
}
|
||||
|
||||
bool is_x_eq_y_atom(expr * n, var * & v1, var * & v2) {
|
||||
return m_manager.is_eq(n) && is_var_and_var(to_app(n)->get_arg(0), to_app(n)->get_arg(1), v1, v2);
|
||||
return m.is_eq(n) && is_var_and_var(to_app(n)->get_arg(0), to_app(n)->get_arg(1), v1, v2);
|
||||
}
|
||||
|
||||
bool is_x_gle_y_atom(expr * n, var * & v1, var * & v2) {
|
||||
|
@ -2042,28 +2035,28 @@ namespace smt {
|
|||
return false;
|
||||
if (sign) {
|
||||
bool r = is_le_ge(atom) && is_var_and_ground(to_app(atom)->get_arg(0), to_app(atom)->get_arg(1), v, t);
|
||||
CTRACE("is_x_gle_t", r, tout << "is_x_gle_t: " << mk_ismt2_pp(atom, m_manager) << "\n--->\n"
|
||||
<< mk_ismt2_pp(v, m_manager) << " " << mk_ismt2_pp(t, m_manager) << "\n";
|
||||
CTRACE("is_x_gle_t", r, tout << "is_x_gle_t: " << mk_ismt2_pp(atom, m) << "\n--->\n"
|
||||
<< mk_ismt2_pp(v, m) << " " << mk_ismt2_pp(t, m) << "\n";
|
||||
tout << "sign: " << sign << "\n";);
|
||||
return r;
|
||||
}
|
||||
else {
|
||||
if (is_le_ge(atom)) {
|
||||
expr_ref tmp(m_manager);
|
||||
expr_ref tmp(m);
|
||||
bool le = is_le(atom);
|
||||
bool inv = false;
|
||||
if (is_var_and_ground(to_app(atom)->get_arg(0), to_app(atom)->get_arg(1), v, tmp, inv)) {
|
||||
if (inv)
|
||||
le = !le;
|
||||
sort * s = m_manager.get_sort(tmp);
|
||||
expr_ref one(m_manager);
|
||||
sort * s = m.get_sort(tmp);
|
||||
expr_ref one(m);
|
||||
one = mk_one(s);
|
||||
if (le)
|
||||
mk_add(tmp, one, t);
|
||||
else
|
||||
mk_sub(tmp, one, t);
|
||||
TRACE("is_x_gle_t", tout << "is_x_gle_t: " << mk_ismt2_pp(atom, m_manager) << "\n--->\n"
|
||||
<< mk_ismt2_pp(v, m_manager) << " " << mk_ismt2_pp(t, m_manager) << "\n";
|
||||
TRACE("is_x_gle_t", tout << "is_x_gle_t: " << mk_ismt2_pp(atom, m) << "\n--->\n"
|
||||
<< mk_ismt2_pp(v, m) << " " << mk_ismt2_pp(t, m) << "\n";
|
||||
tout << "sign: " << sign << "\n";);
|
||||
return true;
|
||||
}
|
||||
|
@ -2113,9 +2106,9 @@ namespace smt {
|
|||
}
|
||||
|
||||
var * v;
|
||||
expr_ref k(m_manager);
|
||||
expr_ref k(m);
|
||||
if (is_var_plus_ground(arg, v, k)) {
|
||||
insert_qinfo(alloc(f_var_plus_offset, m_manager, t->get_decl(), i, v->get_idx(), k.get()));
|
||||
insert_qinfo(alloc(f_var_plus_offset, m, t->get_decl(), i, v->get_idx(), k.get()));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -2157,7 +2150,7 @@ namespace smt {
|
|||
for (unsigned i = 1; i < num_args; i++) {
|
||||
expr * arg = t->get_arg(i);
|
||||
if (is_var(arg)) {
|
||||
insert_qinfo(alloc(select_var, m_manager, t, i, to_var(arg)->get_idx()));
|
||||
insert_qinfo(alloc(select_var, m, t, i, to_var(arg)->get_idx()));
|
||||
}
|
||||
else {
|
||||
SASSERT(is_ground(arg));
|
||||
|
@ -2174,7 +2167,7 @@ namespace smt {
|
|||
void process_app(app * t) {
|
||||
SASSERT(!is_ground(t));
|
||||
|
||||
if (t->get_family_id() != m_manager.get_basic_family_id()) {
|
||||
if (t->get_family_id() != m.get_basic_family_id()) {
|
||||
m_info->m_ng_decls.insert(t->get_decl());
|
||||
}
|
||||
|
||||
|
@ -2191,7 +2184,7 @@ namespace smt {
|
|||
expr * curr = m_ttodo.back();
|
||||
m_ttodo.pop_back();
|
||||
|
||||
if (m_manager.is_bool(curr)) {
|
||||
if (m.is_bool(curr)) {
|
||||
// formula nested in a term.
|
||||
visit_formula(curr, POS);
|
||||
visit_formula(curr, NEG);
|
||||
|
@ -2212,30 +2205,30 @@ namespace smt {
|
|||
}
|
||||
|
||||
void process_literal(expr * atom, bool sign) {
|
||||
CTRACE("model_finder_bug", is_ground(atom), tout << mk_pp(atom, m_manager) << "\n";);
|
||||
CTRACE("model_finder_bug", is_ground(atom), tout << mk_pp(atom, m) << "\n";);
|
||||
SASSERT(!is_ground(atom));
|
||||
SASSERT(m_manager.is_bool(atom));
|
||||
SASSERT(m.is_bool(atom));
|
||||
|
||||
if (is_var(atom)) {
|
||||
if (sign) {
|
||||
// atom (not X) can be viewed as X != true
|
||||
insert_qinfo(alloc(x_neq_t, m_manager, to_var(atom)->get_idx(), m_manager.mk_true()));
|
||||
insert_qinfo(alloc(x_neq_t, m, to_var(atom)->get_idx(), m.mk_true()));
|
||||
}
|
||||
else {
|
||||
// atom X can be viewed as X != false
|
||||
insert_qinfo(alloc(x_neq_t, m_manager, to_var(atom)->get_idx(), m_manager.mk_false()));
|
||||
insert_qinfo(alloc(x_neq_t, m, to_var(atom)->get_idx(), m.mk_false()));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (is_app(atom)) {
|
||||
var * v, * v1, * v2;
|
||||
expr_ref t(m_manager);
|
||||
expr_ref t(m);
|
||||
if (is_x_eq_t_atom(atom, v, t)) {
|
||||
if (sign)
|
||||
insert_qinfo(alloc(x_neq_t, m_manager, v->get_idx(), t));
|
||||
insert_qinfo(alloc(x_neq_t, m, v->get_idx(), t));
|
||||
else
|
||||
insert_qinfo(alloc(x_eq_t, m_manager, v->get_idx(), t));
|
||||
insert_qinfo(alloc(x_eq_t, m, v->get_idx(), t));
|
||||
}
|
||||
else if (is_x_eq_y_atom(atom, v1, v2)) {
|
||||
if (sign)
|
||||
|
@ -2252,7 +2245,7 @@ namespace smt {
|
|||
insert_qinfo(alloc(x_leq_y, v1->get_idx(), v2->get_idx()));
|
||||
}
|
||||
else if (is_x_gle_t_atom(atom, sign, v, t)) {
|
||||
insert_qinfo(alloc(x_gle_t, m_manager, v->get_idx(), t));
|
||||
insert_qinfo(alloc(x_gle_t, m, v->get_idx(), t));
|
||||
}
|
||||
else {
|
||||
process_app(to_app(atom));
|
||||
|
@ -2299,7 +2292,7 @@ namespace smt {
|
|||
polarity pol = e.second;
|
||||
m_ftodo.pop_back();
|
||||
if (is_app(curr)) {
|
||||
if (to_app(curr)->get_family_id() == m_manager.get_basic_family_id() && m_manager.is_bool(curr)) {
|
||||
if (to_app(curr)->get_family_id() == m.get_basic_family_id() && m.is_bool(curr)) {
|
||||
switch (static_cast<basic_op_kind>(to_app(curr)->get_decl_kind())) {
|
||||
case OP_IMPLIES:
|
||||
case OP_XOR:
|
||||
|
@ -2316,7 +2309,7 @@ namespace smt {
|
|||
process_ite(to_app(curr), pol);
|
||||
break;
|
||||
case OP_EQ:
|
||||
if (m_manager.is_bool(to_app(curr)->get_arg(0))) {
|
||||
if (m.is_bool(to_app(curr)->get_arg(0))) {
|
||||
process_iff(to_app(curr));
|
||||
}
|
||||
else {
|
||||
|
@ -2333,7 +2326,7 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
else if (is_var(curr)) {
|
||||
SASSERT(m_manager.is_bool(curr));
|
||||
SASSERT(m.is_bool(curr));
|
||||
process_literal(curr, pol);
|
||||
}
|
||||
else {
|
||||
|
@ -2344,32 +2337,32 @@ namespace smt {
|
|||
}
|
||||
|
||||
void process_formula(expr * n) {
|
||||
SASSERT(m_manager.is_bool(n));
|
||||
SASSERT(m.is_bool(n));
|
||||
visit_formula(n, POS);
|
||||
}
|
||||
|
||||
void process_clause(expr * cls) {
|
||||
SASSERT(is_clause(m_manager, cls));
|
||||
unsigned num_lits = get_clause_num_literals(m_manager, cls);
|
||||
SASSERT(is_clause(m, cls));
|
||||
unsigned num_lits = get_clause_num_literals(m, cls);
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
expr * lit = get_clause_literal(m_manager, cls, i);
|
||||
SASSERT(is_literal(m_manager, lit));
|
||||
expr * lit = get_clause_literal(m, cls, i);
|
||||
SASSERT(is_literal(m, lit));
|
||||
expr * atom;
|
||||
bool sign;
|
||||
get_literal_atom_sign(m_manager, lit, atom, sign);
|
||||
get_literal_atom_sign(m, lit, atom, sign);
|
||||
if (!is_ground(atom))
|
||||
process_literal(atom, sign);
|
||||
}
|
||||
}
|
||||
|
||||
void collect_macro_candidates(quantifier * q) {
|
||||
macro_util::macro_candidates candidates(m_manager);
|
||||
macro_util::macro_candidates candidates(m);
|
||||
m_mutil.collect_macro_candidates(q, candidates);
|
||||
unsigned num_candidates = candidates.size();
|
||||
for (unsigned i = 0; i < num_candidates; i++) {
|
||||
cond_macro * m = alloc(cond_macro, m_manager, candidates.get_f(i), candidates.get_def(i), candidates.get_cond(i),
|
||||
cond_macro * mc = alloc(cond_macro, m, candidates.get_f(i), candidates.get_def(i), candidates.get_cond(i),
|
||||
candidates.ineq(i), candidates.satisfy_atom(i), candidates.hint(i), q->get_weight());
|
||||
m_info->insert_macro(m);
|
||||
m_info->insert_macro(mc);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2377,7 +2370,7 @@ namespace smt {
|
|||
public:
|
||||
quantifier_analyzer(model_finder& mf, ast_manager & m):
|
||||
m_mf(mf),
|
||||
m_manager(m),
|
||||
m(m),
|
||||
m_mutil(m),
|
||||
m_array_util(m),
|
||||
m_arith_util(m),
|
||||
|
@ -2389,13 +2382,14 @@ namespace smt {
|
|||
void operator()(quantifier_info * d) {
|
||||
m_info = d;
|
||||
quantifier * q = d->get_flat_q();
|
||||
if (m.is_lambda_def(q)) return;
|
||||
expr * e = q->get_expr();
|
||||
SASSERT(!has_quantifiers(e));
|
||||
reset_cache();
|
||||
SASSERT(m_ttodo.empty());
|
||||
SASSERT(m_ftodo.empty());
|
||||
|
||||
if (is_clause(m_manager, e)) {
|
||||
if (is_clause(m, e)) {
|
||||
process_clause(e);
|
||||
}
|
||||
else {
|
||||
|
@ -2419,7 +2413,7 @@ namespace smt {
|
|||
*/
|
||||
class base_macro_solver {
|
||||
protected:
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
obj_map<quantifier, quantifier_info *> const & m_q2info;
|
||||
proto_model * m_model;
|
||||
|
||||
|
@ -2434,18 +2428,18 @@ namespace smt {
|
|||
SASSERT(f_else != 0);
|
||||
func_interp * fi = m_model->get_func_interp(f);
|
||||
if (fi == nullptr) {
|
||||
fi = alloc(func_interp, m_manager, f->get_arity());
|
||||
fi = alloc(func_interp, m, f->get_arity());
|
||||
m_model->register_decl(f, fi);
|
||||
}
|
||||
fi->set_else(f_else);
|
||||
TRACE("model_finder", tout << f->get_name() << " " << mk_pp(f_else, m_manager) << "\n";);
|
||||
TRACE("model_finder", tout << f->get_name() << " " << mk_pp(f_else, m) << "\n";);
|
||||
}
|
||||
|
||||
virtual bool process(ptr_vector<quantifier> const & qs, ptr_vector<quantifier> & new_qs, ptr_vector<quantifier> & residue) = 0;
|
||||
|
||||
public:
|
||||
base_macro_solver(ast_manager & m, obj_map<quantifier, quantifier_info *> const & q2i):
|
||||
m_manager(m),
|
||||
m(m),
|
||||
m_q2info(q2i),
|
||||
m_model(nullptr) {
|
||||
}
|
||||
|
@ -2647,7 +2641,7 @@ namespace smt {
|
|||
|
||||
bool is_candidate(quantifier * q) const {
|
||||
quantifier_info * qi = get_qinfo(q);
|
||||
for (cond_macro * m : qi->macros()) {
|
||||
for (cond_macro* m : qi->macros()) {
|
||||
if (m->satisfy_atom() && !m_forbidden.contains(m->get_f()))
|
||||
return true;
|
||||
}
|
||||
|
@ -2708,7 +2702,7 @@ namespace smt {
|
|||
|
||||
void display_qcandidates(std::ostream & out, ptr_vector<quantifier> const & qcandidates) const {
|
||||
for (quantifier * q : qcandidates) {
|
||||
out << q->get_qid() << " ->\n" << mk_pp(q, m_manager) << "\n";
|
||||
out << q->get_qid() << " ->\n" << mk_pp(q, m) << "\n";
|
||||
quantifier_info * qi = get_qinfo(q);
|
||||
qi->display(out);
|
||||
out << "------\n";
|
||||
|
@ -2724,7 +2718,7 @@ namespace smt {
|
|||
func_decl * f = kv.get_key1();
|
||||
expr * def = kv.get_key2();
|
||||
quantifier_set * s = kv.get_value();
|
||||
out << f->get_name() << " " << mk_pp(def, m_manager) << " ->\n"; display_quantifier_set(out, s);
|
||||
out << f->get_name() << " " << mk_pp(def, m) << " ->\n"; display_quantifier_set(out, s);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2846,7 +2840,7 @@ namespace smt {
|
|||
|
||||
m_satisfied.push_scope();
|
||||
m_residue.push_scope();
|
||||
TRACE("model_finder", tout << f->get_name() << " " << mk_pp(def, m_manager) << "\n";);
|
||||
TRACE("model_finder", tout << f->get_name() << " " << mk_pp(def, m) << "\n";);
|
||||
m_fs.insert(f, def);
|
||||
|
||||
if (update_satisfied_residue(f, def)) {
|
||||
|
@ -3023,7 +3017,7 @@ namespace smt {
|
|||
qi_params const * m_qi_params;
|
||||
|
||||
bool add_macro(func_decl * f, expr * f_else) {
|
||||
TRACE("model_finder", tout << "trying to add macro for " << f->get_name() << "\n" << mk_pp(f_else, m_manager) << "\n";);
|
||||
TRACE("model_finder", tout << "trying to add macro for " << f->get_name() << "\n" << mk_pp(f_else, m) << "\n";);
|
||||
func_decl_set * s = m_dependencies.mk_func_decl_set();
|
||||
m_dependencies.collect_ng_func_decls(f_else, s);
|
||||
if (!m_dependencies.insert(f, s)) {
|
||||
|
@ -3092,23 +3086,23 @@ namespace smt {
|
|||
}
|
||||
|
||||
void process(func_decl * f, ptr_vector<quantifier> const & qs, obj_hashtable<quantifier> & removed) {
|
||||
expr_ref fi_else(m_manager);
|
||||
expr_ref fi_else(m);
|
||||
ptr_buffer<quantifier> to_remove;
|
||||
for (quantifier * q : qs) {
|
||||
if (removed.contains(q))
|
||||
continue;
|
||||
cond_macro * m = get_macro_for(f, q);
|
||||
if (!m)
|
||||
cond_macro * cm = get_macro_for(f, q);
|
||||
if (!cm)
|
||||
continue;
|
||||
SASSERT(!m->is_hint());
|
||||
if (m->is_unconditional())
|
||||
SASSERT(!cm->is_hint());
|
||||
if (cm->is_unconditional())
|
||||
return; // f is part of a full macro... ignoring it.
|
||||
to_remove.push_back(q);
|
||||
if (fi_else.get() == nullptr) {
|
||||
fi_else = m->get_def();
|
||||
fi_else = cm->get_def();
|
||||
}
|
||||
else {
|
||||
fi_else = m_manager.mk_ite(m->get_cond(), m->get_def(), fi_else);
|
||||
fi_else = m.mk_ite(cm->get_cond(), cm->get_def(), fi_else);
|
||||
}
|
||||
}
|
||||
if (fi_else.get() != nullptr && add_macro(f, fi_else)) {
|
||||
|
@ -3166,7 +3160,7 @@ namespace smt {
|
|||
// -----------------------------------
|
||||
|
||||
model_finder::model_finder(ast_manager & m):
|
||||
m_manager(m),
|
||||
m(m),
|
||||
m_context(nullptr),
|
||||
m_analyzer(alloc(quantifier_analyzer, *this, m)),
|
||||
m_auf_solver(alloc(auf_solver, m)),
|
||||
|
@ -3206,8 +3200,8 @@ namespace smt {
|
|||
}
|
||||
|
||||
void model_finder::register_quantifier(quantifier * q) {
|
||||
TRACE("model_finder", tout << "registering:\n" << mk_pp(q, m_manager) << "\n";);
|
||||
quantifier_info * new_info = alloc(quantifier_info, *this, m_manager, q);
|
||||
TRACE("model_finder", tout << "registering:\n" << mk_pp(q, m) << "\n";);
|
||||
quantifier_info * new_info = alloc(quantifier_info, *this, m, q);
|
||||
m_q2info.insert(q, new_info);
|
||||
m_quantifiers.push_back(q);
|
||||
m_analyzer->operator()(new_info);
|
||||
|
@ -3261,9 +3255,9 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
|
||||
void model_finder::process_auf(ptr_vector<quantifier> const & qs, proto_model * m) {
|
||||
void model_finder::process_auf(ptr_vector<quantifier> const & qs, proto_model * mdl) {
|
||||
m_auf_solver->reset();
|
||||
m_auf_solver->set_model(m);
|
||||
m_auf_solver->set_model(mdl);
|
||||
|
||||
for (quantifier * q : qs) {
|
||||
quantifier_info * qi = get_quantifier_info(q);
|
||||
|
@ -3280,7 +3274,7 @@ namespace smt {
|
|||
for (quantifier * q : qs) {
|
||||
quantifier_info * qi = get_quantifier_info(q);
|
||||
quantifier * fq = qi->get_flat_q();
|
||||
tout << "#" << fq->get_id() << " ->\n" << mk_pp(fq, m_manager) << "\n";
|
||||
tout << "#" << fq->get_id() << " ->\n" << mk_pp(fq, m) << "\n";
|
||||
}
|
||||
m_auf_solver->display_nodes(tout););
|
||||
}
|
||||
|
@ -3310,11 +3304,8 @@ namespace smt {
|
|||
\brief Clean leftovers from previous invocations to fix_model.
|
||||
*/
|
||||
void model_finder::cleanup_quantifier_infos(ptr_vector<quantifier> const & qs) {
|
||||
ptr_vector<quantifier>::const_iterator it = qs.begin();
|
||||
ptr_vector<quantifier>::const_iterator end = qs.end();
|
||||
for (; it != end; ++it) {
|
||||
quantifier_info * qi = get_quantifier_info(*it);
|
||||
qi->reset_the_one();
|
||||
for (quantifier* q : qs) {
|
||||
get_quantifier_info(q)->reset_the_one();
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3356,7 +3347,7 @@ namespace smt {
|
|||
quantifier * flat_q = get_flat_quantifier(q);
|
||||
SASSERT(flat_q->get_num_decls() >= q->get_num_decls());
|
||||
instantiation_set const * r = m_auf_solver->get_uvar_inst_set(flat_q, flat_q->get_num_decls() - q->get_num_decls() + i);
|
||||
TRACE("model_finder", tout << "q: #" << q->get_id() << "\n" << mk_pp(q,m_manager) << "\nflat_q: " << mk_pp(flat_q, m_manager)
|
||||
TRACE("model_finder", tout << "q: #" << q->get_id() << "\n" << mk_pp(q,m) << "\nflat_q: " << mk_pp(flat_q, m)
|
||||
<< "\ni: " << i << " " << flat_q->get_num_decls() - q->get_num_decls() + i << "\n";);
|
||||
if (r != nullptr)
|
||||
return r;
|
||||
|
@ -3365,7 +3356,6 @@ namespace smt {
|
|||
quantifier_info * qinfo = get_quantifier_info(q);
|
||||
SASSERT(qinfo);
|
||||
SASSERT(qinfo->get_the_one() != 0);
|
||||
|
||||
return qinfo->get_macro_based_inst_set(i, m_context, *(m_auf_solver.get()));
|
||||
}
|
||||
|
||||
|
@ -3415,15 +3405,13 @@ namespace smt {
|
|||
if (inv.empty())
|
||||
continue; // nothing to do
|
||||
ptr_buffer<expr> eqs;
|
||||
obj_map<expr, expr *>::iterator it = inv.begin();
|
||||
obj_map<expr, expr *>::iterator end = inv.end();
|
||||
for (; it != end; ++it) {
|
||||
expr * val = (*it).m_key;
|
||||
eqs.push_back(m_manager.mk_eq(sk, val));
|
||||
for (auto const& kv : inv) {
|
||||
expr * val = kv.m_key;
|
||||
eqs.push_back(m.mk_eq(sk, val));
|
||||
}
|
||||
expr_ref new_cnstr(m_manager);
|
||||
new_cnstr = m_manager.mk_or(eqs.size(), eqs.c_ptr());
|
||||
TRACE("model_finder", tout << "assert_restriction:\n" << mk_pp(new_cnstr, m_manager) << "\n";);
|
||||
expr_ref new_cnstr(m);
|
||||
new_cnstr = m.mk_or(eqs.size(), eqs.c_ptr());
|
||||
TRACE("model_finder", tout << "assert_restriction:\n" << mk_pp(new_cnstr, m) << "\n";);
|
||||
aux_ctx->assert_expr(new_cnstr);
|
||||
asserted_something = true;
|
||||
}
|
||||
|
@ -3435,7 +3423,7 @@ namespace smt {
|
|||
if (sz > 0) {
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
expr * c = m_new_constraints.get(i);
|
||||
TRACE("model_finder_bug_detail", tout << "asserting new constraint: " << mk_pp(c, m_manager) << "\n";);
|
||||
TRACE("model_finder_bug_detail", tout << "asserting new constraint: " << mk_pp(c, m) << "\n";);
|
||||
m_context->internalize(c, true);
|
||||
literal l(m_context->get_literal(c));
|
||||
m_context->mark_as_relevant(l);
|
||||
|
|
|
@ -74,7 +74,7 @@ namespace smt {
|
|||
typedef mf::non_auf_macro_solver non_auf_macro_solver;
|
||||
typedef mf::instantiation_set instantiation_set;
|
||||
|
||||
ast_manager & m_manager;
|
||||
ast_manager & m;
|
||||
context * m_context;
|
||||
scoped_ptr<quantifier_analyzer> m_analyzer;
|
||||
scoped_ptr<auf_solver> m_auf_solver;
|
||||
|
|
|
@ -24,6 +24,7 @@ Revision History:
|
|||
#include "smt/smt_context.h"
|
||||
#include "smt/smt_model_generator.h"
|
||||
#include "smt/proto_model/proto_model.h"
|
||||
#include "model/model_v2_pp.h"
|
||||
|
||||
namespace smt {
|
||||
|
||||
|
@ -51,11 +52,9 @@ namespace smt {
|
|||
SASSERT(!m_model);
|
||||
// PARAM-TODO smt_params ---> params_ref
|
||||
m_model = alloc(proto_model, m_manager); // , m_context->get_fparams());
|
||||
ptr_vector<theory>::const_iterator it = m_context->begin_theories();
|
||||
ptr_vector<theory>::const_iterator end = m_context->end_theories();
|
||||
for (; it != end; ++it) {
|
||||
TRACE("model", tout << "init_model for theory: " << (*it)->get_name() << "\n";);
|
||||
(*it)->init_model(*this);
|
||||
for (theory* th : m_context->theories()) {
|
||||
TRACE("model_generator_bug", tout << "init_model for theory: " << th->get_name() << "\n";);
|
||||
th->init_model(*this);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -82,10 +81,7 @@ namespace smt {
|
|||
*/
|
||||
void model_generator::mk_value_procs(obj_map<enode, model_value_proc *> & root2proc, ptr_vector<enode> & roots,
|
||||
ptr_vector<model_value_proc> & procs) {
|
||||
ptr_vector<enode>::const_iterator it = m_context->begin_enodes();
|
||||
ptr_vector<enode>::const_iterator end = m_context->end_enodes();
|
||||
for (; it != end; ++it) {
|
||||
enode * r = *it;
|
||||
for (enode * r : m_context->enodes()) {
|
||||
if (r == r->get_root() && m_context->is_relevant(r)) {
|
||||
roots.push_back(r);
|
||||
sort * s = m_manager.get_sort(r->get_owner());
|
||||
|
@ -201,10 +197,7 @@ namespace smt {
|
|||
SASSERT(proc);
|
||||
buffer<model_value_dependency> dependencies;
|
||||
proc->get_dependencies(dependencies);
|
||||
buffer<model_value_dependency>::const_iterator it = dependencies.begin();
|
||||
buffer<model_value_dependency>::const_iterator end = dependencies.end();
|
||||
for (; it != end; ++it) {
|
||||
model_value_dependency const & dep = *it;
|
||||
for (model_value_dependency const& dep : dependencies) {
|
||||
visit_child(dep, colors, todo, visited);
|
||||
TRACE("mg_top_sort", tout << "#" << n->get_owner_id() << " -> ";
|
||||
if (dep.is_fresh_value()) tout << "fresh!" << dep.get_value()->get_idx();
|
||||
|
@ -308,10 +301,7 @@ namespace smt {
|
|||
mk_value_procs(root2proc, roots, procs);
|
||||
top_sort_sources(roots, root2proc, sources);
|
||||
TRACE("sorted_sources",
|
||||
svector<source>::const_iterator it = sources.begin();
|
||||
svector<source>::const_iterator end = sources.end();
|
||||
for (; it != end; ++it) {
|
||||
source const & curr = *it;
|
||||
for (source const& curr : sources) {
|
||||
if (curr.is_fresh_value()) {
|
||||
tout << "fresh!" << curr.get_value()->get_idx() << " " << mk_pp(curr.get_value()->get_sort(), m_manager) << "\n";
|
||||
}
|
||||
|
@ -326,11 +316,7 @@ namespace smt {
|
|||
tout << " is_fresh: " << proc->is_fresh() << "\n";
|
||||
}
|
||||
});
|
||||
svector<source>::const_iterator it = sources.begin();
|
||||
svector<source>::const_iterator end = sources.end();
|
||||
for (; it != end; ++it) {
|
||||
source const & curr = *it;
|
||||
|
||||
for (source const& curr : sources) {
|
||||
if (curr.is_fresh_value()) {
|
||||
sort * s = curr.get_value()->get_sort();
|
||||
TRACE("model_fresh_bug", tout << "mk fresh!" << curr.get_value()->get_idx() << " : " << mk_pp(s, m_manager) << "\n";);
|
||||
|
@ -349,10 +335,7 @@ namespace smt {
|
|||
VERIFY(root2proc.find(n, proc));
|
||||
SASSERT(proc);
|
||||
proc->get_dependencies(dependencies);
|
||||
buffer<model_value_dependency>::const_iterator it2 = dependencies.begin();
|
||||
buffer<model_value_dependency>::const_iterator end2 = dependencies.end();
|
||||
for (; it2 != end2; ++it2) {
|
||||
model_value_dependency const & d = *it2;
|
||||
for (model_value_dependency const& d : dependencies) {
|
||||
if (d.is_fresh_value()) {
|
||||
CTRACE("mg_top_sort", !d.get_value()->get_value(),
|
||||
tout << "#" << n->get_owner_id() << " -> ";
|
||||
|
@ -381,10 +364,7 @@ namespace smt {
|
|||
m_extra_fresh_values.reset();
|
||||
|
||||
// send model
|
||||
ptr_vector<enode>::const_iterator it3 = m_context->begin_enodes();
|
||||
ptr_vector<enode>::const_iterator end3 = m_context->end_enodes();
|
||||
for (; it3 != end3; ++it3) {
|
||||
enode * n = *it3;
|
||||
for (enode * n : m_context->enodes()) {
|
||||
if (is_uninterp_const(n->get_owner()) && m_context->is_relevant(n)) {
|
||||
func_decl * d = n->get_owner()->get_decl();
|
||||
TRACE("mg_top_sort", tout << d->get_name() << " " << (m_hidden_ufs.contains(d)?"hidden":"visible") << "\n";);
|
||||
|
@ -484,17 +464,12 @@ namespace smt {
|
|||
}
|
||||
|
||||
void model_generator::finalize_theory_models() {
|
||||
ptr_vector<theory>::const_iterator it = m_context->begin_theories();
|
||||
ptr_vector<theory>::const_iterator end = m_context->end_theories();
|
||||
for (; it != end; ++it)
|
||||
(*it)->finalize_model(*this);
|
||||
for (theory* th : m_context->theories())
|
||||
th->finalize_model(*this);
|
||||
}
|
||||
|
||||
void model_generator::register_existing_model_values() {
|
||||
ptr_vector<enode>::const_iterator it = m_context->begin_enodes();
|
||||
ptr_vector<enode>::const_iterator end = m_context->end_enodes();
|
||||
for (; it != end; ++it) {
|
||||
enode * r = *it;
|
||||
for (enode * r : m_context->enodes()) {
|
||||
if (r == r->get_root() && m_context->is_relevant(r)) {
|
||||
expr * n = r->get_owner();
|
||||
if (m_manager.is_model_value(n)) {
|
||||
|
@ -531,6 +506,7 @@ namespace smt {
|
|||
mk_func_interps();
|
||||
finalize_theory_models();
|
||||
register_macros();
|
||||
TRACE("model", model_v2_pp(tout, *m_model, true););
|
||||
return m_model;
|
||||
}
|
||||
|
||||
|
|
|
@ -191,6 +191,7 @@ namespace smt {
|
|||
bool add_instance(quantifier * q, app * pat,
|
||||
unsigned num_bindings,
|
||||
enode * const * bindings,
|
||||
expr* def,
|
||||
unsigned max_generation,
|
||||
unsigned min_top_generation,
|
||||
unsigned max_top_generation,
|
||||
|
@ -200,7 +201,7 @@ namespace smt {
|
|||
return false;
|
||||
}
|
||||
get_stat(q)->update_max_generation(max_generation);
|
||||
fingerprint * f = m_context.add_fingerprint(q, q->get_id(), num_bindings, bindings);
|
||||
fingerprint * f = m_context.add_fingerprint(q, q->get_id(), num_bindings, bindings, def);
|
||||
if (f) {
|
||||
if (has_trace_stream()) {
|
||||
std::ostream & out = trace_stream();
|
||||
|
@ -399,16 +400,17 @@ namespace smt {
|
|||
bool quantifier_manager::add_instance(quantifier * q, app * pat,
|
||||
unsigned num_bindings,
|
||||
enode * const * bindings,
|
||||
expr* def,
|
||||
unsigned max_generation,
|
||||
unsigned min_top_generation,
|
||||
unsigned max_top_generation,
|
||||
vector<std::tuple<enode *, enode *>> & used_enodes) {
|
||||
return m_imp->add_instance(q, pat, num_bindings, bindings, max_generation, min_top_generation, max_generation, used_enodes);
|
||||
return m_imp->add_instance(q, pat, num_bindings, bindings, def, max_generation, min_top_generation, max_generation, used_enodes);
|
||||
}
|
||||
|
||||
bool quantifier_manager::add_instance(quantifier * q, unsigned num_bindings, enode * const * bindings, unsigned generation) {
|
||||
bool quantifier_manager::add_instance(quantifier * q, unsigned num_bindings, enode * const * bindings, expr* def, unsigned generation) {
|
||||
vector<std::tuple<enode *, enode *>> tmp;
|
||||
return add_instance(q, nullptr, num_bindings, bindings, generation, generation, generation, tmp);
|
||||
return add_instance(q, nullptr, num_bindings, bindings, def, generation, generation, generation, tmp);
|
||||
}
|
||||
|
||||
void quantifier_manager::init_search_eh() {
|
||||
|
|
|
@ -55,11 +55,12 @@ namespace smt {
|
|||
bool add_instance(quantifier * q, app * pat,
|
||||
unsigned num_bindings,
|
||||
enode * const * bindings,
|
||||
expr* def,
|
||||
unsigned max_generation,
|
||||
unsigned min_top_generation,
|
||||
unsigned max_top_generation,
|
||||
vector<std::tuple<enode *, enode *>> & used_enodes /*gives the equalities used for the pattern match, see mam.cpp for more info*/);
|
||||
bool add_instance(quantifier * q, unsigned num_bindings, enode * const * bindings, unsigned generation = 0);
|
||||
bool add_instance(quantifier * q, unsigned num_bindings, enode * const * bindings, expr* def, unsigned generation = 0);
|
||||
|
||||
void init_search_eh();
|
||||
void assign_eh(quantifier * q);
|
||||
|
@ -92,6 +93,8 @@ namespace smt {
|
|||
|
||||
ptr_vector<quantifier>::const_iterator begin_quantifiers() const;
|
||||
ptr_vector<quantifier>::const_iterator end_quantifiers() const;
|
||||
ptr_vector<quantifier>::const_iterator begin() const { return begin_quantifiers(); }
|
||||
ptr_vector<quantifier>::const_iterator end() const { return end_quantifiers(); }
|
||||
unsigned num_quantifiers() const;
|
||||
|
||||
};
|
||||
|
|
|
@ -52,10 +52,7 @@ namespace smt {
|
|||
bool quick_checker::collector::check_arg(enode * n, func_decl * f, unsigned i) {
|
||||
if (!f || !m_conservative)
|
||||
return true;
|
||||
enode_vector::const_iterator it = m_context.begin_enodes_of(f);
|
||||
enode_vector::const_iterator end = m_context.end_enodes_of(f);
|
||||
for (; it != end; ++it) {
|
||||
enode * curr = *it;
|
||||
for (enode * curr : m_context.enodes_of(f)) {
|
||||
if (m_context.is_relevant(curr) && curr->is_cgr() && i < curr->get_num_args() && curr->get_arg(i)->get_root() == n->get_root())
|
||||
return true;
|
||||
}
|
||||
|
@ -77,10 +74,7 @@ namespace smt {
|
|||
if (s.empty())
|
||||
continue;
|
||||
ns.reset();
|
||||
enode_vector::const_iterator it = m_context.begin_enodes_of(f);
|
||||
enode_vector::const_iterator end = m_context.end_enodes_of(f);
|
||||
for (; it != end; ++it) {
|
||||
enode * curr = *it;
|
||||
for (enode * curr : m_context.enodes_of(f)) {
|
||||
if (m_context.is_relevant(curr) && curr->is_cgr() && check_arg(curr, p, i) && j < curr->get_num_args()) {
|
||||
enode * arg = curr->get_arg(j)->get_root();
|
||||
// intersection
|
||||
|
@ -94,10 +88,7 @@ namespace smt {
|
|||
else {
|
||||
m_already_found[idx] = true;
|
||||
enode_set & s = m_candidates[idx];
|
||||
enode_vector::const_iterator it = m_context.begin_enodes_of(f);
|
||||
enode_vector::const_iterator end = m_context.end_enodes_of(f);
|
||||
for (; it != end; ++it) {
|
||||
enode * curr = *it;
|
||||
for (enode * curr : m_context.enodes_of(f)) {
|
||||
if (m_context.is_relevant(curr) && curr->is_cgr() && check_arg(curr, p, i) && j < curr->get_num_args()) {
|
||||
enode * arg = curr->get_arg(j)->get_root();
|
||||
s.insert(arg);
|
||||
|
@ -134,10 +125,7 @@ namespace smt {
|
|||
enode_vector & v = candidates[i];
|
||||
v.reset();
|
||||
enode_set & s = m_candidates[i];
|
||||
enode_set::iterator it = s.begin();
|
||||
enode_set::iterator end = s.end();
|
||||
for (; it != end; ++it) {
|
||||
enode * curr = *it;
|
||||
for (enode * curr : s) {
|
||||
v.push_back(curr);
|
||||
}
|
||||
}
|
||||
|
@ -146,10 +134,8 @@ namespace smt {
|
|||
for (unsigned i = 0; i < m_num_vars; i++) {
|
||||
tout << "var " << i << ":";
|
||||
enode_vector & v = candidates[i];
|
||||
enode_vector::iterator it = v.begin();
|
||||
enode_vector::iterator end = v.end();
|
||||
for (; it != end; ++it)
|
||||
tout << " #" << (*it)->get_owner_id();
|
||||
for (enode * n : v)
|
||||
tout << " #" << n->get_owner_id();
|
||||
tout << "\n";
|
||||
});
|
||||
}
|
||||
|
@ -227,10 +213,8 @@ namespace smt {
|
|||
tout << "candidates:\n";
|
||||
for (unsigned i = 0; i < m_num_bindings; i++) {
|
||||
enode_vector & v = m_candidate_vectors[i];
|
||||
enode_vector::iterator it = v.begin();
|
||||
enode_vector::iterator end = v.end();
|
||||
for (; it != end; ++it)
|
||||
tout << "#" << (*it)->get_owner_id() << " ";
|
||||
for (enode * n : v)
|
||||
tout << "#" << n->get_owner_id() << " ";
|
||||
tout << "\n";
|
||||
});
|
||||
bool result = false;
|
||||
|
@ -252,7 +236,8 @@ namespace smt {
|
|||
TRACE("quick_checker_sizes", tout << "found new candidate\n";
|
||||
for (unsigned i = 0; i < m_num_bindings; i++) tout << "#" << m_bindings[i]->get_owner_id() << " "; tout << "\n";);
|
||||
unsigned max_generation = get_max_generation(m_num_bindings, m_bindings.c_ptr());
|
||||
if (m_context.add_instance(q, nullptr /* no pattern was used */, m_num_bindings, m_bindings.c_ptr(), max_generation,
|
||||
if (m_context.add_instance(q, nullptr /* no pattern was used */, m_num_bindings, m_bindings.c_ptr(), nullptr,
|
||||
max_generation,
|
||||
0, // min_top_generation is only available for instances created by the MAM
|
||||
0, // max_top_generation is only available for instances created by the MAM
|
||||
empty_used_enodes))
|
||||
|
|
|
@ -222,7 +222,7 @@ namespace smt {
|
|||
void setup::setup_QF_BVRE() {
|
||||
setup_QF_BV();
|
||||
setup_QF_LIA();
|
||||
m_context.register_plugin(alloc(theory_seq, m_manager));
|
||||
m_context.register_plugin(alloc(theory_seq, m_manager, m_params));
|
||||
}
|
||||
|
||||
void setup::setup_QF_UF(static_features const & st) {
|
||||
|
@ -332,7 +332,7 @@ namespace smt {
|
|||
m_params.m_arith_propagate_eqs = false;
|
||||
m_params.m_arith_small_lemma_size = 30;
|
||||
m_params.m_nnf_cnf = false;
|
||||
setup_i_arith();
|
||||
setup_lra_arith();
|
||||
}
|
||||
|
||||
void setup::setup_QF_IDL(static_features & st) {
|
||||
|
@ -404,7 +404,7 @@ namespace smt {
|
|||
m_params.m_restart_strategy = RS_GEOMETRIC;
|
||||
m_params.m_restart_factor = 1.5;
|
||||
m_params.m_restart_adaptive = false;
|
||||
setup_i_arith();
|
||||
setup_lra_arith();
|
||||
}
|
||||
|
||||
void setup::setup_QF_UFIDL(static_features & st) {
|
||||
|
@ -454,7 +454,7 @@ namespace smt {
|
|||
m_params.m_arith_propagate_eqs = false;
|
||||
m_params.m_eliminate_term_ite = true;
|
||||
m_params.m_nnf_cnf = false;
|
||||
setup_r_arith();
|
||||
setup_lra_arith();
|
||||
}
|
||||
|
||||
void setup::setup_QF_LRA(static_features const & st) {
|
||||
|
@ -479,7 +479,7 @@ namespace smt {
|
|||
m_params.m_restart_adaptive = false;
|
||||
}
|
||||
m_params.m_arith_small_lemma_size = 32;
|
||||
setup_r_arith();
|
||||
setup_lra_arith();
|
||||
}
|
||||
|
||||
void setup::setup_QF_LIRA(static_features const& st) {
|
||||
|
@ -493,7 +493,7 @@ namespace smt {
|
|||
m_params.m_arith_reflect = false;
|
||||
m_params.m_arith_propagate_eqs = false;
|
||||
m_params.m_nnf_cnf = false;
|
||||
setup_i_arith();
|
||||
setup_lra_arith();
|
||||
}
|
||||
|
||||
void setup::setup_QF_LIA(static_features const & st) {
|
||||
|
@ -534,7 +534,7 @@ namespace smt {
|
|||
m_params.m_arith_bound_prop = BP_NONE;
|
||||
m_params.m_arith_stronger_lemmas = false;
|
||||
}
|
||||
setup_i_arith();
|
||||
setup_lra_arith();
|
||||
}
|
||||
|
||||
void setup::setup_QF_UFLIA() {
|
||||
|
@ -542,7 +542,7 @@ namespace smt {
|
|||
m_params.m_arith_reflect = false;
|
||||
m_params.m_nnf_cnf = false;
|
||||
m_params.m_arith_propagation_threshold = 1000;
|
||||
setup_i_arith();
|
||||
setup_lra_arith();
|
||||
}
|
||||
|
||||
void setup::setup_QF_UFLIA(static_features & st) {
|
||||
|
@ -555,7 +555,7 @@ namespace smt {
|
|||
m_params.m_relevancy_lvl = 0;
|
||||
m_params.m_arith_reflect = false;
|
||||
m_params.m_nnf_cnf = false;
|
||||
setup_r_arith();
|
||||
setup_lra_arith();
|
||||
}
|
||||
|
||||
void setup::setup_QF_BV() {
|
||||
|
@ -721,8 +721,18 @@ namespace smt {
|
|||
}
|
||||
|
||||
void setup::setup_QF_S() {
|
||||
m_context.register_plugin(alloc(smt::theory_mi_arith, m_manager, m_params));
|
||||
m_context.register_plugin(alloc(smt::theory_str, m_manager, m_params));
|
||||
if (m_params.m_string_solver == "z3str3") {
|
||||
setup_str();
|
||||
}
|
||||
else if (m_params.m_string_solver == "seq") {
|
||||
setup_unknown();
|
||||
}
|
||||
else if (m_params.m_string_solver == "auto") {
|
||||
setup_unknown();
|
||||
}
|
||||
else {
|
||||
throw default_exception("invalid parameter for smt.string_solver, valid options are 'z3str3', 'seq', 'auto'");
|
||||
}
|
||||
}
|
||||
|
||||
bool is_arith(static_features const & st) {
|
||||
|
@ -730,23 +740,34 @@ namespace smt {
|
|||
}
|
||||
|
||||
void setup::setup_i_arith() {
|
||||
// m_context.register_plugin(alloc(smt::theory_lra, m_manager, m_params));
|
||||
m_context.register_plugin(alloc(smt::theory_i_arith, m_manager, m_params));
|
||||
if (AS_OLD_ARITH == m_params.m_arith_mode) {
|
||||
m_context.register_plugin(alloc(smt::theory_i_arith, m_manager, m_params));
|
||||
}
|
||||
else {
|
||||
setup_lra_arith();
|
||||
}
|
||||
}
|
||||
|
||||
void setup::setup_r_arith() {
|
||||
void setup::setup_lra_arith() {
|
||||
m_context.register_plugin(alloc(smt::theory_lra, m_manager, m_params));
|
||||
}
|
||||
|
||||
void setup::setup_mi_arith() {
|
||||
if (m_params.m_arith_mode == AS_OPTINF) {
|
||||
switch (m_params.m_arith_mode) {
|
||||
case AS_OPTINF:
|
||||
m_context.register_plugin(alloc(smt::theory_inf_arith, m_manager, m_params));
|
||||
}
|
||||
else {
|
||||
break;
|
||||
case AS_NEW_ARITH:
|
||||
setup_lra_arith();
|
||||
break;
|
||||
default:
|
||||
m_context.register_plugin(alloc(smt::theory_mi_arith, m_manager, m_params));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
void setup::setup_arith() {
|
||||
static_features st(m_manager);
|
||||
IF_VERBOSE(100, verbose_stream() << "(smt.collecting-features)\n";);
|
||||
|
@ -800,15 +821,18 @@ namespace smt {
|
|||
case AS_OPTINF:
|
||||
m_context.register_plugin(alloc(smt::theory_inf_arith, m_manager, m_params));
|
||||
break;
|
||||
case AS_LRA:
|
||||
setup_r_arith();
|
||||
break;
|
||||
default:
|
||||
case AS_OLD_ARITH:
|
||||
if (m_params.m_arith_int_only && int_only)
|
||||
m_context.register_plugin(alloc(smt::theory_i_arith, m_manager, m_params));
|
||||
else
|
||||
m_context.register_plugin(alloc(smt::theory_mi_arith, m_manager, m_params));
|
||||
break;
|
||||
case AS_NEW_ARITH:
|
||||
setup_lra_arith();
|
||||
break;
|
||||
default:
|
||||
m_context.register_plugin(alloc(smt::theory_mi_arith, m_manager, m_params));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -885,7 +909,7 @@ namespace smt {
|
|||
}
|
||||
|
||||
void setup::setup_seq() {
|
||||
m_context.register_plugin(alloc(smt::theory_seq, m_manager));
|
||||
m_context.register_plugin(alloc(smt::theory_seq, m_manager, m_params));
|
||||
}
|
||||
|
||||
void setup::setup_unknown() {
|
||||
|
@ -968,7 +992,7 @@ namespace smt {
|
|||
if (st.num_theories() == 2 && st.has_uf() && is_arith(st)) {
|
||||
if (!st.m_has_real)
|
||||
setup_QF_UFLIA(st);
|
||||
else if (!st.m_has_int && st.m_num_non_linear == 0)
|
||||
else if (!st.m_has_int && st.m_num_non_linear == 0)
|
||||
setup_QF_UFLRA();
|
||||
else
|
||||
setup_unknown();
|
||||
|
|
|
@ -101,7 +101,7 @@ namespace smt {
|
|||
void setup_card();
|
||||
void setup_i_arith();
|
||||
void setup_mi_arith();
|
||||
void setup_r_arith();
|
||||
void setup_lra_arith();
|
||||
void setup_fpa();
|
||||
void setup_str();
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@ class smt_tactic : public tactic {
|
|||
smt_params m_params;
|
||||
params_ref m_params_ref;
|
||||
statistics m_stats;
|
||||
std::string m_failure;
|
||||
smt::kernel * m_ctx;
|
||||
symbol m_logic;
|
||||
progress_callback * m_callback;
|
||||
|
@ -259,7 +258,7 @@ public:
|
|||
if (m_fail_if_inconclusive && !m_candidate_models) {
|
||||
std::stringstream strm;
|
||||
strm << "smt tactic failed to show goal to be sat/unsat " << m_ctx->last_failure_as_string();
|
||||
throw tactic_exception(strm.str().c_str());
|
||||
throw tactic_exception(strm.str());
|
||||
}
|
||||
result.push_back(in.get());
|
||||
if (m_candidate_models) {
|
||||
|
@ -281,8 +280,7 @@ public:
|
|||
break;
|
||||
}
|
||||
}
|
||||
m_failure = m_ctx->last_failure_as_string();
|
||||
throw tactic_exception(m_failure.c_str());
|
||||
throw tactic_exception(m_ctx->last_failure_as_string());
|
||||
}
|
||||
}
|
||||
catch (rewriter_exception & ex) {
|
||||
|
|
|
@ -42,7 +42,7 @@ Revision History:
|
|||
namespace smt {
|
||||
|
||||
struct theory_arith_stats {
|
||||
unsigned m_conflicts, m_add_rows, m_pivots, m_diseq_cs, m_gomory_cuts, m_branches, m_gcd_tests;
|
||||
unsigned m_conflicts, m_add_rows, m_pivots, m_diseq_cs, m_gomory_cuts, m_branches, m_gcd_tests, m_patches, m_patches_succ;
|
||||
unsigned m_assert_lower, m_assert_upper, m_assert_diseq, m_core2th_eqs, m_core2th_diseqs;
|
||||
unsigned m_th2core_eqs, m_th2core_diseqs, m_bound_props, m_offset_eqs, m_fixed_eqs, m_offline_eqs;
|
||||
unsigned m_max_min;
|
||||
|
|
|
@ -1335,7 +1335,7 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
});
|
||||
|
||||
m_stats.m_patches++;
|
||||
patch_int_infeasible_vars();
|
||||
fix_non_base_vars();
|
||||
|
||||
|
@ -1368,6 +1368,7 @@ namespace smt {
|
|||
|
||||
theory_var int_var = find_infeasible_int_base_var();
|
||||
if (int_var == null_theory_var) {
|
||||
m_stats.m_patches_succ++;
|
||||
TRACE("arith_int_incomp", tout << "FC_DONE 2...\n"; display(tout););
|
||||
return m_liberal_final_check || !m_changed_assignment ? FC_DONE : FC_CONTINUE;
|
||||
}
|
||||
|
@ -1385,6 +1386,7 @@ namespace smt {
|
|||
|
||||
m_branch_cut_counter++;
|
||||
// TODO: add giveup code
|
||||
TRACE("gomory_cut", tout << m_branch_cut_counter << ", " << m_params.m_arith_branch_cut_ratio << std::endl;);
|
||||
if (m_branch_cut_counter % m_params.m_arith_branch_cut_ratio == 0) {
|
||||
TRACE("opt_verbose", display(tout););
|
||||
move_non_base_vars_to_bounds();
|
||||
|
@ -1399,7 +1401,7 @@ namespace smt {
|
|||
SASSERT(is_base(int_var));
|
||||
row const & r = m_rows[get_var_row(int_var)];
|
||||
if (!mk_gomory_cut(r)) {
|
||||
// silent failure
|
||||
TRACE("gomory_cut", tout << "silent failure\n";);
|
||||
}
|
||||
return FC_CONTINUE;
|
||||
}
|
||||
|
|
|
@ -38,6 +38,8 @@ namespace smt {
|
|||
st.update("arith gcd tests", m_stats.m_gcd_tests);
|
||||
st.update("arith ineq splits", m_stats.m_branches);
|
||||
st.update("arith gomory cuts", m_stats.m_gomory_cuts);
|
||||
st.update("arith patches", m_stats.m_patches);
|
||||
st.update("arith patches_succ", m_stats.m_patches_succ);
|
||||
st.update("arith max-min", m_stats.m_max_min);
|
||||
st.update("arith grobner", m_stats.m_gb_compute_basis);
|
||||
st.update("arith pseudo nonlinear", m_stats.m_nl_linear);
|
||||
|
@ -389,8 +391,19 @@ namespace smt {
|
|||
void theory_arith<Ext>::display_vars(std::ostream & out) const {
|
||||
out << "vars:\n";
|
||||
int n = get_num_vars();
|
||||
for (theory_var v = 0; v < n; v++)
|
||||
display_var(out, v);
|
||||
int inf_vars = 0;
|
||||
int int_inf_vars = 0;
|
||||
for (theory_var v = 0; v < n; v++) {
|
||||
if ((lower(v) && lower(v)->get_value() > get_value(v))
|
||||
|| (upper(v) && upper(v)->get_value() < get_value(v)))
|
||||
inf_vars++;
|
||||
if (is_int(v) && !get_value(v).is_int())
|
||||
int_inf_vars++;
|
||||
}
|
||||
out << "infeasibles = " << inf_vars << " int_inf = " << int_inf_vars << std::endl;
|
||||
for (theory_var v = 0; v < n; v++) {
|
||||
display_var(out, v);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename Ext>
|
||||
|
|
|
@ -383,7 +383,7 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
TRACE("array", tout << "m_found_unsupported_op: " << m_found_unsupported_op << " " << r << "\n";);
|
||||
if (r == FC_DONE && m_found_unsupported_op)
|
||||
if (r == FC_DONE && m_found_unsupported_op && !get_context().get_fparams().m_array_fake_support)
|
||||
r = FC_GIVEUP;
|
||||
return r;
|
||||
}
|
||||
|
|
|
@ -33,8 +33,12 @@ namespace smt {
|
|||
}
|
||||
|
||||
void theory_array_base::found_unsupported_op(expr * n) {
|
||||
TRACE("array", tout << mk_ll_pp(n, get_manager()) << "\n";);
|
||||
if (!m_found_unsupported_op) {
|
||||
if (!get_context().get_fparams().m_array_fake_support && !m_found_unsupported_op) {
|
||||
//array_util autil(get_manager());
|
||||
//func_decl* f = 0;
|
||||
//if (autil.is_as_array(n, f) && f->is_skolem()) return;
|
||||
TRACE("array", tout << mk_ll_pp(n, get_manager()) << "\n";);
|
||||
|
||||
get_context().push_trail(value_trail<context, bool>(m_found_unsupported_op));
|
||||
m_found_unsupported_op = true;
|
||||
}
|
||||
|
|
|
@ -17,13 +17,13 @@ Revision History:
|
|||
|
||||
--*/
|
||||
|
||||
#include "smt/smt_context.h"
|
||||
#include "smt/theory_array_full.h"
|
||||
#include "util/stats.h"
|
||||
#include "ast/ast_ll_pp.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/ast_util.h"
|
||||
#include "ast/ast_smt2_pp.h"
|
||||
#include "util/stats.h"
|
||||
#include "smt/smt_context.h"
|
||||
#include "smt/theory_array_full.h"
|
||||
|
||||
namespace smt {
|
||||
|
||||
|
@ -54,11 +54,9 @@ namespace smt {
|
|||
set_prop_upward(v,d);
|
||||
d_full->m_maps.push_back(s);
|
||||
m_trail_stack.push(push_back_trail<theory_array, enode *, false>(d_full->m_maps));
|
||||
ptr_vector<enode>::iterator it = d->m_parent_selects.begin();
|
||||
ptr_vector<enode>::iterator end = d->m_parent_selects.end();
|
||||
for (; it != end; ++it) {
|
||||
SASSERT(is_select(*it));
|
||||
instantiate_select_map_axiom(*it, s);
|
||||
for (enode* n : d->m_parent_selects) {
|
||||
SASSERT(is_select(n));
|
||||
instantiate_select_map_axiom(n, s);
|
||||
}
|
||||
set_prop_upward(s);
|
||||
}
|
||||
|
@ -67,15 +65,10 @@ namespace smt {
|
|||
bool result = false;
|
||||
var_data * d = m_var_data[v];
|
||||
var_data_full * d_full = m_var_data_full[v];
|
||||
unsigned num_maps = d_full->m_parent_maps.size();
|
||||
unsigned num_selects = d->m_parent_selects.size();
|
||||
for (unsigned i = 0; i < num_maps; ++i) {
|
||||
for (unsigned j = 0; j < num_selects; ++j) {
|
||||
if (instantiate_select_map_axiom(d->m_parent_selects[j], d_full->m_parent_maps[i])) {
|
||||
result = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (enode* pm : d_full->m_parent_maps)
|
||||
for (enode* ps : d->m_parent_selects)
|
||||
if (instantiate_select_map_axiom(ps, pm))
|
||||
result = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -91,11 +84,9 @@ namespace smt {
|
|||
d_full->m_parent_maps.push_back(s);
|
||||
m_trail_stack.push(push_back_trail<theory_array, enode *, false>(d_full->m_parent_maps));
|
||||
if (!m_params.m_array_weak && !m_params.m_array_delay_exp_axiom && d->m_prop_upward) {
|
||||
ptr_vector<enode>::iterator it = d->m_parent_selects.begin();
|
||||
ptr_vector<enode>::iterator end = d->m_parent_selects.end();
|
||||
for (; it != end; ++it) {
|
||||
if (!m_params.m_array_cg || (*it)->is_cgr()) {
|
||||
instantiate_select_map_axiom(*it, s);
|
||||
for (enode * n : d->m_parent_selects) {
|
||||
if (!m_params.m_array_cg || n->is_cgr()) {
|
||||
instantiate_select_map_axiom(n, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -118,20 +109,14 @@ namespace smt {
|
|||
instantiate_axiom_map_for(v);
|
||||
}
|
||||
var_data_full * d2 = m_var_data_full[v];
|
||||
ptr_vector<enode>::iterator it = d->m_stores.begin();
|
||||
ptr_vector<enode>::iterator end = d->m_stores.end();
|
||||
for (; it != end; ++it) {
|
||||
set_prop_upward(*it);
|
||||
for (enode * n : d->m_stores) {
|
||||
set_prop_upward(n);
|
||||
}
|
||||
it = d2->m_maps.begin();
|
||||
end = d2->m_maps.end();
|
||||
for (; it != end; ++it) {
|
||||
set_prop_upward(*it);
|
||||
for (enode * n : d2->m_maps) {
|
||||
set_prop_upward(n);
|
||||
}
|
||||
it = d2->m_consts.begin();
|
||||
end = d2->m_consts.end();
|
||||
for (; it != end; ++it) {
|
||||
set_prop_upward(*it);
|
||||
for (enode * n : d2->m_consts) {
|
||||
set_prop_upward(n);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -180,12 +165,9 @@ namespace smt {
|
|||
m_trail_stack.push(push_back_trail<theory_array, enode *, false>(consts));
|
||||
consts.push_back(cnst);
|
||||
instantiate_default_const_axiom(cnst);
|
||||
|
||||
ptr_vector<enode>::iterator it = d->m_parent_selects.begin();
|
||||
ptr_vector<enode>::iterator end = d->m_parent_selects.end();
|
||||
for (; it != end; ++it) {
|
||||
SASSERT(is_select(*it));
|
||||
instantiate_select_const_axiom(*it, cnst);
|
||||
for (enode * n : d->m_parent_selects) {
|
||||
SASSERT(is_select(n));
|
||||
instantiate_select_const_axiom(n, cnst);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -199,12 +181,9 @@ namespace smt {
|
|||
m_trail_stack.push(push_back_trail<theory_array, enode *, false>(as_arrays));
|
||||
as_arrays.push_back(arr);
|
||||
instantiate_default_as_array_axiom(arr);
|
||||
|
||||
ptr_vector<enode>::iterator it = d->m_parent_selects.begin();
|
||||
ptr_vector<enode>::iterator end = d->m_parent_selects.end();
|
||||
for (; it != end; ++it) {
|
||||
SASSERT(is_select(*it));
|
||||
instantiate_select_as_array_axiom(*it, arr);
|
||||
for (enode * n : d->m_parent_selects) {
|
||||
SASSERT(is_select(n));
|
||||
instantiate_select_as_array_axiom(n, arr);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -257,6 +236,10 @@ namespace smt {
|
|||
}
|
||||
|
||||
bool theory_array_full::internalize_term(app * n) {
|
||||
context & ctx = get_context();
|
||||
if (ctx.e_internalized(n)) {
|
||||
return true;
|
||||
}
|
||||
TRACE("array", tout << mk_pp(n, get_manager()) << "\n";);
|
||||
|
||||
if (is_store(n) || is_select(n)) {
|
||||
|
@ -272,11 +255,10 @@ namespace smt {
|
|||
if (!internalize_term_core(n)) {
|
||||
return true;
|
||||
}
|
||||
context & ctx = get_context();
|
||||
|
||||
if (is_map(n) || is_array_ext(n)) {
|
||||
for (unsigned i = 0; i < n->get_num_args(); ++i) {
|
||||
enode* arg = ctx.get_enode(n->get_arg(i));
|
||||
for (expr* e : *n) {
|
||||
enode* arg = ctx.get_enode(e);
|
||||
if (!is_attached_to_var(arg)) {
|
||||
mk_var(arg);
|
||||
}
|
||||
|
@ -300,8 +282,8 @@ namespace smt {
|
|||
add_parent_default(v_arg);
|
||||
}
|
||||
else if (is_map(n)) {
|
||||
for (unsigned i = 0; i < n->get_num_args(); ++i) {
|
||||
enode* arg = ctx.get_enode(n->get_arg(i));
|
||||
for (expr* e : *n) {
|
||||
enode* arg = ctx.get_enode(e);
|
||||
theory_var v_arg = arg->get_th_var(get_id());
|
||||
add_parent_map(v_arg, node);
|
||||
}
|
||||
|
@ -334,27 +316,17 @@ namespace smt {
|
|||
// v1 is the new root
|
||||
SASSERT(v1 == find(v1));
|
||||
var_data_full * d2 = m_var_data_full[v2];
|
||||
ptr_vector<enode>::iterator it, end;
|
||||
|
||||
it = d2->m_maps.begin();
|
||||
end = d2->m_maps.end();
|
||||
for (; it != end; ++it) {
|
||||
add_map(v1, *it);
|
||||
for (enode * n : d2->m_maps) {
|
||||
add_map(v1, n);
|
||||
}
|
||||
it = d2->m_parent_maps.begin();
|
||||
end = d2->m_parent_maps.end();
|
||||
for (; it != end; ++it) {
|
||||
add_parent_map(v1, *it);
|
||||
for (enode * n : d2->m_parent_maps) {
|
||||
add_parent_map(v1, n);
|
||||
}
|
||||
it = d2->m_consts.begin();
|
||||
end = d2->m_consts.end();
|
||||
for (; it != end; ++it) {
|
||||
add_const(v1, *it);
|
||||
for (enode * n : d2->m_consts) {
|
||||
add_const(v1, n);
|
||||
}
|
||||
it = d2->m_as_arrays.begin();
|
||||
end = d2->m_as_arrays.end();
|
||||
for (; it != end; ++it) {
|
||||
add_as_array(v1, *it);
|
||||
for (enode * n : d2->m_as_arrays) {
|
||||
add_as_array(v1, n);
|
||||
}
|
||||
TRACE("array",
|
||||
tout << mk_pp(get_enode(v1)->get_owner(), get_manager()) << "\n";
|
||||
|
@ -367,21 +339,13 @@ namespace smt {
|
|||
SASSERT(v != null_theory_var);
|
||||
v = find(v);
|
||||
var_data* d = m_var_data[v];
|
||||
ptr_vector<enode>::iterator it, end;
|
||||
|
||||
it = d->m_stores.begin();
|
||||
end = d->m_stores.end();
|
||||
for(; it != end; ++it) {
|
||||
enode * store = *it;
|
||||
for (enode * store : d->m_stores) {
|
||||
SASSERT(is_store(store));
|
||||
instantiate_default_store_axiom(store);
|
||||
}
|
||||
|
||||
if (!m_params.m_array_weak && !m_params.m_array_delay_exp_axiom && d->m_prop_upward) {
|
||||
it = d->m_parent_stores.begin();
|
||||
end = d->m_parent_stores.end();
|
||||
for (; it != end; ++it) {
|
||||
enode* store = *it;
|
||||
for (enode * store : d->m_parent_stores) {
|
||||
SASSERT(is_store(store));
|
||||
if (!m_params.m_array_cg || store->is_cgr()) {
|
||||
instantiate_default_store_axiom(store);
|
||||
|
@ -399,23 +363,15 @@ namespace smt {
|
|||
v = find(v);
|
||||
var_data_full* d_full = m_var_data_full[v];
|
||||
var_data* d = m_var_data[v];
|
||||
ptr_vector<enode>::iterator it = d_full->m_consts.begin();
|
||||
ptr_vector<enode>::iterator end = d_full->m_consts.end();
|
||||
for (; it != end; ++it) {
|
||||
instantiate_select_const_axiom(s, *it);
|
||||
for (enode * n : d_full->m_consts) {
|
||||
instantiate_select_const_axiom(s, n);
|
||||
}
|
||||
it = d_full->m_maps.begin();
|
||||
end = d_full->m_maps.end();
|
||||
for (; it != end; ++it) {
|
||||
enode* map = *it;
|
||||
for (enode * map : d_full->m_maps) {
|
||||
SASSERT(is_map(map));
|
||||
instantiate_select_map_axiom(s, map);
|
||||
}
|
||||
if (!m_params.m_array_weak && !m_params.m_array_delay_exp_axiom && d->m_prop_upward) {
|
||||
it = d_full->m_parent_maps.begin();
|
||||
end = d_full->m_parent_maps.end();
|
||||
for (; it != end; ++it) {
|
||||
enode* map = *it;
|
||||
for (enode * map : d_full->m_parent_maps) {
|
||||
SASSERT(is_map(map));
|
||||
if (!m_params.m_array_cg || map->is_cgr()) {
|
||||
instantiate_select_map_axiom(s, map);
|
||||
|
@ -437,7 +393,7 @@ namespace smt {
|
|||
enode * arg = ctx.get_enode(n->get_arg(0));
|
||||
theory_var v = arg->get_th_var(get_id());
|
||||
SASSERT(v != null_theory_var);
|
||||
add_parent_select(find(v), node);
|
||||
add_parent_select(find(v), node);
|
||||
}
|
||||
else if (is_default(n)) {
|
||||
enode * arg = ctx.get_enode(n->get_arg(0));
|
||||
|
@ -577,7 +533,14 @@ namespace smt {
|
|||
return try_assign_eq(val, def);
|
||||
}
|
||||
|
||||
/**
|
||||
* instantiate f(ep1,ep2,..,ep_n) = default(as-array f)
|
||||
* it is disabled to avoid as-array terms during search.
|
||||
*/
|
||||
|
||||
bool theory_array_full::instantiate_default_as_array_axiom(enode* arr) {
|
||||
return false;
|
||||
#if 0
|
||||
context& ctx = get_context();
|
||||
if (!ctx.add_fingerprint(this, 0, 1, &arr)) {
|
||||
return false;
|
||||
|
@ -595,6 +558,7 @@ namespace smt {
|
|||
ctx.internalize(def, false);
|
||||
ctx.internalize(val.get(), false);
|
||||
return try_assign_eq(val.get(), def);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool theory_array_full::has_large_domain(app* array_term) {
|
||||
|
|
|
@ -843,14 +843,12 @@ namespace smt {
|
|||
context & ctx = get_context();
|
||||
|
||||
bool first = true;
|
||||
ptr_vector<enode>::const_iterator it = ctx.begin_enodes();
|
||||
ptr_vector<enode>::const_iterator end = ctx.end_enodes();
|
||||
for (; it != end; it++) {
|
||||
theory_var v = (*it)->get_th_var(get_family_id());
|
||||
for (enode* n : ctx.enodes()) {
|
||||
theory_var v = n->get_th_var(get_family_id());
|
||||
if (v != -1) {
|
||||
if (first) out << "fpa theory variables:" << std::endl;
|
||||
out << v << " -> " <<
|
||||
mk_ismt2_pp((*it)->get_owner(), m) << std::endl;
|
||||
mk_ismt2_pp(n->get_owner(), m) << std::endl;
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
@ -858,30 +856,24 @@ namespace smt {
|
|||
if (first) return;
|
||||
|
||||
out << "bv theory variables:" << std::endl;
|
||||
it = ctx.begin_enodes();
|
||||
end = ctx.end_enodes();
|
||||
for (; it != end; it++) {
|
||||
theory_var v = (*it)->get_th_var(m_bv_util.get_family_id());
|
||||
for (enode * n : ctx.enodes()) {
|
||||
theory_var v = n->get_th_var(m_bv_util.get_family_id());
|
||||
if (v != -1) out << v << " -> " <<
|
||||
mk_ismt2_pp((*it)->get_owner(), m) << std::endl;
|
||||
mk_ismt2_pp(n->get_owner(), m) << std::endl;
|
||||
}
|
||||
|
||||
out << "arith theory variables:" << std::endl;
|
||||
it = ctx.begin_enodes();
|
||||
end = ctx.end_enodes();
|
||||
for (; it != end; it++) {
|
||||
theory_var v = (*it)->get_th_var(m_arith_util.get_family_id());
|
||||
for (enode* n : ctx.enodes()) {
|
||||
theory_var v = n->get_th_var(m_arith_util.get_family_id());
|
||||
if (v != -1) out << v << " -> " <<
|
||||
mk_ismt2_pp((*it)->get_owner(), m) << std::endl;
|
||||
mk_ismt2_pp(n->get_owner(), m) << std::endl;
|
||||
}
|
||||
|
||||
out << "equivalence classes:\n";
|
||||
it = ctx.begin_enodes();
|
||||
end = ctx.end_enodes();
|
||||
for (; it != end; ++it) {
|
||||
expr * n = (*it)->get_owner();
|
||||
expr * r = (*it)->get_root()->get_owner();
|
||||
out << r->get_id() << " --> " << mk_ismt2_pp(n, m) << std::endl;
|
||||
for (enode * n : ctx.enodes()) {
|
||||
expr * e = n->get_owner();
|
||||
expr * r = n->get_root()->get_owner();
|
||||
out << r->get_id() << " --> " << mk_ismt2_pp(e, m) << std::endl;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -31,7 +31,7 @@ namespace smt {
|
|||
theory_lra(ast_manager& m, theory_arith_params& ap);
|
||||
~theory_lra() override;
|
||||
theory* mk_fresh(context* new_ctx) override;
|
||||
char const* get_name() const override { return "lra"; }
|
||||
char const* get_name() const override { return "arithmetic"; }
|
||||
|
||||
void init(context * ctx) override;
|
||||
|
||||
|
@ -78,6 +78,8 @@ namespace smt {
|
|||
model_value_proc * mk_value(enode * n, model_generator & mg) override;
|
||||
|
||||
bool get_value(enode* n, expr_ref& r) override;
|
||||
bool get_lower(enode* n, expr_ref& r);
|
||||
bool get_upper(enode* n, expr_ref& r);
|
||||
|
||||
bool validate_eq_in_model(theory_var v1, theory_var v2, bool is_true) const override;
|
||||
|
||||
|
|
|
@ -752,9 +752,10 @@ namespace smt {
|
|||
class theory_pb::card_justification : public justification {
|
||||
card& m_card;
|
||||
family_id m_fid;
|
||||
literal m_lit;
|
||||
public:
|
||||
card_justification(card& c, family_id fid)
|
||||
: justification(true), m_card(c), m_fid(fid) {}
|
||||
card_justification(card& c, literal lit, family_id fid)
|
||||
: justification(true), m_card(c), m_fid(fid), m_lit(lit) {}
|
||||
|
||||
card& get_card() { return m_card; }
|
||||
|
||||
|
@ -769,7 +770,28 @@ namespace smt {
|
|||
return m_fid;
|
||||
}
|
||||
|
||||
virtual proof* mk_proof(smt::conflict_resolution& cr) { return 0; }
|
||||
virtual proof* mk_proof(smt::conflict_resolution& cr) {
|
||||
ptr_buffer<proof> prs;
|
||||
ast_manager& m = cr.get_context().get_manager();
|
||||
expr_ref fact(m);
|
||||
cr.get_context().literal2expr(m_lit, fact);
|
||||
bool all_valid = true;
|
||||
proof* pr = nullptr;
|
||||
pr = cr.get_proof(m_card.lit());
|
||||
all_valid &= pr != nullptr;
|
||||
prs.push_back(pr);
|
||||
for (unsigned i = m_card.k(); i < m_card.size(); ++i) {
|
||||
pr = cr.get_proof(~m_card.lit(i));
|
||||
all_valid &= pr != nullptr;
|
||||
prs.push_back(pr);
|
||||
}
|
||||
if (!all_valid) {
|
||||
return nullptr;
|
||||
}
|
||||
else {
|
||||
return m.mk_th_lemma(m_fid, fact, prs.size(), prs.c_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
@ -940,11 +962,11 @@ namespace smt {
|
|||
m_stats.m_num_conflicts++;
|
||||
context& ctx = get_context();
|
||||
justification* js = 0;
|
||||
if (proofs_enabled()) {
|
||||
js = alloc(theory_lemma_justification, get_id(), ctx, lits.size(), lits.c_ptr());
|
||||
}
|
||||
c.inc_propagations(*this);
|
||||
if (!resolve_conflict(c, lits)) {
|
||||
if (proofs_enabled()) {
|
||||
js = alloc(theory_lemma_justification, get_id(), ctx, lits.size(), lits.c_ptr());
|
||||
}
|
||||
ctx.mk_clause(lits.size(), lits.c_ptr(), js, CLS_AUX_LEMMA, 0);
|
||||
}
|
||||
SASSERT(ctx.inconsistent());
|
||||
|
@ -959,7 +981,7 @@ namespace smt {
|
|||
m_stats.m_num_propagations++;
|
||||
TRACE("pb", tout << "#prop: " << c.num_propagations() << " - " << c.lit() << " => " << l << "\n";);
|
||||
SASSERT(validate_unit_propagation(c));
|
||||
ctx.assign(l, ctx.mk_justification(card_justification(c, get_id())));
|
||||
ctx.assign(l, ctx.mk_justification(card_justification(c, l, get_id())));
|
||||
}
|
||||
|
||||
void theory_pb::clear_watch(card& c) {
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -29,6 +29,7 @@ Revision History:
|
|||
#include "math/automata/automaton.h"
|
||||
#include "ast/rewriter/seq_rewriter.h"
|
||||
#include "util/union_find.h"
|
||||
#include "util/obj_ref_hashtable.h"
|
||||
|
||||
namespace smt {
|
||||
|
||||
|
@ -48,7 +49,7 @@ namespace smt {
|
|||
typedef union_find<theory_seq> th_union_find;
|
||||
|
||||
class seq_value_proc;
|
||||
|
||||
|
||||
// cache to track evaluations under equalities
|
||||
class eval_cache {
|
||||
eqdep_map_t m_map;
|
||||
|
@ -292,6 +293,7 @@ namespace smt {
|
|||
typedef hashtable<rational, rational::hash_proc, rational::eq_proc> rational_set;
|
||||
|
||||
ast_manager& m;
|
||||
theory_seq_params const& m_params;
|
||||
dependency_manager m_dm;
|
||||
solution_map m_rep; // unification representative.
|
||||
bool m_reset_cache; // invalidate cache.
|
||||
|
@ -301,6 +303,12 @@ namespace smt {
|
|||
unsigned m_eq_id;
|
||||
th_union_find m_find;
|
||||
|
||||
obj_ref_map<ast_manager, expr, unsigned_vector> m_overlap;
|
||||
obj_ref_map<ast_manager, expr, unsigned_vector> m_overlap2;
|
||||
obj_map<enode, obj_map<enode, int>> m_len_offset;
|
||||
int m_len_prop_lvl;
|
||||
|
||||
|
||||
seq_factory* m_factory; // value factory
|
||||
exclusion_table m_exclude; // set of asserted disequalities.
|
||||
expr_ref_vector m_axioms; // list of axioms to add.
|
||||
|
@ -321,7 +329,7 @@ namespace smt {
|
|||
stats m_stats;
|
||||
symbol m_prefix, m_suffix, 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_pre, m_post, m_eq;
|
||||
symbol m_pre, m_post, m_eq, m_seq_align;
|
||||
ptr_vector<expr> m_todo;
|
||||
expr_ref_vector m_ls, m_rs, m_lhs, m_rhs;
|
||||
|
||||
|
@ -354,7 +362,7 @@ namespace smt {
|
|||
void pop_scope_eh(unsigned num_scopes) override;
|
||||
void restart_eh() override;
|
||||
void relevant_eh(app* n) override;
|
||||
theory* mk_fresh(context* new_ctx) override { return alloc(theory_seq, new_ctx->get_manager()); }
|
||||
theory* mk_fresh(context* new_ctx) override { return alloc(theory_seq, new_ctx->get_manager(), m_params); }
|
||||
char const * get_name() const override { return "seq"; }
|
||||
theory_var mk_var(enode* n) override;
|
||||
void apply_sort_cnstr(enode* n, sort* s) override;
|
||||
|
@ -366,23 +374,44 @@ namespace smt {
|
|||
void init_search_eh() override;
|
||||
|
||||
void init_model(expr_ref_vector const& es);
|
||||
|
||||
void len_offset(expr* const& e, rational val);
|
||||
void prop_arith_to_len_offset();
|
||||
int find_fst_non_empty_idx(expr_ref_vector const& x) const;
|
||||
expr* find_fst_non_empty_var(expr_ref_vector const& x) const;
|
||||
void find_max_eq_len(expr_ref_vector const& ls, expr_ref_vector const& rs);
|
||||
bool has_len_offset(expr_ref_vector const& ls, expr_ref_vector const& rs, int & diff);
|
||||
bool find_better_rep(expr_ref_vector const& ls, expr_ref_vector const& rs, unsigned const& idx, dependency*& deps, expr_ref_vector & res);
|
||||
|
||||
// final check
|
||||
bool simplify_and_solve_eqs(); // solve unitary equalities
|
||||
bool reduce_length_eq();
|
||||
bool branch_unit_variable(); // branch on XYZ = abcdef
|
||||
bool branch_binary_variable(); // branch on abcX = Ydefg
|
||||
bool branch_ternary_variable1(); // branch on XabcY = Zdefg or XabcY = defgZ
|
||||
bool branch_ternary_variable2(); // branch on XabcY = defgZmnpq
|
||||
bool branch_quat_variable(); // branch on XabcY = ZdefgT
|
||||
bool len_based_split(); // split based on len offset
|
||||
bool branch_variable_mb(); // branch on a variable, model based on length
|
||||
bool branch_variable(); // branch on a variable
|
||||
bool split_variable(); // split a variable
|
||||
bool is_solved();
|
||||
bool check_length_coherence();
|
||||
bool check_length_coherence0(expr* e);
|
||||
bool check_length_coherence(expr* e);
|
||||
bool fixed_length();
|
||||
bool fixed_length(expr* e);
|
||||
bool fixed_length(bool is_zero = false);
|
||||
bool fixed_length(expr* e, bool is_zero);
|
||||
void branch_unit_variable(dependency* dep, expr* X, expr_ref_vector const& units);
|
||||
bool branch_variable(eq const& e);
|
||||
bool branch_binary_variable(eq const& e);
|
||||
bool eq_unit(expr* const& l, expr* const &r) const;
|
||||
unsigned_vector overlap(expr_ref_vector const& ls, expr_ref_vector const& rs);
|
||||
unsigned_vector overlap2(expr_ref_vector const& ls, expr_ref_vector const& rs);
|
||||
bool branch_ternary_variable_base(dependency* dep, unsigned_vector indexes, expr* const& x, expr_ref_vector const& xs, expr* const& y1, expr_ref_vector const& ys, expr* const& y2);
|
||||
bool branch_ternary_variable_base2(dependency* dep, unsigned_vector indexes, expr_ref_vector const& xs, expr* const& x, expr* const& y1, expr_ref_vector const& ys, expr* const& y2);
|
||||
bool branch_ternary_variable(eq const& e, bool flag1 = false);
|
||||
bool branch_ternary_variable2(eq const& e, bool flag1 = false);
|
||||
bool branch_quat_variable(eq const& e);
|
||||
bool len_based_split(eq const& e);
|
||||
bool is_unit_eq(expr_ref_vector const& ls, expr_ref_vector const& rs);
|
||||
bool propagate_length_coherence(expr* e);
|
||||
bool split_lengths(dependency* dep,
|
||||
|
@ -394,11 +423,14 @@ namespace smt {
|
|||
bool check_extensionality();
|
||||
bool check_contains();
|
||||
bool solve_eqs(unsigned start);
|
||||
bool solve_eq(expr_ref_vector const& l, expr_ref_vector const& r, dependency* dep);
|
||||
bool solve_eq(expr_ref_vector const& l, expr_ref_vector const& r, dependency* dep, unsigned idx);
|
||||
bool simplify_eq(expr_ref_vector& l, expr_ref_vector& r, dependency* dep);
|
||||
bool solve_unit_eq(expr* l, expr* r, dependency* dep);
|
||||
bool solve_unit_eq(expr_ref_vector const& l, expr_ref_vector const& r, dependency* dep);
|
||||
bool is_binary_eq(expr_ref_vector const& l, expr_ref_vector const& r, expr*& x, ptr_vector<expr>& xunits, ptr_vector<expr>& yunits, expr*& y);
|
||||
bool is_quat_eq(expr_ref_vector const& ls, expr_ref_vector const& rs, expr*& x1, expr_ref_vector& xs, expr*& x2, expr*& y1, expr_ref_vector& ys, expr*& y2);
|
||||
bool is_ternary_eq(expr_ref_vector const& ls, expr_ref_vector const& rs, expr*& x, expr_ref_vector& xs, expr*& y1, expr_ref_vector& ys, expr*& y2, bool flag1);
|
||||
bool is_ternary_eq2(expr_ref_vector const& ls, expr_ref_vector const& rs, expr_ref_vector& xs, expr*& x, expr*& y1, expr_ref_vector& ys, expr*& y2, bool flag1);
|
||||
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);
|
||||
|
||||
|
@ -410,7 +442,7 @@ namespace smt {
|
|||
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(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) { SASSERT(!es.empty()); return mk_concat(es.size(), es.c_ptr()); }
|
||||
expr_ref mk_concat(expr_ref_vector const& es) { SASSERT(!es.empty()); return expr_ref(m_util.str.mk_concat(es.size(), es.c_ptr()), m); }
|
||||
expr_ref mk_concat(ptr_vector<expr> const& es) { SASSERT(!es.empty()); return mk_concat(es.size(), es.c_ptr()); }
|
||||
expr_ref mk_concat(expr* e1, expr* e2) { return expr_ref(m_util.str.mk_concat(e1, e2), m); }
|
||||
expr_ref mk_concat(expr* e1, expr* e2, expr* e3) { return expr_ref(m_util.str.mk_concat(e1, e2, e3), m); }
|
||||
|
@ -454,8 +486,9 @@ namespace smt {
|
|||
// variable solving utilities
|
||||
bool occurs(expr* a, expr* b);
|
||||
bool occurs(expr* a, expr_ref_vector const& b);
|
||||
bool is_var(expr* b);
|
||||
bool is_var(expr* b) const;
|
||||
bool add_solution(expr* l, expr* r, dependency* dep);
|
||||
bool is_unit_nth(expr* a) const;
|
||||
bool is_nth(expr* a) const;
|
||||
bool is_nth(expr* a, expr*& e1, expr*& e2) const;
|
||||
bool is_tail(expr* a, expr*& s, unsigned& idx) const;
|
||||
|
@ -521,6 +554,7 @@ namespace smt {
|
|||
literal mk_seq_eq(expr* a, expr* b);
|
||||
void tightest_prefix(expr* s, expr* x);
|
||||
expr_ref mk_sub(expr* a, expr* b);
|
||||
expr_ref mk_add(expr* a, expr* b);
|
||||
enode* ensure_enode(expr* a);
|
||||
|
||||
dependency* mk_join(dependency* deps, literal lit);
|
||||
|
@ -530,11 +564,13 @@ namespace smt {
|
|||
// arithmetic integration
|
||||
bool get_num_value(expr* s, rational& val) const;
|
||||
bool lower_bound(expr* s, rational& lo) const;
|
||||
bool lower_bound2(expr* s, rational& lo);
|
||||
bool upper_bound(expr* s, rational& hi) const;
|
||||
bool get_length(expr* s, rational& val) const;
|
||||
|
||||
void mk_decompose(expr* e, expr_ref& head, expr_ref& tail);
|
||||
expr_ref mk_skolem(symbol const& s, expr* e1, expr* e2 = nullptr, expr* e3 = nullptr, sort* range = nullptr);
|
||||
expr* coalesce_chars(expr* const& str);
|
||||
expr_ref mk_skolem(symbol const& s, expr* e1, expr* e2 = nullptr, expr* e3 = nullptr, expr* e4 = nullptr, sort* range = nullptr);
|
||||
bool is_skolem(symbol const& s, expr* e) const;
|
||||
|
||||
void set_incomplete(app* term);
|
||||
|
@ -586,7 +622,7 @@ namespace smt {
|
|||
void display_deps(std::ostream& out, literal_vector const& lits, enode_pair_vector const& eqs) const;
|
||||
void display_nc(std::ostream& out, nc const& nc) const;
|
||||
public:
|
||||
theory_seq(ast_manager& m);
|
||||
theory_seq(ast_manager& m, theory_seq_params const & params);
|
||||
~theory_seq() override;
|
||||
|
||||
// model building
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue