mirror of
https://github.com/Z3Prover/z3
synced 2025-10-07 16:31:55 +00:00
initial integration of opt
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
8205b45839
114 changed files with 3680 additions and 1370 deletions
|
@ -3942,7 +3942,7 @@ namespace smt {
|
|||
#endif
|
||||
|
||||
virtual void on_match(quantifier * qa, app * pat, unsigned num_bindings, enode * const * bindings, unsigned max_generation, ptr_vector<enode> & used_enodes) {
|
||||
TRACE("trigger_bug", tout << "found match\n";);
|
||||
TRACE("trigger_bug", tout << "found match " << mk_pp(qa, m_ast_manager) << "\n";);
|
||||
#ifdef Z3DEBUG
|
||||
if (m_check_missing_instances) {
|
||||
if (!m_context.slow_contains_instance(qa, num_bindings, bindings)) {
|
||||
|
|
|
@ -81,7 +81,7 @@ ext_numeral & ext_numeral::operator*=(ext_numeral const & other) {
|
|||
m_value.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
if (is_infinite() || other.is_infinite()) {
|
||||
if (sign() == other.sign())
|
||||
m_kind = PLUS_INFINITY;
|
||||
|
@ -203,7 +203,7 @@ interval::interval(v_dependency_manager & m, rational const & val, v_dependency
|
|||
m_lower_dep(l_dep),
|
||||
m_upper_dep(u_dep) {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Create intervals (-oo, val], (-oo, val), [val, oo), (val, oo)
|
||||
*/
|
||||
|
@ -271,8 +271,8 @@ interval & interval::operator-=(interval const & other) {
|
|||
return operator+=(tmp);
|
||||
}
|
||||
|
||||
v_dependency * interval::join(v_dependency * d1, v_dependency * d2, v_dependency * d3, v_dependency * d4) {
|
||||
return m_manager.mk_join(m_manager.mk_join(d1, d2), m_manager.mk_join(d3,d4));
|
||||
v_dependency * interval::join(v_dependency * d1, v_dependency * d2, v_dependency * d3, v_dependency * d4) {
|
||||
return m_manager.mk_join(m_manager.mk_join(d1, d2), m_manager.mk_join(d3,d4));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -318,7 +318,7 @@ interval & interval::operator*=(interval const & other) {
|
|||
v_dependency * d_d = other.m_upper_dep;
|
||||
|
||||
TRACE("interval_bug", tout << "operator*= " << *this << " " << other << "\n";);
|
||||
|
||||
|
||||
if (is_N()) {
|
||||
if (other.is_N()) {
|
||||
// x <= b <= 0, y <= d <= 0 --> b*d <= x*y
|
||||
|
@ -452,7 +452,7 @@ interval & interval::operator*=(interval const & other) {
|
|||
m_upper_dep = m_upper.is_infinite() ? 0 : join(b_d, d_d, a_d);
|
||||
}
|
||||
else {
|
||||
// 0 <= a <= x, 0 <= c <= y --> a*c <= x*y
|
||||
// 0 <= a <= x, 0 <= c <= y --> a*c <= x*y
|
||||
// x <= b, y <= d --> x*y <= b*d (uses the fact that x is pos (a is not negative) or y is pos (c is not negative))
|
||||
TRACE("interval_bug", tout << "(P, P)\n";);
|
||||
SASSERT(other.is_P());
|
||||
|
@ -467,7 +467,7 @@ interval & interval::operator*=(interval const & other) {
|
|||
}
|
||||
}
|
||||
TRACE("interval_bug", tout << "operator*= result: " << *this << "\n";);
|
||||
CTRACE("interval", !(!(contains_zero1 || contains_zero2) || contains_zero()),
|
||||
CTRACE("interval", !(!(contains_zero1 || contains_zero2) || contains_zero()),
|
||||
tout << "contains_zero1: " << contains_zero1 << ", contains_zero2: " << contains_zero2 << ", contains_zero(): " << contains_zero() << "\n";);
|
||||
SASSERT(!(contains_zero1 || contains_zero2) || contains_zero());
|
||||
return *this;
|
||||
|
@ -482,7 +482,7 @@ bool interval::contains_zero() const {
|
|||
tout << "m_upper.is_zero: " << m_upper.is_zero() << "\n";
|
||||
tout << "m_upper_open: " << m_upper_open << "\n";
|
||||
tout << "result: " << ((m_lower.is_neg() || (m_lower.is_zero() && !m_lower_open)) && (m_upper.is_pos() || (m_upper.is_zero() && !m_upper_open))) << "\n";);
|
||||
return
|
||||
return
|
||||
(m_lower.is_neg() || (m_lower.is_zero() && !m_lower_open)) &&
|
||||
(m_upper.is_pos() || (m_upper.is_zero() && !m_upper_open));
|
||||
}
|
||||
|
@ -510,7 +510,7 @@ interval & interval::inv() {
|
|||
ext_numeral new_upper;
|
||||
if (m_lower.is_zero()) {
|
||||
SASSERT(m_lower_open);
|
||||
ext_numeral plus_infinity(true);
|
||||
ext_numeral plus_infinity(true);
|
||||
new_upper = plus_infinity;
|
||||
}
|
||||
else {
|
||||
|
@ -595,7 +595,7 @@ void interval::expt(unsigned n) {
|
|||
else if (m_upper.is_neg()) {
|
||||
// [l, u]^n = [u^n, l^n] if u < 0
|
||||
// a <= x <= b < 0 --> x^n <= a^n (use lower and upper bound -- need the fact that x is negative)
|
||||
// x <= b < 0 --> b^n <= x^n
|
||||
// x <= b < 0 --> b^n <= x^n
|
||||
std::swap(m_lower, m_upper);
|
||||
std::swap(m_lower_open, m_upper_open);
|
||||
std::swap(m_lower_dep, m_upper_dep);
|
||||
|
@ -614,7 +614,7 @@ void interval::expt(unsigned n) {
|
|||
m_upper = m_lower;
|
||||
m_upper_open = m_lower_open;
|
||||
}
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : m_manager.mk_join(m_lower_dep, m_upper_dep);
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : m_manager.mk_join(m_lower_dep, m_upper_dep);
|
||||
m_lower = ext_numeral(0);
|
||||
m_lower_open = false;
|
||||
m_lower_dep = 0;
|
||||
|
|
|
@ -64,5 +64,6 @@ def_module_params(module_name='smt',
|
|||
('core.validate', BOOL, False, 'validate unsat core produced by SMT context'),
|
||||
('core.minimize', BOOL, False, 'minimize unsat core produced by SMT context'),
|
||||
('core.extend_patterns', BOOL, False, 'extend unsat core with literals that trigger (potential) quantifier instances'),
|
||||
('core.extend_patterns.max_distance', UINT, UINT_MAX, 'limits the distance of a pattern-extended unsat core')
|
||||
('core.extend_patterns.max_distance', UINT, UINT_MAX, 'limits the distance of a pattern-extended unsat core'),
|
||||
('core.extend_nonlocal_patterns', BOOL, False, 'extend unsat cores with literals that have quantifiers with patterns that contain symbols which are not in the quantifier\'s body')
|
||||
))
|
||||
|
|
|
@ -59,9 +59,9 @@ namespace smt {
|
|||
SASSERT(n->trans_reaches(n->get_root()));
|
||||
while (n) {
|
||||
if (Set)
|
||||
n->set_mark();
|
||||
n->set_mark2();
|
||||
else
|
||||
n->unset_mark();
|
||||
n->unset_mark2();
|
||||
n = n->m_trans.m_target;
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +84,7 @@ namespace smt {
|
|||
mark_enodes_in_trans<true>(n1);
|
||||
while (true) {
|
||||
SASSERT(n2);
|
||||
if (n2->is_marked()) {
|
||||
if (n2->is_marked2()) {
|
||||
mark_enodes_in_trans<false>(n1);
|
||||
return n2;
|
||||
}
|
||||
|
|
|
@ -30,6 +30,7 @@ namespace smt {
|
|||
index_set::iterator it = vars.begin(), end = vars.end();
|
||||
for (; it != end; ++it) {
|
||||
expr* e = bool_var2expr(*it);
|
||||
e = m_assumption2orig.find(e);
|
||||
premises.push_back(get_assignment(*it) != l_false ? e : m_manager.mk_not(e));
|
||||
}
|
||||
return mk_and(premises);
|
||||
|
@ -44,13 +45,14 @@ namespace smt {
|
|||
// - e is an equality between a variable and value that is to be fixed.
|
||||
// - e is a data-type recognizer of a variable that is to be fixed.
|
||||
//
|
||||
void context::extract_fixed_consequences(literal lit, obj_map<expr, expr*>& vars, index_set const& assumptions, expr_ref_vector& conseq) {
|
||||
void context::extract_fixed_consequences(literal lit, index_set const& assumptions, expr_ref_vector& conseq) {
|
||||
ast_manager& m = m_manager;
|
||||
datatype_util dt(m);
|
||||
expr* e1, *e2;
|
||||
expr_ref fml(m);
|
||||
if (lit == true_literal) return;
|
||||
expr* e = bool_var2expr(lit.var());
|
||||
TRACE("context", display(tout << mk_pp(e, m) << "\n"););
|
||||
index_set s;
|
||||
if (assumptions.contains(lit.var())) {
|
||||
s.insert(lit.var());
|
||||
|
@ -65,26 +67,32 @@ namespace smt {
|
|||
}
|
||||
tout << "\n";);
|
||||
bool found = false;
|
||||
if (vars.contains(e)) {
|
||||
if (m_var2val.contains(e)) {
|
||||
found = true;
|
||||
m_var2val.erase(e);
|
||||
e = m_var2orig.find(e);
|
||||
fml = lit.sign() ? m.mk_not(e) : e;
|
||||
vars.erase(e);
|
||||
}
|
||||
else if (!lit.sign() && m.is_eq(e, e1, e2)) {
|
||||
if (vars.contains(e2)) {
|
||||
std::swap(e1, e2);
|
||||
}
|
||||
if (vars.contains(e1) && m.is_value(e2)) {
|
||||
if (m_var2val.contains(e2) && m.is_value(e1)) {
|
||||
found = true;
|
||||
fml = e;
|
||||
vars.erase(e1);
|
||||
m_var2val.erase(e2);
|
||||
e2 = m_var2orig.find(e2);
|
||||
std::swap(e1, e2);
|
||||
fml = m.mk_eq(e1, e2);
|
||||
}
|
||||
else if (m_var2val.contains(e1) && m.is_value(e2)) {
|
||||
found = true;
|
||||
m_var2val.erase(e1);
|
||||
e1 = m_var2orig.find(e1);
|
||||
fml = m.mk_eq(e1, e2);
|
||||
}
|
||||
}
|
||||
else if (!lit.sign() && is_app(e) && dt.is_recognizer(to_app(e)->get_decl())) {
|
||||
if (vars.contains(to_app(e)->get_arg(0))) {
|
||||
if (m_var2val.contains(to_app(e)->get_arg(0))) {
|
||||
found = true;
|
||||
fml = m.mk_eq(to_app(e)->get_arg(0), m.mk_const(dt.get_recognizer_constructor(to_app(e)->get_decl())));
|
||||
vars.erase(to_app(e)->get_arg(0));
|
||||
m_var2val.erase(to_app(e)->get_arg(0));
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
|
@ -94,6 +102,7 @@ namespace smt {
|
|||
}
|
||||
|
||||
void context::justify(literal lit, index_set& s) {
|
||||
ast_manager& m = m_manager;
|
||||
b_justification js = get_justification(lit.var());
|
||||
switch (js.get_kind()) {
|
||||
case b_justification::CLAUSE: {
|
||||
|
@ -119,6 +128,9 @@ namespace smt {
|
|||
literal_vector literals;
|
||||
m_conflict_resolution->justification2literals(js.get_justification(), literals);
|
||||
for (unsigned j = 0; j < literals.size(); ++j) {
|
||||
if (!m_antecedents.contains(literals[j].var())) {
|
||||
TRACE("context", tout << literals[j] << " " << mk_pp(bool_var2expr(literals[j].var()), m) << "\n";);
|
||||
}
|
||||
s |= m_antecedents.find(literals[j].var());
|
||||
}
|
||||
break;
|
||||
|
@ -126,13 +138,13 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
|
||||
void context::extract_fixed_consequences(unsigned& start, obj_map<expr, expr*>& vars, index_set const& assumptions, expr_ref_vector& conseq) {
|
||||
void context::extract_fixed_consequences(unsigned& start, index_set const& assumptions, expr_ref_vector& conseq) {
|
||||
pop_to_search_lvl();
|
||||
SASSERT(!inconsistent());
|
||||
literal_vector const& lits = assigned_literals();
|
||||
unsigned sz = lits.size();
|
||||
for (unsigned i = start; i < sz; ++i) {
|
||||
extract_fixed_consequences(lits[i], vars, assumptions, conseq);
|
||||
extract_fixed_consequences(lits[i], assumptions, conseq);
|
||||
}
|
||||
start = sz;
|
||||
SASSERT(!inconsistent());
|
||||
|
@ -150,10 +162,10 @@ namespace smt {
|
|||
// rules out as many non-fixed variables as possible.
|
||||
//
|
||||
|
||||
unsigned context::delete_unfixed(obj_map<expr, expr*>& var2val, expr_ref_vector& unfixed) {
|
||||
unsigned context::delete_unfixed(expr_ref_vector& unfixed) {
|
||||
ast_manager& m = m_manager;
|
||||
ptr_vector<expr> to_delete;
|
||||
obj_map<expr,expr*>::iterator it = var2val.begin(), end = var2val.end();
|
||||
obj_map<expr,expr*>::iterator it = m_var2val.begin(), end = m_var2val.end();
|
||||
for (; it != end; ++it) {
|
||||
expr* k = it->m_key;
|
||||
expr* v = it->m_value;
|
||||
|
@ -189,7 +201,7 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
for (unsigned i = 0; i < to_delete.size(); ++i) {
|
||||
var2val.remove(to_delete[i]);
|
||||
m_var2val.remove(to_delete[i]);
|
||||
unfixed.push_back(to_delete[i]);
|
||||
}
|
||||
return to_delete.size();
|
||||
|
@ -202,12 +214,12 @@ namespace smt {
|
|||
// Add a clause to short-circuit the congruence justifications for
|
||||
// next rounds.
|
||||
//
|
||||
unsigned context::extract_fixed_eqs(obj_map<expr, expr*>& var2val, expr_ref_vector& conseq) {
|
||||
unsigned context::extract_fixed_eqs(expr_ref_vector& conseq) {
|
||||
TRACE("context", tout << "extract fixed consequences\n";);
|
||||
ast_manager& m = m_manager;
|
||||
ptr_vector<expr> to_delete;
|
||||
expr_ref fml(m), eq(m);
|
||||
obj_map<expr,expr*>::iterator it = var2val.begin(), end = var2val.end();
|
||||
obj_map<expr,expr*>::iterator it = m_var2val.begin(), end = m_var2val.end();
|
||||
for (; it != end; ++it) {
|
||||
expr* k = it->m_key;
|
||||
expr* v = it->m_value;
|
||||
|
@ -220,7 +232,7 @@ namespace smt {
|
|||
s |= m_antecedents.find(literals[i].var());
|
||||
}
|
||||
|
||||
fml = m.mk_eq(k, v);
|
||||
fml = m.mk_eq(m_var2orig.find(k), v);
|
||||
fml = m.mk_implies(antecedent2fml(s), fml);
|
||||
conseq.push_back(fml);
|
||||
to_delete.push_back(k);
|
||||
|
@ -235,16 +247,20 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
for (unsigned i = 0; i < to_delete.size(); ++i) {
|
||||
var2val.remove(to_delete[i]);
|
||||
m_var2val.remove(to_delete[i]);
|
||||
}
|
||||
return to_delete.size();
|
||||
}
|
||||
|
||||
literal context::mk_diseq(expr* e, expr* val) {
|
||||
ast_manager& m = m_manager;
|
||||
if (m.is_bool(e)) {
|
||||
if (m.is_bool(e) && b_internalized(e)) {
|
||||
return literal(get_bool_var(e), m.is_true(val));
|
||||
}
|
||||
else if (m.is_bool(e)) {
|
||||
internalize_formula(e, false);
|
||||
return literal(get_bool_var(e), !m.is_true(val));
|
||||
}
|
||||
else {
|
||||
expr_ref eq(mk_eq_atom(e, val), m);
|
||||
internalize_formula(eq, false);
|
||||
|
@ -252,43 +268,85 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
|
||||
lbool context::get_consequences(expr_ref_vector const& assumptions,
|
||||
expr_ref_vector const& vars,
|
||||
lbool context::get_consequences(expr_ref_vector const& assumptions0,
|
||||
expr_ref_vector const& vars0,
|
||||
expr_ref_vector& conseq,
|
||||
expr_ref_vector& unfixed) {
|
||||
|
||||
m_antecedents.reset();
|
||||
m_antecedents.insert(true_literal.var(), index_set());
|
||||
pop_to_base_lvl();
|
||||
ast_manager& m = m_manager;
|
||||
expr_ref_vector vars(m), assumptions(m);
|
||||
m_var2val.reset();
|
||||
m_var2orig.reset();
|
||||
m_assumption2orig.reset();
|
||||
bool pushed = false;
|
||||
for (unsigned i = 0; i < vars0.size(); ++i) {
|
||||
expr* v = vars0[i];
|
||||
if (is_uninterp_const(v)) {
|
||||
vars.push_back(v);
|
||||
m_var2orig.insert(v, v);
|
||||
}
|
||||
else {
|
||||
if (!pushed) {
|
||||
pushed = true;
|
||||
push();
|
||||
}
|
||||
expr_ref c(m.mk_fresh_const("v", m.get_sort(v)), m);
|
||||
expr_ref eq(m.mk_eq(c, v), m);
|
||||
assert_expr(eq);
|
||||
vars.push_back(c);
|
||||
m_var2orig.insert(c, v);
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < assumptions0.size(); ++i) {
|
||||
expr* a = assumptions0[i];
|
||||
if (is_uninterp_const(a)) {
|
||||
assumptions.push_back(a);
|
||||
m_assumption2orig.insert(a, a);
|
||||
}
|
||||
else {
|
||||
if (!pushed) {
|
||||
pushed = true;
|
||||
push();
|
||||
}
|
||||
expr_ref c(m.mk_fresh_const("a", m.get_sort(a)), m);
|
||||
expr_ref eq(m.mk_eq(c, a), m);
|
||||
assert_expr(eq);
|
||||
assumptions.push_back(c);
|
||||
m_assumption2orig.insert(c, a);
|
||||
}
|
||||
}
|
||||
lbool is_sat = check(assumptions.size(), assumptions.c_ptr());
|
||||
if (is_sat != l_true) {
|
||||
TRACE("context", tout << is_sat << "\n";);
|
||||
if (pushed) pop(1);
|
||||
return is_sat;
|
||||
}
|
||||
|
||||
obj_map<expr, expr*> var2val;
|
||||
index_set _assumptions;
|
||||
for (unsigned i = 0; i < assumptions.size(); ++i) {
|
||||
_assumptions.insert(get_literal(assumptions[i]).var());
|
||||
_assumptions.insert(get_literal(assumptions[i].get()).var());
|
||||
}
|
||||
model_ref mdl;
|
||||
get_model(mdl);
|
||||
ast_manager& m = m_manager;
|
||||
expr_ref_vector trail(m);
|
||||
model_evaluator eval(*mdl.get());
|
||||
expr_ref val(m);
|
||||
TRACE("context", model_pp(tout, *mdl););
|
||||
for (unsigned i = 0; i < vars.size(); ++i) {
|
||||
eval(vars[i], val);
|
||||
eval(vars[i].get(), val);
|
||||
if (m.is_value(val)) {
|
||||
trail.push_back(val);
|
||||
var2val.insert(vars[i], val);
|
||||
m_var2val.insert(vars[i].get(), val);
|
||||
}
|
||||
else {
|
||||
unfixed.push_back(vars[i]);
|
||||
unfixed.push_back(vars[i].get());
|
||||
}
|
||||
}
|
||||
unsigned num_units = 0;
|
||||
extract_fixed_consequences(num_units, var2val, _assumptions, conseq);
|
||||
extract_fixed_consequences(num_units, _assumptions, conseq);
|
||||
app_ref eq(m);
|
||||
TRACE("context",
|
||||
tout << "vars: " << vars.size() << "\n";
|
||||
|
@ -298,11 +356,12 @@ namespace smt {
|
|||
unsigned num_fixed_eqs = 0;
|
||||
unsigned chunk_size = 100;
|
||||
|
||||
while (!var2val.empty()) {
|
||||
obj_map<expr,expr*>::iterator it = var2val.begin(), end = var2val.end();
|
||||
while (!m_var2val.empty()) {
|
||||
obj_map<expr,expr*>::iterator it = m_var2val.begin(), end = m_var2val.end();
|
||||
unsigned num_vars = 0;
|
||||
for (; it != end && num_vars < chunk_size; ++it) {
|
||||
if (get_cancel_flag()) {
|
||||
if (pushed) pop(1);
|
||||
return l_undef;
|
||||
}
|
||||
expr* e = it->m_key;
|
||||
|
@ -332,6 +391,7 @@ namespace smt {
|
|||
while (true) {
|
||||
is_sat = bounded_search();
|
||||
if (is_sat != l_true && m_last_search_failure != OK) {
|
||||
if (pushed) pop(1);
|
||||
return is_sat;
|
||||
}
|
||||
if (is_sat == l_undef) {
|
||||
|
@ -347,18 +407,21 @@ namespace smt {
|
|||
m_not_l = null_literal;
|
||||
}
|
||||
if (is_sat == l_true) {
|
||||
delete_unfixed(var2val, unfixed);
|
||||
delete_unfixed(unfixed);
|
||||
}
|
||||
extract_fixed_consequences(num_units, var2val, _assumptions, conseq);
|
||||
num_fixed_eqs += extract_fixed_eqs(var2val, conseq);
|
||||
IF_VERBOSE(1, display_consequence_progress(verbose_stream(), num_iterations, var2val.size(), conseq.size(),
|
||||
extract_fixed_consequences(num_units, _assumptions, conseq);
|
||||
num_fixed_eqs += extract_fixed_eqs(conseq);
|
||||
IF_VERBOSE(1, display_consequence_progress(verbose_stream(), num_iterations, m_var2val.size(), conseq.size(),
|
||||
unfixed.size(), num_fixed_eqs););
|
||||
TRACE("context", display_consequence_progress(tout, num_iterations, var2val.size(), conseq.size(),
|
||||
TRACE("context", display_consequence_progress(tout, num_iterations, m_var2val.size(), conseq.size(),
|
||||
unfixed.size(), num_fixed_eqs););
|
||||
}
|
||||
|
||||
end_search();
|
||||
DEBUG_CODE(validate_consequences(assumptions, vars, conseq, unfixed););
|
||||
if (pushed) {
|
||||
pop(1);
|
||||
}
|
||||
return l_true;
|
||||
}
|
||||
|
||||
|
|
|
@ -304,7 +304,6 @@ namespace smt {
|
|||
TRACE("assign_core", tout << (decision?"decision: ":"propagating: ") << l << " ";
|
||||
display_literal_verbose(tout, l); tout << " level: " << m_scope_lvl << "\n";
|
||||
display(tout, j););
|
||||
SASSERT(l.var() < static_cast<int>(m_b_internalized_stack.size()));
|
||||
m_assigned_literals.push_back(l);
|
||||
m_assignment[l.index()] = l_true;
|
||||
m_assignment[(~l).index()] = l_false;
|
||||
|
@ -319,14 +318,23 @@ namespace smt {
|
|||
d.m_phase_available = true;
|
||||
d.m_phase = !l.sign();
|
||||
TRACE("phase_selection", tout << "saving phase, is_pos: " << d.m_phase << " l: " << l << "\n";);
|
||||
|
||||
TRACE("relevancy",
|
||||
tout << "is_atom: " << d.is_atom() << " is relevant: " << is_relevant_core(bool_var2expr(l.var())) << "\n";);
|
||||
if (d.is_atom() && (m_fparams.m_relevancy_lvl == 0 || (m_fparams.m_relevancy_lvl == 1 && !d.is_quantifier()) || is_relevant_core(bool_var2expr(l.var()))))
|
||||
tout << "is_atom: " << d.is_atom() << " is relevant: " << is_relevant_core(l) << "\n";);
|
||||
if (d.is_atom() && (m_fparams.m_relevancy_lvl == 0 || (m_fparams.m_relevancy_lvl == 1 && !d.is_quantifier()) || is_relevant_core(l)))
|
||||
m_atom_propagation_queue.push_back(l);
|
||||
|
||||
if (m_manager.has_trace_stream())
|
||||
trace_assign(l, j, decision);
|
||||
m_case_split_queue->assign_lit_eh(l);
|
||||
|
||||
// a unit is asserted at search level. Mark it as relevant.
|
||||
// this addresses bug... where a literal becomes fixed to true (false)
|
||||
// as a conflict gets assigned misses relevancy (and quantifier instantiation).
|
||||
//
|
||||
if (false && !decision && relevancy() && at_search_level() && !is_relevant_core(l)) {
|
||||
mark_as_relevant(l);
|
||||
}
|
||||
}
|
||||
|
||||
bool context::bcp() {
|
||||
|
@ -1634,7 +1642,7 @@ namespace smt {
|
|||
m_atom_propagation_queue.push_back(literal(v, val == l_false));
|
||||
}
|
||||
}
|
||||
TRACE("propagate_relevancy", tout << "marking as relevant:\n" << mk_bounded_pp(n, m_manager) << "\n";);
|
||||
TRACE("propagate_relevancy", tout << "marking as relevant:\n" << mk_bounded_pp(n, m_manager) << " " << m_scope_lvl << "\n";);
|
||||
#ifndef SMTCOMP
|
||||
m_case_split_queue->relevant_eh(n);
|
||||
#endif
|
||||
|
@ -3073,11 +3081,11 @@ namespace smt {
|
|||
m_assumptions.reset();
|
||||
}
|
||||
|
||||
void context::mk_unsat_core() {
|
||||
lbool context::mk_unsat_core() {
|
||||
SASSERT(inconsistent());
|
||||
if (!tracking_assumptions()) {
|
||||
SASSERT(m_assumptions.empty());
|
||||
return;
|
||||
return l_false;
|
||||
}
|
||||
uint_set already_found_assumptions;
|
||||
literal_vector::const_iterator it = m_conflict_resolution->begin_unsat_core();
|
||||
|
@ -3102,7 +3110,17 @@ namespace smt {
|
|||
for (unsigned i = 0; i < sz; i++) {
|
||||
tout << mk_pp(m_unsat_core.get(i), m_manager) << "\n";
|
||||
});
|
||||
validate_unsat_core();
|
||||
validate_unsat_core();
|
||||
// theory validation of unsat core
|
||||
ptr_vector<theory>::iterator th_it = m_theory_set.begin();
|
||||
ptr_vector<theory>::iterator th_end = m_theory_set.end();
|
||||
for (; th_it != th_end; ++th_it) {
|
||||
lbool theory_result = (*th_it)->validate_unsat_core(m_unsat_core);
|
||||
if (theory_result == l_undef) {
|
||||
return l_undef;
|
||||
}
|
||||
}
|
||||
return l_false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -3145,6 +3163,14 @@ namespace smt {
|
|||
SASSERT(m_scope_lvl == 0);
|
||||
SASSERT(!m_setup.already_configured());
|
||||
setup_context(m_fparams.m_auto_config);
|
||||
|
||||
expr_ref_vector theory_assumptions(m_manager);
|
||||
add_theory_assumptions(theory_assumptions);
|
||||
if (!theory_assumptions.empty()) {
|
||||
TRACE("search", tout << "Adding theory assumptions to context" << std::endl;);
|
||||
return check(theory_assumptions.size(), theory_assumptions.c_ptr(), reset_cancel, true);
|
||||
}
|
||||
|
||||
internalize_assertions();
|
||||
lbool r = l_undef;
|
||||
if (m_asserted_formulas.inconsistent()) {
|
||||
|
@ -3206,7 +3232,15 @@ namespace smt {
|
|||
(*it)->setup();
|
||||
}
|
||||
|
||||
lbool context::check(unsigned num_assumptions, expr * const * assumptions, bool reset_cancel) {
|
||||
void context::add_theory_assumptions(expr_ref_vector & theory_assumptions) {
|
||||
ptr_vector<theory>::iterator it = m_theory_set.begin();
|
||||
ptr_vector<theory>::iterator end = m_theory_set.end();
|
||||
for (; it != end; ++it) {
|
||||
(*it)->add_theory_assumptions(theory_assumptions);
|
||||
}
|
||||
}
|
||||
|
||||
lbool context::check(unsigned ext_num_assumptions, expr * const * ext_assumptions, bool reset_cancel, bool already_did_theory_assumptions) {
|
||||
m_stats.m_num_checks++;
|
||||
TRACE("check_bug", tout << "STARTING check(num_assumptions, assumptions)\n";
|
||||
tout << "inconsistent: " << inconsistent() << ", m_unsat_core.empty(): " << m_unsat_core.empty() << "\n";
|
||||
|
@ -3217,6 +3251,15 @@ namespace smt {
|
|||
m_unsat_core.reset();
|
||||
if (!check_preamble(reset_cancel))
|
||||
return l_undef;
|
||||
|
||||
expr_ref_vector all_assumptions(m_manager, ext_num_assumptions, ext_assumptions);
|
||||
if (!already_did_theory_assumptions) {
|
||||
add_theory_assumptions(all_assumptions);
|
||||
}
|
||||
|
||||
unsigned num_assumptions = all_assumptions.size();
|
||||
expr * const * assumptions = all_assumptions.c_ptr();
|
||||
|
||||
if (!validate_assumptions(num_assumptions, assumptions))
|
||||
return l_undef;
|
||||
TRACE("check_bug", tout << "inconsistent: " << inconsistent() << ", m_unsat_core.empty(): " << m_unsat_core.empty() << "\n";);
|
||||
|
@ -3240,13 +3283,21 @@ namespace smt {
|
|||
TRACE("after_internalization", display(tout););
|
||||
if (inconsistent()) {
|
||||
VERIFY(!resolve_conflict()); // build the proof
|
||||
mk_unsat_core();
|
||||
r = l_false;
|
||||
lbool result = mk_unsat_core();
|
||||
if (result == l_undef) {
|
||||
r = l_undef;
|
||||
} else {
|
||||
r = l_false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
r = search();
|
||||
if (r == l_false)
|
||||
mk_unsat_core();
|
||||
if (r == l_false) {
|
||||
lbool result = mk_unsat_core();
|
||||
if (result == l_undef) {
|
||||
r = l_undef;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -3750,6 +3801,7 @@ namespace smt {
|
|||
// I invoke pop_scope_core instead of pop_scope because I don't want
|
||||
// to reset cached generations... I need them to rebuild the literals
|
||||
// of the new conflict clause.
|
||||
if (relevancy()) record_relevancy(num_lits, lits);
|
||||
unsigned num_bool_vars = pop_scope_core(m_scope_lvl - new_lvl);
|
||||
SASSERT(m_scope_lvl == new_lvl);
|
||||
// the logical context may still be in conflict after
|
||||
|
@ -3781,6 +3833,7 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (relevancy()) restore_relevancy(num_lits, lits);
|
||||
// Resetting the cache manually because I did not invoke pop_scope, but pop_scope_core
|
||||
reset_cache_generation();
|
||||
TRACE("resolve_conflict_bug",
|
||||
|
@ -3863,6 +3916,28 @@ namespace smt {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
\brief we record and restore relevancy information for literals in conflict clauses.
|
||||
A literal may have been marked relevant within the scope that gets popped during
|
||||
conflict resolution. In this case, the literal is no longer marked as relevant after
|
||||
the pop. This can cause quantifier instantiation to miss relevant triggers and thereby
|
||||
cause incmpleteness.
|
||||
*/
|
||||
void context::record_relevancy(unsigned n, literal const* lits) {
|
||||
m_relevant_conflict_literals.reset();
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
m_relevant_conflict_literals.push_back(is_relevant(lits[i]));
|
||||
}
|
||||
}
|
||||
|
||||
void context::restore_relevancy(unsigned n, literal const* lits) {
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
if (m_relevant_conflict_literals[i] && !is_relevant(lits[i])) {
|
||||
mark_as_relevant(lits[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void context::get_relevant_labels(expr* cnstr, buffer<symbol> & result) {
|
||||
if (m_fparams.m_check_at_labels) {
|
||||
|
@ -4195,42 +4270,21 @@ namespace smt {
|
|||
for (unsigned i = 0; 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;
|
||||
SASSERT(q->get_num_patterns() == 1);
|
||||
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);
|
||||
SASSERT(is_app(fn));
|
||||
func_decl* f = to_app(fn)->get_decl();
|
||||
expr* eq = q->get_expr();
|
||||
expr_ref body(m);
|
||||
if (is_fun_def(fn, q->get_expr(), body)) {
|
||||
func_interp* fi = alloc(func_interp, m, f->get_arity());
|
||||
fi->set_else(body);
|
||||
m_model->register_decl(f, fi);
|
||||
}
|
||||
func_interp* fi = alloc(func_interp, m, f->get_arity());
|
||||
fi->set_else(body);
|
||||
m_model->register_decl(f, fi);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool context::is_fun_def(expr* f, expr* body, expr_ref& result) {
|
||||
expr* t1, *t2, *t3;
|
||||
if (m_manager.is_eq(body, t1, t2) || m_manager.is_iff(body, t1, t2)) {
|
||||
if (t1 == f) return result = t2, true;
|
||||
if (t2 == f) return result = t1, true;
|
||||
return false;
|
||||
}
|
||||
if (m_manager.is_ite(body, t1, t2, t3)) {
|
||||
expr_ref body1(m_manager), body2(m_manager);
|
||||
if (is_fun_def(f, t2, body1) && is_fun_def(f, t3, body2)) {
|
||||
// f is not free in t1
|
||||
result = m_manager.mk_ite(t1, body1, body2);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1066,7 +1066,9 @@ namespace smt {
|
|||
|
||||
void reset_assumptions();
|
||||
|
||||
void mk_unsat_core();
|
||||
void add_theory_assumptions(expr_ref_vector & theory_assumptions);
|
||||
|
||||
lbool mk_unsat_core();
|
||||
|
||||
void validate_unsat_core();
|
||||
|
||||
|
@ -1110,6 +1112,10 @@ namespace smt {
|
|||
|
||||
bool is_relevant_core(expr * n) const { return m_relevancy_propagator->is_relevant(n); }
|
||||
|
||||
svector<bool> m_relevant_conflict_literals;
|
||||
void record_relevancy(unsigned n, literal const* lits);
|
||||
void restore_relevancy(unsigned n, literal const* lits);
|
||||
|
||||
public:
|
||||
// event handler for relevancy_propagator class
|
||||
void relevant_eh(expr * n);
|
||||
|
@ -1131,6 +1137,10 @@ namespace smt {
|
|||
return is_relevant(l.var());
|
||||
}
|
||||
|
||||
bool is_relevant_core(literal l) const {
|
||||
return is_relevant_core(bool_var2expr(l.var()));
|
||||
}
|
||||
|
||||
void mark_as_relevant(expr * n) { m_relevancy_propagator->mark_as_relevant(n); m_relevancy_propagator->propagate(); }
|
||||
|
||||
void mark_as_relevant(enode * n) { mark_as_relevant(n->get_owner()); }
|
||||
|
@ -1166,8 +1176,6 @@ namespace smt {
|
|||
|
||||
void add_rec_funs_to_model();
|
||||
|
||||
bool is_fun_def(expr* f, expr* q, expr_ref& body);
|
||||
|
||||
public:
|
||||
bool can_propagate() const;
|
||||
|
||||
|
@ -1378,14 +1386,17 @@ namespace smt {
|
|||
typedef hashtable<unsigned, u_hash, u_eq> index_set;
|
||||
//typedef uint_set index_set;
|
||||
u_map<index_set> m_antecedents;
|
||||
void extract_fixed_consequences(literal lit, obj_map<expr, expr*>& var2val, index_set const& assumptions, expr_ref_vector& conseq);
|
||||
void extract_fixed_consequences(unsigned& idx, obj_map<expr, expr*>& var2val, index_set const& assumptions, expr_ref_vector& conseq);
|
||||
obj_map<expr, expr*> m_var2orig;
|
||||
obj_map<expr, expr*> m_assumption2orig;
|
||||
obj_map<expr, expr*> m_var2val;
|
||||
void extract_fixed_consequences(literal lit, index_set const& assumptions, expr_ref_vector& conseq);
|
||||
void extract_fixed_consequences(unsigned& idx, index_set const& assumptions, expr_ref_vector& conseq);
|
||||
|
||||
void display_consequence_progress(std::ostream& out, unsigned it, unsigned nv, unsigned fixed, unsigned unfixed, unsigned eq);
|
||||
|
||||
unsigned delete_unfixed(obj_map<expr, expr*>& var2val, expr_ref_vector& unfixed);
|
||||
unsigned delete_unfixed(expr_ref_vector& unfixed);
|
||||
|
||||
unsigned extract_fixed_eqs(obj_map<expr, expr*>& var2val, expr_ref_vector& conseq);
|
||||
unsigned extract_fixed_eqs(expr_ref_vector& conseq);
|
||||
|
||||
expr_ref antecedent2fml(index_set const& ante);
|
||||
|
||||
|
@ -1442,7 +1453,7 @@ namespace smt {
|
|||
|
||||
void pop(unsigned num_scopes);
|
||||
|
||||
lbool check(unsigned num_assumptions = 0, expr * const * assumptions = 0, bool reset_cancel = true);
|
||||
lbool check(unsigned num_assumptions = 0, expr * const * assumptions = 0, bool reset_cancel = true, bool already_did_theory_assumptions = false);
|
||||
|
||||
lbool get_consequences(expr_ref_vector const& assumptions, expr_ref_vector const& vars, expr_ref_vector& conseq, expr_ref_vector& unfixed);
|
||||
|
||||
|
|
|
@ -433,6 +433,9 @@ namespace smt {
|
|||
if (!is_ground(n)) {
|
||||
continue;
|
||||
}
|
||||
if (is_quantifier(n) && m.is_rec_fun_def(to_quantifier(n))) {
|
||||
continue;
|
||||
}
|
||||
switch (get_assignment(*it)) {
|
||||
case l_undef:
|
||||
break;
|
||||
|
|
|
@ -246,13 +246,15 @@ namespace smt {
|
|||
|
||||
simple_justification::simple_justification(region & r, unsigned num_lits, literal const * lits):
|
||||
m_num_literals(num_lits) {
|
||||
m_literals = new (r) literal[num_lits];
|
||||
memcpy(m_literals, lits, sizeof(literal) * num_lits);
|
||||
if (num_lits != 0) {
|
||||
m_literals = new (r) literal[num_lits];
|
||||
memcpy(m_literals, lits, sizeof(literal) * num_lits);
|
||||
#ifdef Z3DEBUG
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
SASSERT(lits[i] != null_literal);
|
||||
}
|
||||
for (unsigned i = 0; i < num_lits; i++) {
|
||||
SASSERT(lits[i] != null_literal);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void simple_justification::get_antecedents(conflict_resolution & cr) {
|
||||
|
|
|
@ -316,9 +316,9 @@ namespace smt {
|
|||
return false;
|
||||
}
|
||||
|
||||
bool model_checker::check_rec_fun(quantifier* q) {
|
||||
bool model_checker::check_rec_fun(quantifier* q, bool strict_rec_fun) {
|
||||
TRACE("model_checker", tout << mk_pp(q, m) << "\n";);
|
||||
SASSERT(q->get_num_patterns() == 1);
|
||||
SASSERT(q->get_num_patterns() == 2); // first pattern is the function, second is the body.
|
||||
expr* fn = to_app(q->get_pattern(0))->get_arg(0);
|
||||
SASSERT(is_app(fn));
|
||||
func_decl* f = to_app(fn)->get_decl();
|
||||
|
@ -340,7 +340,7 @@ namespace smt {
|
|||
}
|
||||
sub(q->get_expr(), num_decls, args.c_ptr(), tmp);
|
||||
m_curr_model->eval(tmp, result, true);
|
||||
if (m.is_false(result)) {
|
||||
if (strict_rec_fun ? !m.is_true(result) : m.is_false(result)) {
|
||||
add_instance(q, args, 0);
|
||||
return false;
|
||||
}
|
||||
|
@ -365,10 +365,10 @@ namespace smt {
|
|||
|
||||
bool model_checker::check(proto_model * md, obj_map<enode, app *> const & root2value) {
|
||||
SASSERT(md != 0);
|
||||
|
||||
m_root2value = &root2value;
|
||||
ptr_vector<quantifier>::const_iterator it = m_qm->begin_quantifiers();
|
||||
ptr_vector<quantifier>::const_iterator end = m_qm->end_quantifiers();
|
||||
if (it == end)
|
||||
|
||||
if (m_qm->num_quantifiers() == 0)
|
||||
return true;
|
||||
|
||||
if (m_iteration_idx >= m_params.m_mbqi_max_iterations) {
|
||||
|
@ -393,6 +393,36 @@ namespace smt {
|
|||
bool found_relevant = false;
|
||||
unsigned num_failures = 0;
|
||||
|
||||
check_quantifiers(false, found_relevant, num_failures);
|
||||
|
||||
|
||||
if (found_relevant)
|
||||
m_iteration_idx++;
|
||||
|
||||
TRACE("model_checker", tout << "model after check:\n"; model_pp(tout, *md););
|
||||
TRACE("model_checker", tout << "model checker result: " << (num_failures == 0) << "\n";);
|
||||
m_max_cexs += m_params.m_mbqi_max_cexs;
|
||||
|
||||
if (num_failures == 0 && !m_context->validate_model()) {
|
||||
num_failures = 1;
|
||||
// this time force expanding recursive function definitions
|
||||
// that are not forced true in the current model.
|
||||
check_quantifiers(true, found_relevant, num_failures);
|
||||
}
|
||||
if (num_failures == 0)
|
||||
m_curr_model->cleanup();
|
||||
if (m_params.m_mbqi_trace) {
|
||||
if (num_failures == 0)
|
||||
verbose_stream() << "(smt.mbqi :succeeded true)\n";
|
||||
else
|
||||
verbose_stream() << "(smt.mbqi :num-failures " << num_failures << ")\n";
|
||||
}
|
||||
return num_failures == 0;
|
||||
}
|
||||
|
||||
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;
|
||||
|
@ -406,7 +436,7 @@ namespace smt {
|
|||
}
|
||||
found_relevant = true;
|
||||
if (m.is_rec_fun_def(q)) {
|
||||
if (!check_rec_fun(q)) {
|
||||
if (!check_rec_fun(q, strict_rec_fun)) {
|
||||
TRACE("model_checker", tout << "checking recursive function failed\n";);
|
||||
num_failures++;
|
||||
}
|
||||
|
@ -420,26 +450,6 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (found_relevant)
|
||||
m_iteration_idx++;
|
||||
|
||||
TRACE("model_checker", tout << "model after check:\n"; model_pp(tout, *md););
|
||||
TRACE("model_checker", tout << "model checker result: " << (num_failures == 0) << "\n";);
|
||||
m_max_cexs += m_params.m_mbqi_max_cexs;
|
||||
|
||||
if (num_failures == 0 && !m_context->validate_model()) {
|
||||
num_failures = 1;
|
||||
}
|
||||
if (num_failures == 0)
|
||||
m_curr_model->cleanup();
|
||||
if (m_params.m_mbqi_trace) {
|
||||
if (num_failures == 0)
|
||||
verbose_stream() << "(smt.mbqi :succeeded true)\n";
|
||||
else
|
||||
verbose_stream() << "(smt.mbqi :num-failures " << num_failures << ")\n";
|
||||
}
|
||||
return num_failures == 0;
|
||||
}
|
||||
|
||||
void model_checker::init_search_eh() {
|
||||
|
|
|
@ -59,7 +59,8 @@ namespace smt {
|
|||
void assert_neg_q_m(quantifier * q, expr_ref_vector & sks);
|
||||
bool add_blocking_clause(model * cex, expr_ref_vector & sks);
|
||||
bool check(quantifier * q);
|
||||
bool check_rec_fun(quantifier* q);
|
||||
bool check_rec_fun(quantifier* q, bool strict_rec_fun);
|
||||
void check_quantifiers(bool strict_rec_fun, bool& found_relevant, unsigned& num_failures);
|
||||
|
||||
struct instance {
|
||||
quantifier * m_q;
|
||||
|
|
|
@ -52,8 +52,9 @@ namespace smt {
|
|||
m_qi_queue.setup();
|
||||
}
|
||||
|
||||
bool has_trace_stream() const { return m_context.get_manager().has_trace_stream(); }
|
||||
std::ostream & trace_stream() { return m_context.get_manager().trace_stream(); }
|
||||
ast_manager& m() const { return m_context.get_manager(); }
|
||||
bool has_trace_stream() const { return m().has_trace_stream(); }
|
||||
std::ostream & trace_stream() { return m().trace_stream(); }
|
||||
|
||||
quantifier_stat * get_stat(quantifier * q) const {
|
||||
return m_quantifier_stat.find(q);
|
||||
|
@ -110,8 +111,9 @@ namespace smt {
|
|||
unsigned max_top_generation,
|
||||
ptr_vector<enode> & used_enodes) {
|
||||
max_generation = std::max(max_generation, get_generation(q));
|
||||
if (m_num_instances > m_params.m_qi_max_instances)
|
||||
if (m_num_instances > m_params.m_qi_max_instances) {
|
||||
return false;
|
||||
}
|
||||
get_stat(q)->update_max_generation(max_generation);
|
||||
fingerprint * f = m_context.add_fingerprint(q, q->get_id(), num_bindings, bindings);
|
||||
if (f) {
|
||||
|
@ -132,9 +134,17 @@ namespace smt {
|
|||
}
|
||||
m_qi_queue.insert(f, pat, max_generation, min_top_generation, max_top_generation); // TODO
|
||||
m_num_instances++;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
TRACE("quantifier",
|
||||
tout << mk_pp(q, m()) << " ";
|
||||
for (unsigned i = 0; i < num_bindings; ++i) {
|
||||
tout << mk_pp(bindings[i]->get_owner(), m()) << " ";
|
||||
}
|
||||
tout << "\n";
|
||||
tout << "inserted: " << (f != 0) << "\n";
|
||||
);
|
||||
|
||||
return f != 0;
|
||||
}
|
||||
|
||||
void init_search_eh() {
|
||||
|
@ -186,7 +196,7 @@ namespace smt {
|
|||
}
|
||||
|
||||
bool check_quantifier(quantifier* q) {
|
||||
return m_context.is_relevant(q) && m_context.get_assignment(q) == l_true; // && !m_context.get_manager().is_rec_fun_def(q);
|
||||
return m_context.is_relevant(q) && m_context.get_assignment(q) == l_true; // && !m().is_rec_fun_def(q);
|
||||
}
|
||||
|
||||
bool quick_check_quantifiers() {
|
||||
|
@ -387,6 +397,10 @@ namespace smt {
|
|||
return m_imp->m_quantifiers.end();
|
||||
}
|
||||
|
||||
unsigned quantifier_manager::num_quantifiers() const {
|
||||
return m_imp->m_quantifiers.size();
|
||||
}
|
||||
|
||||
// The default plugin uses E-matching, MBQI and quick-checker
|
||||
class default_qm_plugin : public quantifier_manager_plugin {
|
||||
quantifier_manager * m_qm;
|
||||
|
@ -501,13 +515,13 @@ namespace smt {
|
|||
SASSERT(m_context->get_manager().is_pattern(mp));
|
||||
bool unary = (mp->get_num_args() == 1);
|
||||
if (!unary && j >= num_eager_multi_patterns) {
|
||||
TRACE("assign_quantifier", tout << "delaying (too many multipatterns):\n" << mk_ismt2_pp(mp, m_context->get_manager()) << "\n"
|
||||
TRACE("quantifier", tout << "delaying (too many multipatterns):\n" << mk_ismt2_pp(mp, m_context->get_manager()) << "\n"
|
||||
<< "j: " << j << " unary: " << unary << " m_params.m_qi_max_eager_multipatterns: " << m_fparams->m_qi_max_eager_multipatterns
|
||||
<< " num_eager_multi_patterns: " << num_eager_multi_patterns << "\n";);
|
||||
m_lazy_mam->add_pattern(q, mp);
|
||||
}
|
||||
else {
|
||||
TRACE("assign_quantifier", tout << "adding:\n" << mk_ismt2_pp(mp, m_context->get_manager()) << "\n";);
|
||||
TRACE("quantifier", tout << "adding:\n" << mk_ismt2_pp(mp, m_context->get_manager()) << "\n";);
|
||||
m_mam->add_pattern(q, mp);
|
||||
}
|
||||
if (!unary)
|
||||
|
|
|
@ -91,6 +91,8 @@ namespace smt {
|
|||
|
||||
ptr_vector<quantifier>::const_iterator begin_quantifiers() const;
|
||||
ptr_vector<quantifier>::const_iterator end_quantifiers() const;
|
||||
unsigned num_quantifiers() const;
|
||||
|
||||
};
|
||||
|
||||
class quantifier_manager_plugin {
|
||||
|
|
|
@ -38,6 +38,7 @@ namespace smt {
|
|||
bool m_minimizing_core;
|
||||
bool m_core_extend_patterns;
|
||||
unsigned m_core_extend_patterns_max_distance;
|
||||
bool m_core_extend_nonlocal_patterns;
|
||||
obj_map<expr, expr*> m_name2assertion;
|
||||
|
||||
public:
|
||||
|
@ -48,13 +49,15 @@ namespace smt {
|
|||
m_context(m, m_smt_params),
|
||||
m_minimizing_core(false),
|
||||
m_core_extend_patterns(false),
|
||||
m_core_extend_patterns_max_distance(UINT_MAX) {
|
||||
m_core_extend_patterns_max_distance(UINT_MAX),
|
||||
m_core_extend_nonlocal_patterns(false) {
|
||||
m_logic = l;
|
||||
if (m_logic != symbol::null)
|
||||
m_context.set_logic(m_logic);
|
||||
smt_params_helper smth(p);
|
||||
m_core_extend_patterns = smth.core_extend_patterns();
|
||||
m_core_extend_patterns_max_distance = smth.core_extend_patterns_max_distance();
|
||||
m_core_extend_nonlocal_patterns = smth.core_extend_nonlocal_patterns();
|
||||
}
|
||||
|
||||
virtual solver * translate(ast_manager & m, params_ref const & p) {
|
||||
|
@ -81,6 +84,8 @@ namespace smt {
|
|||
m_context.updt_params(p);
|
||||
smt_params_helper smth(p);
|
||||
m_core_extend_patterns = smth.core_extend_patterns();
|
||||
m_core_extend_patterns_max_distance = smth.core_extend_patterns_max_distance();
|
||||
m_core_extend_nonlocal_patterns = smth.core_extend_nonlocal_patterns();
|
||||
}
|
||||
|
||||
virtual void collect_param_descrs(param_descrs & r) {
|
||||
|
@ -172,6 +177,8 @@ namespace smt {
|
|||
|
||||
if (m_core_extend_patterns)
|
||||
add_pattern_literals_to_core(r);
|
||||
if (m_core_extend_nonlocal_patterns)
|
||||
add_nonlocal_pattern_literals_to_core(r);
|
||||
}
|
||||
|
||||
virtual void get_model(model_ref & m) {
|
||||
|
@ -250,7 +257,7 @@ namespace smt {
|
|||
}
|
||||
};
|
||||
|
||||
void collect_pattern_func_decls(expr_ref & e, func_decl_set & fds) {
|
||||
void collect_pattern_fds(expr_ref & e, func_decl_set & fds) {
|
||||
collect_pattern_fds_proc p(get_manager(), fds);
|
||||
expr_mark visited;
|
||||
for_each_expr(p, visited, e);
|
||||
|
@ -295,7 +302,7 @@ namespace smt {
|
|||
expr_ref name(core[i], m);
|
||||
SASSERT(m_name2assertion.contains(name));
|
||||
expr_ref assrtn(m_name2assertion.find(name), m);
|
||||
collect_pattern_func_decls(assrtn, pattern_fds);
|
||||
collect_pattern_fds(assrtn, pattern_fds);
|
||||
}
|
||||
|
||||
if (!pattern_fds.empty()) {
|
||||
|
@ -317,6 +324,55 @@ namespace smt {
|
|||
break;
|
||||
}
|
||||
}
|
||||
|
||||
struct collect_body_fds_proc {
|
||||
ast_manager & m;
|
||||
func_decl_set & m_fds;
|
||||
collect_body_fds_proc(ast_manager & m, func_decl_set & fds) :
|
||||
m(m), m_fds(fds) {
|
||||
}
|
||||
void operator()(var * n) {}
|
||||
void operator()(app * n) {}
|
||||
void operator()(quantifier * n) {
|
||||
collect_fds_proc p(m, m_fds);
|
||||
expr_fast_mark1 visited;
|
||||
quick_for_each_expr(p, visited, n->get_expr());
|
||||
}
|
||||
};
|
||||
|
||||
void collect_body_func_decls(expr_ref & e, func_decl_set & fds) {
|
||||
ast_manager & m = get_manager();
|
||||
collect_body_fds_proc p(m, fds);
|
||||
expr_mark visited;
|
||||
for_each_expr(p, visited, e);
|
||||
}
|
||||
|
||||
void add_nonlocal_pattern_literals_to_core(ptr_vector<expr> & core) {
|
||||
ast_manager & m = get_manager();
|
||||
|
||||
obj_map<expr, expr*>::iterator it = m_name2assertion.begin();
|
||||
obj_map<expr, expr*>::iterator end = m_name2assertion.end();
|
||||
for (unsigned i = 0; it != end; it++, i++) {
|
||||
expr_ref name(it->m_key, m);
|
||||
expr_ref assrtn(it->m_value, m);
|
||||
|
||||
if (!core.contains(name)) {
|
||||
func_decl_set pattern_fds, body_fds;
|
||||
collect_pattern_fds(assrtn, pattern_fds);
|
||||
collect_body_func_decls(assrtn, body_fds);
|
||||
|
||||
func_decl_set::iterator pit = pattern_fds.begin();
|
||||
func_decl_set::iterator pend= pattern_fds.end();
|
||||
for (; pit != pend; pit++) {
|
||||
func_decl * fd = *pit;
|
||||
if (!body_fds.contains(fd)) {
|
||||
core.insert(name);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -177,6 +177,22 @@ namespace smt {
|
|||
virtual void restart_eh() {
|
||||
}
|
||||
|
||||
/**
|
||||
\brief This method is called by smt_context before the search starts
|
||||
to get any extra assumptions the theory wants to use.
|
||||
(See theory_str for an example)
|
||||
*/
|
||||
virtual void add_theory_assumptions(expr_ref_vector & assumptions) {
|
||||
}
|
||||
|
||||
/**
|
||||
\brief This method is called from smt_context when an unsat core is generated.
|
||||
The theory may change the answer to UNKNOWN by returning l_undef from this method.
|
||||
*/
|
||||
virtual lbool validate_unsat_core(expr_ref_vector & unsat_core) {
|
||||
return l_false;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief This method is invoked before the search starts.
|
||||
*/
|
||||
|
|
|
@ -40,7 +40,7 @@ namespace smt {
|
|||
template<typename Ext>
|
||||
void theory_arith<Ext>::found_underspecified_op(app * n) {
|
||||
if (!m_found_underspecified_op) {
|
||||
TRACE("arith", tout << "found non underspecificed expression:\n" << mk_pp(n, get_manager()) << "\n";);
|
||||
TRACE("arith", tout << "found underspecificed expression:\n" << mk_pp(n, get_manager()) << "\n";);
|
||||
get_context().push_trail(value_trail<context, bool>(m_found_underspecified_op));
|
||||
m_found_underspecified_op = true;
|
||||
}
|
||||
|
@ -395,6 +395,7 @@ namespace smt {
|
|||
|
||||
template<typename Ext>
|
||||
theory_var theory_arith<Ext>::internalize_div(app * n) {
|
||||
if (!m_util.is_numeral(n->get_arg(1))) found_underspecified_op(n);
|
||||
found_underspecified_op(n);
|
||||
theory_var s = mk_binary_op(n);
|
||||
context & ctx = get_context();
|
||||
|
@ -418,7 +419,7 @@ namespace smt {
|
|||
template<typename Ext>
|
||||
theory_var theory_arith<Ext>::internalize_mod(app * n) {
|
||||
TRACE("arith_mod", tout << "internalizing...\n" << mk_pp(n, get_manager()) << "\n";);
|
||||
found_underspecified_op(n);
|
||||
if (!m_util.is_numeral(n->get_arg(1))) found_underspecified_op(n);
|
||||
theory_var s = mk_binary_op(n);
|
||||
context & ctx = get_context();
|
||||
if (!ctx.relevancy())
|
||||
|
@ -428,7 +429,7 @@ namespace smt {
|
|||
|
||||
template<typename Ext>
|
||||
theory_var theory_arith<Ext>::internalize_rem(app * n) {
|
||||
found_underspecified_op(n);
|
||||
if (!m_util.is_numeral(n->get_arg(1))) found_underspecified_op(n);
|
||||
theory_var s = mk_binary_op(n);
|
||||
context & ctx = get_context();
|
||||
if (!ctx.relevancy()) {
|
||||
|
|
|
@ -206,7 +206,8 @@ namespace smt {
|
|||
numeral k = ceil(get_value(v));
|
||||
rational _k = k.to_rational();
|
||||
expr_ref bound(get_manager());
|
||||
bound = m_util.mk_ge(get_enode(v)->get_owner(), m_util.mk_numeral(_k, true));
|
||||
expr* e = get_enode(v)->get_owner();
|
||||
bound = m_util.mk_ge(e, m_util.mk_numeral(_k, m_util.is_int(e)));
|
||||
TRACE("arith_int", tout << mk_bounded_pp(bound, get_manager()) << "\n";);
|
||||
context & ctx = get_context();
|
||||
ctx.internalize(bound, true);
|
||||
|
@ -371,7 +372,7 @@ namespace smt {
|
|||
|
||||
ctx.mk_th_axiom(get_id(), l1, l2);
|
||||
|
||||
TRACE("theory_arith_int",
|
||||
TRACE("arith_int",
|
||||
tout << "cut: (or " << mk_pp(p1, get_manager()) << " " << mk_pp(p2, get_manager()) << ")\n";
|
||||
);
|
||||
|
||||
|
@ -1407,6 +1408,7 @@ namespace smt {
|
|||
if (m_params.m_arith_int_eq_branching && branch_infeasible_int_equality()) {
|
||||
return FC_CONTINUE;
|
||||
}
|
||||
|
||||
theory_var int_var = find_infeasible_int_base_var();
|
||||
if (int_var != null_theory_var) {
|
||||
TRACE("arith_int", tout << "v" << int_var << " does not have an integer assignment: " << get_value(int_var) << "\n";);
|
||||
|
|
|
@ -339,8 +339,13 @@ namespace smt {
|
|||
tout << mk_pp(var, get_manager()) << "\n";
|
||||
tout << "power " << power << ": " << expt(i, power) << "\n";
|
||||
display_interval(tout << "target before: ", target); tout << "\n";);
|
||||
|
||||
i.expt(power);
|
||||
target *= i;
|
||||
|
||||
get_manager().limit().inc((target.is_lower_open() || target.minus_infinity()) ? 1 : target.get_lower_value().bitsize());
|
||||
get_manager().limit().inc((target.is_upper_open() || target.plus_infinity()) ? 1 : target.get_upper_value().bitsize());
|
||||
|
||||
TRACE("non_linear", display_interval(tout << "target after: ", target); tout << "\n";);
|
||||
}
|
||||
|
||||
|
|
|
@ -607,12 +607,13 @@ namespace smt {
|
|||
}
|
||||
expr_ref sum(m);
|
||||
arith_simp().mk_add(sz, args.c_ptr(), sum);
|
||||
literal l(mk_eq(n, sum, false));
|
||||
TRACE("bv",
|
||||
tout << mk_pp(n, m) << "\n";
|
||||
tout << mk_pp(sum, m) << "\n";
|
||||
ctx.display_literal_verbose(tout, l);
|
||||
tout << "\n";
|
||||
);
|
||||
|
||||
literal l(mk_eq(n, sum, false));
|
||||
|
||||
ctx.mark_as_relevant(l);
|
||||
ctx.mk_th_axiom(get_id(), 1, &l);
|
||||
|
|
|
@ -868,7 +868,8 @@ namespace smt {
|
|||
e = ctx.get_enode(to_app(n));
|
||||
}
|
||||
else {
|
||||
e = ctx.mk_enode(to_app(n), false, false, true);
|
||||
ctx.internalize(n, false);
|
||||
e = ctx.get_enode(n);
|
||||
}
|
||||
v = e->get_th_var(get_id());
|
||||
if (v == null_theory_var) {
|
||||
|
@ -901,7 +902,7 @@ namespace smt {
|
|||
objective_term const& objective = m_objectives[v];
|
||||
has_shared = false;
|
||||
|
||||
IF_VERBOSE(1,
|
||||
IF_VERBOSE(4,
|
||||
for (unsigned i = 0; i < objective.size(); ++i) {
|
||||
verbose_stream() << objective[i].second
|
||||
<< " * v" << objective[i].first << " ";
|
||||
|
@ -991,9 +992,12 @@ namespace smt {
|
|||
if (num_nodes <= v && v < num_nodes + num_edges) {
|
||||
unsigned edge_id = v - num_nodes;
|
||||
literal lit = m_edges[edge_id].m_justification;
|
||||
get_context().literal2expr(lit, tmp);
|
||||
core.push_back(tmp);
|
||||
if (lit != null_literal) {
|
||||
get_context().literal2expr(lit, tmp);
|
||||
core.push_back(tmp);
|
||||
}
|
||||
}
|
||||
TRACE("opt", tout << core << "\n";);
|
||||
}
|
||||
for (unsigned i = 0; i < num_nodes; ++i) {
|
||||
mpq_inf const& val = S.get_value(i);
|
||||
|
@ -1005,7 +1009,8 @@ namespace smt {
|
|||
inf_eps result(rational(0), r);
|
||||
blocker = mk_gt(v, result);
|
||||
IF_VERBOSE(10, verbose_stream() << blocker << "\n";);
|
||||
return result;
|
||||
r += m_objective_consts[v];
|
||||
return inf_eps(rational(0), r);
|
||||
}
|
||||
default:
|
||||
TRACE("opt", tout << "unbounded\n"; );
|
||||
|
@ -1016,6 +1021,7 @@ namespace smt {
|
|||
|
||||
template<typename Ext>
|
||||
theory_var theory_dense_diff_logic<Ext>::add_objective(app* term) {
|
||||
TRACE("opt", tout << mk_pp(term, get_manager()) << "\n";);
|
||||
objective_term objective;
|
||||
theory_var result = m_objectives.size();
|
||||
rational q(1), r(0);
|
||||
|
@ -1050,6 +1056,7 @@ namespace smt {
|
|||
ast_manager& m = get_manager();
|
||||
objective_term const& t = m_objectives[v];
|
||||
expr_ref e(m), f(m), f2(m);
|
||||
TRACE("opt", tout << "mk_ineq " << v << " " << val << "\n";);
|
||||
if (t.size() == 1 && t[0].second.is_one()) {
|
||||
f = get_enode(t[0].first)->get_owner();
|
||||
}
|
||||
|
|
|
@ -255,6 +255,11 @@ final_check_status theory_seq::final_check_eh() {
|
|||
TRACE("seq", tout << ">>solve_eqs\n";);
|
||||
return FC_CONTINUE;
|
||||
}
|
||||
if (check_contains()) {
|
||||
++m_stats.m_propagate_contains;
|
||||
TRACE("seq", tout << ">>propagate_contains\n";);
|
||||
return FC_CONTINUE;
|
||||
}
|
||||
if (solve_nqs(0)) {
|
||||
++m_stats.m_solve_nqs;
|
||||
TRACE("seq", tout << ">>solve_nqs\n";);
|
||||
|
@ -290,11 +295,6 @@ final_check_status theory_seq::final_check_eh() {
|
|||
TRACE("seq", tout << ">>propagate_automata\n";);
|
||||
return FC_CONTINUE;
|
||||
}
|
||||
if (check_contains()) {
|
||||
++m_stats.m_propagate_contains;
|
||||
TRACE("seq", tout << ">>propagate_contains\n";);
|
||||
return FC_CONTINUE;
|
||||
}
|
||||
if (is_solved()) {
|
||||
TRACE("seq", tout << ">>is_solved\n";);
|
||||
return FC_DONE;
|
||||
|
@ -1159,7 +1159,7 @@ bool theory_seq::check_extensionality() {
|
|||
}
|
||||
|
||||
/*
|
||||
\brief check negated contains constriants.
|
||||
\brief check negated contains constraints.
|
||||
*/
|
||||
bool theory_seq::check_contains() {
|
||||
context & ctx = get_context();
|
||||
|
@ -1199,6 +1199,11 @@ bool theory_seq::is_solved() {
|
|||
IF_VERBOSE(10, display_disequation(verbose_stream() << "(seq.giveup ", m_nqs[0]); verbose_stream() << " is unsolved)\n";);
|
||||
return false;
|
||||
}
|
||||
if (!m_ncs.empty()) {
|
||||
TRACE("seq", display_nc(tout << "(seq.giveup ", m_ncs[0]); tout << " is unsolved)\n";);
|
||||
IF_VERBOSE(10, display_nc(verbose_stream() << "(seq.giveup ", m_ncs[0]); verbose_stream() << " is unsolved)\n";);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -1981,6 +1986,23 @@ bool theory_seq::solve_nc(unsigned idx) {
|
|||
}
|
||||
if (c != n.contains()) {
|
||||
m_ncs.push_back(nc(c, deps));
|
||||
m_new_propagation = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
expr* e1, *e2;
|
||||
if (m.is_eq(c, e1, e2)) {
|
||||
literal eq = mk_eq(e1, e2, false);
|
||||
propagate_lit(deps, 0, 0, ~eq);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (m.is_or(c)) {
|
||||
for (unsigned i = 0; i < to_app(c)->get_num_args(); ++i) {
|
||||
expr_ref ci(to_app(c)->get_arg(i), m);
|
||||
m_ncs.push_back(nc(ci, deps));
|
||||
}
|
||||
m_new_propagation = true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -2344,6 +2366,17 @@ bool theory_seq::add_itos_axiom(expr* e) {
|
|||
return false;
|
||||
}
|
||||
add_axiom(mk_eq(e2, n, false));
|
||||
|
||||
#if 1
|
||||
expr_ref num_re(m), opt_re(m);
|
||||
num_re = m_util.re.mk_range(m_util.str.mk_string(symbol("0")), m_util.str.mk_string(symbol("9")));
|
||||
num_re = m_util.re.mk_plus(num_re);
|
||||
opt_re = m_util.re.mk_opt(m_util.re.mk_to_re(m_util.str.mk_string(symbol("-"))));
|
||||
num_re = m_util.re.mk_concat(opt_re, num_re);
|
||||
app_ref in_re(m_util.re.mk_in_re(e, num_re), m);
|
||||
internalize_term(in_re);
|
||||
propagate_in_re(in_re, true);
|
||||
#endif
|
||||
m_trail_stack.push(push_replay(alloc(replay_axiom, m, e)));
|
||||
return true;
|
||||
}
|
||||
|
@ -2403,6 +2436,18 @@ void theory_seq::display(std::ostream & out) const {
|
|||
}
|
||||
}
|
||||
|
||||
if (!m_ncs.empty()) {
|
||||
out << "Non contains:\n";
|
||||
for (unsigned i = 0; i < m_ncs.size(); ++i) {
|
||||
display_nc(out, m_ncs[i]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void theory_seq::display_nc(std::ostream& out, nc const& nc) const {
|
||||
out << "not " << mk_pp(nc.contains(), m) << "\n";
|
||||
display_deps(out << " <- ", nc.deps()); out << "\n";
|
||||
}
|
||||
|
||||
void theory_seq::display_equations(std::ostream& out) const {
|
||||
|
@ -2719,7 +2764,9 @@ bool theory_seq::can_propagate() {
|
|||
|
||||
expr_ref theory_seq::canonize(expr* e, dependency*& eqs) {
|
||||
expr_ref result = expand(e, eqs);
|
||||
TRACE("seq", tout << mk_pp(e, m) << " expands to " << result << "\n";);
|
||||
m_rewrite(result);
|
||||
TRACE("seq", tout << mk_pp(e, m) << " rewrites to " << result << "\n";);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
@ -3494,6 +3541,7 @@ void theory_seq::add_extract_suffix_axiom(expr* e, expr* s, expr* i) {
|
|||
let e = at(s, i)
|
||||
|
||||
0 <= i < len(s) -> s = xey & len(x) = i & len(e) = 1
|
||||
i < 0 \/ i >= len(s) -> e = empty
|
||||
|
||||
*/
|
||||
void theory_seq::add_at_axiom(expr* e) {
|
||||
|
@ -3507,13 +3555,18 @@ void theory_seq::add_at_axiom(expr* e) {
|
|||
expr_ref y = mk_skolem(m_post, s, mk_sub(mk_sub(len_s, i), one));
|
||||
expr_ref xey = mk_concat(x, e, y);
|
||||
expr_ref len_x(m_util.str.mk_length(x), m);
|
||||
expr_ref emp(m_util.str.mk_empty(m.get_sort(e)), m);
|
||||
|
||||
literal i_ge_0 = mk_literal(m_autil.mk_ge(i, zero));
|
||||
literal i_ge_len_s = mk_literal(m_autil.mk_ge(mk_sub(i, m_util.str.mk_length(s)), zero));
|
||||
|
||||
|
||||
add_axiom(~i_ge_0, i_ge_len_s, mk_seq_eq(s, xey));
|
||||
add_axiom(~i_ge_0, i_ge_len_s, mk_eq(one, len_e, false));
|
||||
add_axiom(~i_ge_0, i_ge_len_s, mk_eq(i, len_x, false));
|
||||
|
||||
add_axiom(i_ge_0, mk_eq(s, emp, false));
|
||||
add_axiom(~i_ge_len_s, mk_eq(s, emp, false));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -4469,10 +4522,11 @@ bool theory_seq::canonizes(bool sign, expr* e) {
|
|||
context& ctx = get_context();
|
||||
dependency* deps = 0;
|
||||
expr_ref cont = canonize(e, deps);
|
||||
TRACE("seq", tout << mk_pp(e, m) << " -> " << cont << "\n";);
|
||||
TRACE("seq", tout << mk_pp(e, m) << " -> " << cont << "\n";
|
||||
if (deps) display_deps(tout, deps););
|
||||
if ((m.is_true(cont) && !sign) ||
|
||||
(m.is_false(cont) && sign)) {
|
||||
TRACE("seq", display(tout););
|
||||
TRACE("seq", display(tout); tout << ctx.get_assignment(ctx.get_literal(e)) << "\n";);
|
||||
propagate_lit(deps, 0, 0, ctx.get_literal(e));
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -570,6 +570,7 @@ namespace smt {
|
|||
void display_disequation(std::ostream& out, ne const& e) const;
|
||||
void display_deps(std::ostream& out, dependency* deps) const;
|
||||
void display_deps(std::ostream& out, 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);
|
||||
virtual ~theory_seq();
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue