3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-08 10:25:18 +00:00
This commit is contained in:
Christoph M. Wintersteiger 2015-11-06 16:24:48 +00:00
commit 05e7aca388
15 changed files with 209 additions and 148 deletions

View file

@ -284,6 +284,9 @@ class AstRef(Z3PPObject):
def __repr__(self):
return obj_to_string(self)
def __hash__(self):
return self.hash()
def sexpr(self):
"""Return an string representing the AST node in s-expression notation.

View file

@ -288,11 +288,13 @@ namespace smt {
}
void conflict_resolution::process_antecedent(literal antecedent, unsigned & num_marks) {
TRACE("conflict", tout << "processing antecedent: "; m_ctx.display_literal(tout, antecedent); tout << "\n";);
bool_var var = antecedent.var();
unsigned lvl = m_ctx.get_assign_level(var);
SASSERT(var < static_cast<int>(m_ctx.get_num_bool_vars()));
TRACE("conflict", tout << "processing antecedent (level " << lvl << "):";
m_ctx.display_literal(tout, antecedent);
m_ctx.display_detailed_literal(tout << " ", antecedent); tout << "\n";);
if (!m_ctx.is_marked(var) && lvl > m_ctx.get_base_level()) {
m_ctx.set_mark(var);
m_ctx.inc_bvar_activity(var);

View file

@ -172,7 +172,9 @@ namespace smt {
}
void context::assign_core(literal l, b_justification j, bool decision) {
TRACE("assign_core", tout << "assigning: " << l << " "; display_literal(tout, l); tout << "\n";);
TRACE("assign_core", tout << (decision?"decision: ":"propagating: ") << l << " ";
display_literal(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;
@ -1609,7 +1611,7 @@ namespace smt {
}
bool context::propagate() {
TRACE("propagate", tout << "propagating...\n";);
TRACE("propagate", tout << "propagating... " << m_qhead << ":" << m_assigned_literals.size() << "\n";);
while (true) {
if (inconsistent())
return false;

View file

@ -1237,6 +1237,8 @@ namespace smt {
void display_profile(std::ostream & out) const;
void display(std::ostream& out, b_justification j) const;
// -----------------------------------
//
// Debugging support

View file

@ -97,7 +97,7 @@ namespace smt {
}
void context::display_literals_verbose(std::ostream & out, unsigned num_lits, literal const * lits) const {
display_verbose(out, m_manager, num_lits, lits, m_bool_var2expr.c_ptr());
display_verbose(out, m_manager, num_lits, lits, m_bool_var2expr.c_ptr(), "\n");
}
void context::display_literal_info(std::ostream & out, literal l) const {
@ -204,9 +204,10 @@ namespace smt {
literal_vector::const_iterator end = m_assigned_literals.end();
for (; it != end; ++it) {
display_literal(out, *it);
out << " ";
out << ": ";
display_verbose(tout, m_manager, 1, &*it, m_bool_var2expr.c_ptr());
out << "\n";
}
out << "\n";
}
}
@ -581,15 +582,8 @@ namespace smt {
}
}
}
void context::trace_assign(literal l, b_justification j, bool decision) const {
SASSERT(m_manager.has_trace_stream());
std::ostream & out = m_manager.trace_stream();
out << "[assign] ";
display_literal(out, l);
if (decision)
out << " decision";
out << " ";
void context::display(std::ostream& out, b_justification j) const {
switch (j.get_kind()) {
case b_justification::AXIOM:
out << "axiom";
@ -597,8 +591,6 @@ namespace smt {
case b_justification::BIN_CLAUSE: {
literal l2 = j.get_literal();
out << "bin-clause ";
display_literal(out, l);
out << " ";
display_literal(out, l2);
break;
}
@ -618,5 +610,16 @@ namespace smt {
out << "\n";
}
void context::trace_assign(literal l, b_justification j, bool decision) const {
SASSERT(m_manager.has_trace_stream());
std::ostream & out = m_manager.trace_stream();
out << "[assign] ";
display_literal(out, l);
if (decision)
out << " decision";
out << " ";
display(out, j);
}
};

View file

@ -69,10 +69,10 @@ namespace smt {
}
}
void display_verbose(std::ostream & out, ast_manager& m, unsigned num_lits, literal const * lits, expr * const * bool_var2expr_map) {
void display_verbose(std::ostream & out, ast_manager& m, unsigned num_lits, literal const * lits, expr * const * bool_var2expr_map, char const* sep) {
for (unsigned i = 0; i < num_lits; i++) {
if (i > 0)
out << " ";
out << sep;
lits[i].display(out, m, bool_var2expr_map);
}
}

View file

@ -103,7 +103,7 @@ namespace smt {
void display_compact(std::ostream & out, unsigned num_lits, literal const * lits, expr * const * bool_var2expr_map);
void display_verbose(std::ostream & out, ast_manager& m, unsigned num_lits, literal const * lits, expr * const * bool_var2expr_map);
void display_verbose(std::ostream & out, ast_manager& m, unsigned num_lits, literal const * lits, expr * const * bool_var2expr_map, char const* sep = " ");
template<typename T>
void neg_literals(unsigned num_lits, literal const * lits, T & result) {

View file

@ -218,7 +218,7 @@ namespace smt {
typedef svector<enode_pair> eq_vector;
// keep track of coefficients used for bounds for proof generation.
class antecedents {
class antecedents_t {
literal_vector m_lits;
eq_vector m_eqs;
vector<numeral> m_lit_coeffs;
@ -233,16 +233,38 @@ namespace smt {
void init();
public:
antecedents(): m_init(false) {}
antecedents_t(): m_init(false) {}
void reset();
literal_vector& lits() { return m_lits; }
eq_vector& eqs() { return m_eqs; }
literal_vector const& lits() const { return m_lits; }
eq_vector const& eqs() const { return m_eqs; }
void push_lit(literal l, numeral const& r, bool proofs_enabled);
void push_eq(enode_pair const& p, numeral const& r, bool proofs_enabled);
void append(unsigned sz, literal const* ls) { m_lits.append(sz, ls); }
void append(unsigned sz, enode_pair const* ps) { m_eqs.append(sz, ps); }
unsigned num_params() const { return empty()?0:m_eq_coeffs.size() + m_lit_coeffs.size() + 1; }
numeral const* lit_coeffs() const { return m_lit_coeffs.c_ptr(); }
numeral const* eq_coeffs() const { return m_eq_coeffs.c_ptr(); }
parameter* params(char const* name);
std::ostream& display(theory_arith& th, std::ostream& out) const;
};
class antecedents {
theory_arith& th;
antecedents_t& a;
public:
antecedents(theory_arith& th);
~antecedents();
literal_vector const& lits() const { return a.lits(); }
eq_vector const& eqs() const { return a.eqs(); }
void push_lit(literal l, numeral const& r, bool e) { a.push_lit(l, r, e); }
void push_eq(enode_pair const& p, numeral const& r, bool e) { a.push_eq(p, r, e); }
void append(unsigned sz, literal const* ls) { a.append(sz, ls); }
void append(unsigned sz, enode_pair const* ps) { a.append(sz, ps); }
unsigned num_params() const { return a.num_params(); }
numeral const* lit_coeffs() const { return a.lit_coeffs(); }
numeral const* eq_coeffs() const { return a.eq_coeffs(); }
parameter* params(char const* name) { return a.params(name); }
std::ostream& display(std::ostream& out) const { return a.display(th, out); }
};
class gomory_cut_justification;
@ -324,11 +346,14 @@ namespace smt {
public:
derived_bound(theory_var v, inf_numeral const & val, bound_kind k):bound(v, val, k, false) {}
virtual ~derived_bound() {}
literal_vector const& lits() const { return m_lits; }
eq_vector const& eqs() const { return m_eqs; }
virtual bool has_justification() const { return true; }
virtual void push_justification(antecedents& a, numeral const& coeff, bool proofs_enabled);
virtual void push_lit(literal l, numeral const&) { m_lits.push_back(l); }
virtual void push_eq(enode_pair const& p, numeral const&) { m_eqs.push_back(p); }
virtual void display(theory_arith const& th, std::ostream& out) const;
};
class justified_derived_bound : public derived_bound {
@ -460,8 +485,8 @@ namespace smt {
svector<scope> m_scopes;
literal_vector m_tmp_literal_vector2;
antecedents m_tmp_antecedents;
antecedents m_tmp_antecedents2;
antecedents_t m_antecedents[3];
unsigned m_antecedents_index;
struct var_value_hash;
friend struct var_value_hash;
@ -506,6 +531,8 @@ namespace smt {
bool relax_bounds() const { return m_params.m_arith_stronger_lemmas; }
bool skip_big_coeffs() const { return m_params.m_arith_skip_rows_with_big_coeffs; }
bool dump_lemmas() const { return m_params.m_arith_dump_lemmas; }
void dump_lemmas(literal l, antecedents const& ante);
void dump_lemmas(literal l, derived_bound const& ante);
bool process_atoms() const;
unsigned get_num_conflicts() const { return m_num_conflicts; }
var_kind get_var_kind(theory_var v) const { return m_data[v].kind(); }
@ -750,7 +777,7 @@ namespace smt {
void explain_bound(row const & r, int idx, bool lower, inf_numeral & delta,
antecedents & antecedents);
void mk_implied_bound(row const & r, unsigned idx, bool lower, theory_var v, bound_kind kind, inf_numeral const & k);
void assign_bound_literal(literal l, row const & r, unsigned idx, bool lower, inf_numeral & delta, antecedents& antecedents);
void assign_bound_literal(literal l, row const & r, unsigned idx, bool lower, inf_numeral & delta);
void propagate_bounds();
// -----------------------------------
@ -836,7 +863,9 @@ namespace smt {
// Justification
//
// -----------------------------------
void set_conflict(unsigned num_literals, literal const * lits, unsigned num_eqs, enode_pair const * eqs, antecedents& antecedents, bool is_lia, char const* proof_rule);
void set_conflict(unsigned num_literals, literal const * lits, unsigned num_eqs, enode_pair const * eqs, antecedents& antecedents, char const* proof_rule);
void set_conflict(antecedents const& ante, antecedents& bounds, char const* proof_rule);
void set_conflict(derived_bound const& ante, antecedents& bounds, char const* proof_rule);
void collect_fixed_var_justifications(row const & r, antecedents& antecedents) const;
// -----------------------------------
@ -989,7 +1018,7 @@ namespace smt {
gb_result compute_grobner(svector<theory_var> const & nl_cluster);
bool max_min_nl_vars();
final_check_status process_non_linear();
antecedents& get_antecedents();
// -----------------------------------
//

View file

@ -316,7 +316,7 @@ namespace smt {
// -----------------------------------
template<typename Ext>
void theory_arith<Ext>::antecedents::init() {
void theory_arith<Ext>::antecedents_t::init() {
if (!m_init && !empty()) {
m_params.push_back(parameter(symbol("unknown-arith")));
for (unsigned i = 0; i < m_lits.size(); i++) {
@ -330,7 +330,7 @@ namespace smt {
}
template<typename Ext>
void theory_arith<Ext>::antecedents::reset() {
void theory_arith<Ext>::antecedents_t::reset() {
m_init = false;
m_eq_coeffs.reset();
m_lit_coeffs.reset();
@ -340,7 +340,7 @@ namespace smt {
}
template<typename Ext>
void theory_arith<Ext>::antecedents::push_lit(literal l, numeral const& r, bool proofs_enabled) {
void theory_arith<Ext>::antecedents_t::push_lit(literal l, numeral const& r, bool proofs_enabled) {
m_lits.push_back(l);
if (proofs_enabled) {
m_lit_coeffs.push_back(r);
@ -348,7 +348,7 @@ namespace smt {
}
template<typename Ext>
void theory_arith<Ext>::antecedents::push_eq(enode_pair const& p, numeral const& r, bool proofs_enabled) {
void theory_arith<Ext>::antecedents_t::push_eq(enode_pair const& p, numeral const& r, bool proofs_enabled) {
m_eqs.push_back(p);
if (proofs_enabled) {
m_eq_coeffs.push_back(r);
@ -356,7 +356,7 @@ namespace smt {
}
template<typename Ext>
parameter * theory_arith<Ext>::antecedents::params(char const* name) {
parameter * theory_arith<Ext>::antecedents_t::params(char const* name) {
if (empty()) return 0;
init();
m_params[0] = parameter(symbol(name));
@ -740,8 +740,8 @@ namespace smt {
}
}
else {
a.lits().append(m_lits.size(), m_lits.c_ptr());
a.eqs().append(m_eqs.size(), m_eqs.c_ptr());
a.append(m_lits.size(), m_lits.c_ptr());
a.append(m_eqs.size(), m_eqs.c_ptr());
}
}
@ -804,8 +804,7 @@ namespace smt {
*/
template<typename Ext>
void theory_arith<Ext>::accumulate_justification(bound & b, derived_bound& new_bound, numeral const& coeff, literal_idx_set & lits, eq_set & eqs) {
antecedents& ante = m_tmp_antecedents;
ante.reset();
antecedents ante(*this);
b.push_justification(ante, coeff, proofs_enabled());
unsigned num_lits = ante.lits().size();
for (unsigned i = 0; i < num_lits; ++i) {

View file

@ -349,7 +349,6 @@ namespace smt {
template<typename Ext>
void theory_arith<Ext>::mk_axiom(expr * ante, expr * conseq) {
ast_manager & m = get_manager();
TRACE("arith_axiom", tout << mk_pp(ante, m) << "\n" << mk_pp(conseq, m) << "\n";);
context & ctx = get_context();
simplifier & s = ctx.get_simplifier();
expr_ref s_ante(m), s_conseq(m);
@ -371,6 +370,9 @@ namespace smt {
literal l_conseq = ctx.get_literal(s_conseq);
if (negated) l_conseq.neg();
TRACE("arith_axiom", tout << mk_pp(ante, m) << "\n" << mk_pp(conseq, m) << "\n";
tout << s_ante << "\n" << s_conseq << "\n";);
literal lits[2] = {l_ante, l_conseq};
ctx.mk_th_axiom(get_id(), 2, lits);
if (ctx.relevancy()) {
@ -394,12 +396,12 @@ namespace smt {
void theory_arith<Ext>::mk_div_axiom(expr * p, expr * q) {
if (!m_util.is_zero(q)) {
ast_manager & m = get_manager();
expr_ref div(m), zero(m), eqz(m), eq(m);
TRACE("div_axiom_bug", tout << "expanding div_axiom for: " << mk_pp(p, m) << " / " << mk_pp(q, m) << "\n";);
expr * div = m_util.mk_div(p, q);
expr * zero = m_util.mk_numeral(rational(0), false);
expr_ref eqz(m), eq(m);
eqz = m.mk_eq(q, zero);
eq = m.mk_eq(m_util.mk_mul(q, div), p);
div = m_util.mk_div(p, q);
zero = m_util.mk_numeral(rational(0), false);
eqz = m.mk_eq(q, zero);
eq = m.mk_eq(m_util.mk_mul(q, div), p);
TRACE("div_axiom_bug", tout << "eqz: " << mk_pp(eqz, m) << "\neq: " << mk_pp(eq, m) << "\n";);
mk_axiom(eqz, eq);
}
@ -410,15 +412,21 @@ namespace smt {
if (!m_util.is_zero(divisor)) {
// if divisor is zero, then idiv and mod are uninterpreted functions.
ast_manager & m = get_manager();
expr * div = m_util.mk_idiv(dividend, divisor);
expr * mod = m_util.mk_mod(dividend, divisor);
expr * zero = m_util.mk_numeral(rational(0), true);
expr * abs_divisor = m.mk_ite(m_util.mk_lt(divisor, zero), m_util.mk_sub(zero, divisor), divisor);
expr_ref div(m), mod(m), zero(m), abs_divisor(m);
expr_ref eqz(m), eq(m), lower(m), upper(m);
eqz = m.mk_eq(divisor, zero);
eq = m.mk_eq(m_util.mk_add(m_util.mk_mul(divisor, div), mod), dividend);
lower = m_util.mk_le(zero, mod);
upper = m_util.mk_lt(mod, abs_divisor);
div = m_util.mk_idiv(dividend, divisor);
mod = m_util.mk_mod(dividend, divisor);
zero = m_util.mk_numeral(rational(0), true);
abs_divisor = m.mk_ite(m_util.mk_lt(divisor, zero), m_util.mk_sub(zero, divisor), divisor);
eqz = m.mk_eq(divisor, zero);
eq = m.mk_eq(m_util.mk_add(m_util.mk_mul(divisor, div), mod), dividend);
lower = m_util.mk_le(zero, mod);
upper = m_util.mk_lt(mod, abs_divisor);
TRACE("div_axiom_bug",
tout << "eqz: " << mk_pp(eqz, m) << "\neq: " << mk_pp(eq, m) << "\n";
tout << "lower: " << mk_pp(lower, m) << "\n";
tout << "upper: " << mk_pp(upper, m) << "\n";);
mk_axiom(eqz, eq);
mk_axiom(eqz, lower);
mk_axiom(eqz, upper);
@ -814,6 +822,7 @@ namespace smt {
void theory_arith<Ext>::mk_bound_axioms(atom * a1) {
theory_var v = a1->get_var();
atoms & occs = m_var_occs[v];
//SASSERT(v != 15);
TRACE("mk_bound_axioms", tout << "add bound axioms for v" << v << " " << a1 << "\n";);
if (!get_context().is_searching()) {
//
@ -937,6 +946,8 @@ namespace smt {
template<typename Ext>
void theory_arith<Ext>::flush_bound_axioms() {
CTRACE("arith", !m_new_atoms.empty(), tout << "flush bound axioms\n";);
while (!m_new_atoms.empty()) {
ptr_vector<atom> atoms;
atoms.push_back(m_new_atoms.back());
@ -950,6 +961,10 @@ namespace smt {
--i;
}
}
TRACE("arith",
for (unsigned i = 0; i < atoms.size(); ++i) {
atoms[i]->display(*this, tout);
});
ptr_vector<atom> occs(m_var_occs[v]);
std::sort(atoms.begin(), atoms.end(), compare_atoms());
@ -1140,7 +1155,7 @@ namespace smt {
template<typename Ext>
void theory_arith<Ext>::assign_eh(bool_var v, bool is_true) {
TRACE("arith", tout << "v" << v << " " << is_true << "\n";);
TRACE("arith", tout << "p" << v << " := " << (is_true?"true":"false") << "\n";);
atom * a = get_bv2a(v);
if (!a) return;
SASSERT(get_context().get_assignment(a->get_bool_var()) != l_undef);
@ -1299,28 +1314,6 @@ namespace smt {
final_check_status theory_arith<Ext>::final_check_eh() {
TRACE("arith_eq_adapter_info", m_arith_eq_adapter.display_already_processed(tout););
TRACE("arith_final_check", display(tout););
#if 0
if (true /*m_params.m_smtlib_dump_lemmas*/) {
literal_buffer tmp;
for (unsigned i = 0; i < m_asserted_qhead; i++) {
bound * b = m_asserted_bounds[i];
if (b->is_atom()) {
atom* a = static_cast<atom*>(b);
bool_var bv = a->get_bool_var();
lbool is_true = get_context().get_assignment(bv);
if (is_true == l_true) {
tmp.push_back(literal(bv));
}
else if (is_true == l_false) {
tmp.push_back(~literal(bv));
}
}
}
get_context().display_lemma_as_smt_problem(tmp.size(), tmp.c_ptr(), false_literal, "QF_LIA");
}
#endif
if (!propagate_core())
return FC_CONTINUE;
@ -1530,6 +1523,7 @@ namespace smt {
m_branch_cut_counter(0),
m_eager_gcd(m_params.m_arith_eager_gcd),
m_final_check_idx(0),
m_antecedents_index(0),
m_var_value_table(DEFAULT_HASHTABLE_INITIAL_CAPACITY, var_value_hash(*this), var_value_eq(*this)),
m_liberal_final_check(true),
m_changed_assignment(false),
@ -2202,15 +2196,15 @@ namespace smt {
}
}
TRACE("sign_row_conflict", tout << "v" << x_i << " is_below: " << is_below << " delta: " << delta << "\n"; display_var(tout, x_i);
tout << "is_below_lower: " << below_lower(x_i) << ", is_above_upper: " << above_upper(x_i) << "\n";);
antecedents& ante = get_antecedents();
antecedents ante(*this);
explain_bound(r, idx, !is_below, delta, ante);
b->push_justification(ante, numeral(1), coeffs_enabled());
TRACE("sign_row_conflict", tout << "v" << x_i << " is_below: " << is_below << " delta: " << delta << "\n"; display_var(tout, x_i);
tout << "is_below_lower: " << below_lower(x_i) << ", is_above_upper: " << above_upper(x_i) << "\n";
ante.display(tout););
set_conflict(ante.lits().size(), ante.lits().c_ptr(),
ante.eqs().size(), ante.eqs().c_ptr(), ante, is_int(x_i), "farkas");
set_conflict(ante, ante, "farkas");
// display_bounds_in_smtlib();
}
@ -2348,11 +2342,11 @@ namespace smt {
template<typename Ext>
void theory_arith<Ext>::sign_bound_conflict(bound * b1, bound * b2) {
SASSERT(b1->get_var() == b2->get_var());
antecedents& ante = get_antecedents();
antecedents ante(*this);
b1->push_justification(ante, numeral(1), coeffs_enabled());
b2->push_justification(ante, numeral(1), coeffs_enabled());
set_conflict(ante.lits().size(), ante.lits().c_ptr(), ante.eqs().size(), ante.eqs().c_ptr(), ante, is_int(b1->get_var()), "farkas");
set_conflict(ante, ante, "farkas");
TRACE("arith_conflict", tout << "bound conflict v" << b1->get_var() << "\n";
tout << "bounds: " << b1 << " " << b2 << "\n";);
}
@ -2590,7 +2584,6 @@ namespace smt {
if (!relax_bounds() && (!ante.lits().empty() || !ante.eqs().empty()))
return;
context & ctx = get_context();
ante.reset(); // !!!!TBD: should equality ante also be reset here!!!!
row_entry const & entry = r[idx];
numeral coeff = entry.m_coeff;
if (relax_bounds()) {
@ -2695,7 +2688,6 @@ namespace smt {
template<typename Ext>
void theory_arith<Ext>::mk_implied_bound(row const & r, unsigned idx, bool is_lower, theory_var v, bound_kind kind, inf_numeral const & k) {
atoms const & as = m_var_occs[v];
antecedents& ante = get_antecedents();
inf_numeral const & epsilon = get_epsilon(v);
inf_numeral delta;
typename atoms::const_iterator it = as.begin();
@ -2716,7 +2708,7 @@ namespace smt {
}
TRACE("propagate_bounds", tout << "v" << v << " >= " << k << ", v" << v << " >= " << k2 << ", delta: " << delta << "\n";
display_row(tout, r););
assign_bound_literal(l, r, idx, is_lower, delta, ante);
assign_bound_literal(l, r, idx, is_lower, delta);
}
// v <= k k < k2 |- v < k2 |- not v >= k2
if (kind == B_UPPER && k < k2) {
@ -2732,7 +2724,7 @@ namespace smt {
if (delta.is_nonneg()) {
TRACE("propagate_bounds", tout << "v" << v << " <= " << k << ", not v" << v << " >= " << k2 << ", delta: " << delta << "\n";
display_row(tout, r););
assign_bound_literal(~l, r, idx, is_lower, delta, ante);
assign_bound_literal(~l, r, idx, is_lower, delta);
}
}
}
@ -2747,7 +2739,7 @@ namespace smt {
if (delta.is_nonneg()) {
TRACE("propagate_bounds", tout << "v" << v << " >= " << k << ", not v" << v << " <= " << k2 << ", delta: " << delta << "\n";
display_row(tout, r););
assign_bound_literal(~l, r, idx, is_lower, delta, ante);
assign_bound_literal(~l, r, idx, is_lower, delta);
}
}
// v <= k k <= k2 |- v <= k2
@ -2758,7 +2750,7 @@ namespace smt {
}
TRACE("propagate_bounds", tout << "v" << v << " <= " << k << ", v" << v << " <= " << k2 << ", delta: " << delta << "\n";
display_row(tout, r););
assign_bound_literal(l, r, idx, is_lower, delta, ante);
assign_bound_literal(l, r, idx, is_lower, delta);
}
}
}
@ -2766,28 +2758,34 @@ namespace smt {
}
template<typename Ext>
void theory_arith<Ext>::assign_bound_literal(literal l, row const & r, unsigned idx, bool is_lower, inf_numeral & delta, antecedents& ante) {
void theory_arith<Ext>::dump_lemmas(literal l, antecedents const& ante) {
context & ctx = get_context();
if (dump_lemmas()) {
TRACE("arith", ante.display(tout) << " --> "; ctx.display_detailed_literal(tout, l); tout << "\n";);
ctx.display_lemma_as_smt_problem(ante.lits().size(), ante.lits().c_ptr(),
ante.eqs().size(), ante.eqs().c_ptr(), l, 0);
}
}
template<typename Ext>
void theory_arith<Ext>::dump_lemmas(literal l, derived_bound const& ante) {
context & ctx = get_context();
if (dump_lemmas()) {
ctx.display_lemma_as_smt_problem(ante.lits().size(), ante.lits().c_ptr(),
ante.eqs().size(), ante.eqs().c_ptr(), l, 0);
}
}
template<typename Ext>
void theory_arith<Ext>::assign_bound_literal(literal l, row const & r, unsigned idx, bool is_lower, inf_numeral & delta) {
m_stats.m_bound_props++;
context & ctx = get_context();
antecedents ante(*this);
explain_bound(r, idx, is_lower, delta, ante);
if (dump_lemmas()) {
char const * logic = is_int(r.get_base_var()) ? "QF_LIA" : "QF_LRA";
ctx.display_lemma_as_smt_problem(ante.lits().size(), ante.lits().c_ptr(),
ante.eqs().size(), ante.eqs().c_ptr(), l, logic);
}
dump_lemmas(l, ante);
TRACE("propagate_bounds",
literal_vector::const_iterator it = ante.lits().begin();
literal_vector::const_iterator end = ante.lits().end();
for (; it != end; ++it) {
ctx.display_detailed_literal(tout, *it);
tout << " ";
}
eq_vector::const_iterator it2 = ante.eqs().begin();
eq_vector::const_iterator end2 = ante.eqs().end();
for (; it2 != end2; ++it2) {
tout << "#" << it2->first->get_owner_id() << "=#" << it2->second->get_owner_id() << " ";
}
tout << " --> ";
ante.display(tout) << " --> ";
ctx.display_detailed_literal(tout, l);
tout << "\n";);
if (ante.lits().size() < small_lemma_size() && ante.eqs().empty()) {
@ -2869,19 +2867,26 @@ namespace smt {
// Justification
//
// -----------------------------------
template<typename Ext>
void theory_arith<Ext>::set_conflict(antecedents const& ante, antecedents& bounds, char const* proof_rule) {
dump_lemmas(false_literal, ante);
set_conflict(ante.lits().size(), ante.lits().c_ptr(), ante.eqs().size(), ante.eqs().c_ptr(), bounds, proof_rule);
}
template<typename Ext>
void theory_arith<Ext>::set_conflict(derived_bound const& ante, antecedents& bounds, char const* proof_rule) {
dump_lemmas(false_literal, ante);
set_conflict(ante.lits().size(), ante.lits().c_ptr(), ante.eqs().size(), ante.eqs().c_ptr(), bounds, proof_rule);
}
template<typename Ext>
void theory_arith<Ext>::set_conflict(unsigned num_literals, literal const * lits, unsigned num_eqs, enode_pair const * eqs,
antecedents& bounds, bool is_lia, char const* proof_rule) {
void theory_arith<Ext>::set_conflict(unsigned num_literals, literal const * lits, unsigned num_eqs, enode_pair const * eqs,
antecedents& bounds, char const* proof_rule) {
SASSERT(num_literals != 0 || num_eqs != 0);
context & ctx = get_context();
m_stats.m_conflicts++;
m_num_conflicts++;
if (dump_lemmas()) {
char const * logic = is_lia ? "QF_LIA" : "QF_LRA";
ctx.display_lemma_as_smt_problem(num_literals, lits, num_eqs, eqs, false_literal, logic);
}
region & r = ctx.get_region();
TRACE("arith_conflict",
for (unsigned i = 0; i < num_literals; i++) {
ctx.display_detailed_literal(tout, lits[i]);
@ -2903,7 +2908,7 @@ namespace smt {
record_conflict(num_literals, lits, num_eqs, eqs, bounds.num_params(), bounds.params(proof_rule));
ctx.set_conflict(
ctx.mk_justification(
ext_theory_conflict_justification(get_id(), r, num_literals, lits, num_eqs, eqs,
ext_theory_conflict_justification(get_id(), ctx.get_region(), num_literals, lits, num_eqs, eqs,
bounds.num_params(), bounds.params(proof_rule))));
}
@ -3315,11 +3320,20 @@ namespace smt {
*/
template<typename Ext>
typename theory_arith<Ext>::antecedents& theory_arith<Ext>::get_antecedents() {
m_tmp_antecedents.reset();
return m_tmp_antecedents;
theory_arith<Ext>::antecedents::antecedents(theory_arith& th):
th(th),
a(th.m_antecedents[th.m_antecedents_index]) {
SASSERT(th.m_antecedents_index < 3);
a.reset();
++th.m_antecedents_index;
}
template<typename Ext>
theory_arith<Ext>::antecedents::~antecedents() {
--th.m_antecedents_index;
}
};
#endif /* THEORY_ARITH_CORE_H_ */

View file

@ -52,7 +52,7 @@ namespace smt {
// contain invalid (key -> value) pairs. So, we must check whether v2 is really equal to val (previous test) AND it has
// the same sort of v. The following test was missing in a previous version of Z3.
if (!is_equal(v, v2) && is_int(v) == is_int(v2)) {
antecedents& ante = get_antecedents();
antecedents ante(*this);
//
// v <= k <= v2 => v <= v2
@ -241,7 +241,7 @@ namespace smt {
is_int(x) == is_int(x2) &&
!is_equal(x, x2)) {
antecedents& ante = get_antecedents();
antecedents ante(*this);
collect_fixed_var_justifications(r, ante);
//
@ -256,7 +256,7 @@ namespace smt {
if (k.is_zero() && y != null_theory_var && !is_equal(x, y) && is_int(x) == is_int(y)) {
// found equality x = y
antecedents& ante = get_antecedents();
antecedents ante(*this);
collect_fixed_var_justifications(r, ante);
TRACE("propagate_cheap_eq", tout << "propagate eq using x-y=0 row:\n"; display_row_info(tout, r););
m_stats.m_offset_eqs++;
@ -296,7 +296,7 @@ namespace smt {
if (new_eq) {
if (!is_equal(x, x2) && is_int(x) == is_int(x2)) {
SASSERT(y == y2 && k == k2);
antecedents& ante = get_antecedents();
antecedents ante(*this);
collect_fixed_var_justifications(r, ante);
collect_fixed_var_justifications(r2, ante);
TRACE("propagate_cheap_eq", tout << "propagate eq two rows:\n";

View file

@ -201,12 +201,13 @@ namespace smt {
SASSERT(is_int(v));
SASSERT(!get_value(v).is_int());
m_stats.m_branches++;
TRACE("arith_branching", tout << "branching v" << v << " = " << get_value(v) << "\n";
TRACE("arith_int", tout << "branching v" << v << " = " << get_value(v) << "\n";
display_var(tout, v););
numeral k = ceil(get_value(v));
rational _k = k.to_rational();
expr * bound = m_util.mk_ge(get_enode(v)->get_owner(), m_util.mk_numeral(_k, true));
TRACE("arith_branching", tout << mk_bounded_pp(bound, get_manager()) << "\n";);
expr_ref bound(get_manager());
bound = m_util.mk_ge(get_enode(v)->get_owner(), m_util.mk_numeral(_k, true));
TRACE("arith_int", tout << mk_bounded_pp(bound, get_manager()) << "\n";);
context & ctx = get_context();
ctx.internalize(bound, true);
ctx.mark_as_relevant(bound);
@ -452,11 +453,11 @@ namespace smt {
expr_ref pol(m);
pol = m_util.mk_add(_args.size(), _args.c_ptr());
result = m_util.mk_ge(pol, m_util.mk_numeral(k, all_int));
TRACE("arith_mk_polynomial", tout << "before simplification:\n" << mk_pp(pol, m) << "\n";);
TRACE("arith_mk_polynomial", tout << "before simplification:\n" << result << "\n";);
simplifier & s = get_context().get_simplifier();
proof_ref pr(m);
s(result, result, pr);
TRACE("arith_mk_polynomial", tout << "after simplification:\n" << mk_pp(pol, m) << "\n";);
TRACE("arith_mk_polynomial", tout << "after simplification:\n" << result << "\n";);
SASSERT(is_well_sorted(get_manager(), result));
}
@ -498,7 +499,7 @@ namespace smt {
TRACE("gomory_cut", tout << "applying cut at:\n"; display_row_info(tout, r););
antecedents& ante = get_antecedents();
antecedents ante(*this);
m_stats.m_gomory_cuts++;
@ -508,6 +509,8 @@ namespace smt {
numeral f_0 = Ext::fractional_part(m_value[x_i]);
numeral one_minus_f_0 = numeral(1) - f_0;
SASSERT(!f_0.is_zero());
SASSERT(!one_minus_f_0.is_zero());
numeral lcm_den(1);
unsigned num_ints = 0;
@ -521,36 +524,30 @@ namespace smt {
a_ij.neg(); // make the used format compatible with the format used in: Integrating Simplex with DPLL(T)
if (is_real(x_j)) {
numeral new_a_ij;
TRACE("gomory_cut_detail", tout << a_ij << "*v" << x_j << "\n";);
if (at_lower(x_j)) {
if (a_ij.is_pos()) {
new_a_ij = a_ij / one_minus_f_0;
}
else {
TRUSTME(!f_0.is_zero());
new_a_ij = a_ij / f_0;
new_a_ij.neg();
}
// k += new_a_ij * lower_bound(x_j).get_rational();
k.addmul(new_a_ij, lower_bound(x_j).get_rational());
lower(x_j)->push_justification(ante, new_a_ij, coeffs_enabled());
}
else {
SASSERT(at_upper(x_j));
if (a_ij.is_pos()) {
TRUSTME(!f_0.is_zero());
new_a_ij = a_ij / f_0;
new_a_ij.neg(); // the upper terms are inverted.
}
else {
// new_a_ij = - a_ij / one_minus_f_0
// new_a_ij.neg() // the upper terms are inverted
new_a_ij = a_ij / one_minus_f_0;
new_a_ij = a_ij / one_minus_f_0;
}
// k += new_a_ij * upper_bound(x_j).get_rational();
k.addmul(new_a_ij, upper_bound(x_j).get_rational());
upper(x_j)->push_justification(ante, new_a_ij, coeffs_enabled());
}
TRACE("gomory_cut_detail", tout << a_ij << "*v" << x_j << " k: " << k << "\n";);
pol.push_back(row_entry(new_a_ij, x_j));
}
else {
@ -572,7 +569,6 @@ namespace smt {
else {
new_a_ij = (numeral(1) - f_j) / f_0;
}
// k += new_a_ij * lower_bound(x_j).get_rational();
k.addmul(new_a_ij, lower_bound(x_j).get_rational());
lower(x_j)->push_justification(ante, new_a_ij, coeffs_enabled());
}
@ -585,11 +581,10 @@ namespace smt {
new_a_ij = (numeral(1) - f_j) / one_minus_f_0;
}
new_a_ij.neg(); // the upper terms are inverted
// k += new_a_ij * upper_bound(x_j).get_rational();
k.addmul(new_a_ij, upper_bound(x_j).get_rational());
upper(x_j)->push_justification(ante, new_a_ij, coeffs_enabled());
}
TRACE("gomory_cut_detail", tout << "new_a_ij: " << new_a_ij << "\n";);
TRACE("gomory_cut_detail", tout << "new_a_ij: " << new_a_ij << " k: " << k << "\n";);
pol.push_back(row_entry(new_a_ij, x_j));
lcm_den = lcm(lcm_den, denominator(new_a_ij));
}
@ -603,7 +598,7 @@ namespace smt {
if (pol.empty()) {
SASSERT(k.is_pos());
// conflict 0 >= k where k is positive
set_conflict(ante.lits().size(), ante.lits().c_ptr(), ante.eqs().size(), ante.eqs().c_ptr(), ante, true, "gomory-cut");
set_conflict(ante, ante, "gomory-cut");
return true;
}
else if (pol.size() == 1) {
@ -639,18 +634,19 @@ namespace smt {
}
TRACE("gomory_cut_detail", tout << "after *lcm\n";
for (unsigned i = 0; i < pol.size(); i++) {
tout << pol[i].m_coeff << " " << pol[i].m_var << "\n";
tout << pol[i].m_coeff << " * v" << pol[i].m_var << "\n";
}
tout << "k: " << k << "\n";);
}
mk_polynomial_ge(pol.size(), pol.c_ptr(), k.to_rational(), bound);
}
TRACE("gomory_cut", tout << "new cut:\n" << mk_pp(bound, get_manager()) << "\n";);
TRACE("gomory_cut", tout << "new cut:\n" << bound << "\n"; ante.display(tout););
literal l = null_literal;
context & ctx = get_context();
ctx.internalize(bound, true);
l = ctx.get_literal(bound);
ctx.mark_as_relevant(l);
dump_lemmas(l, ante);
ctx.assign(l, ctx.mk_justification(
gomory_cut_justification(
get_id(), ctx.get_region(),
@ -721,7 +717,7 @@ namespace smt {
if (!(consts / gcds).is_int()) {
TRACE("gcd_test", tout << "row failed the GCD test:\n"; display_row_info(tout, r););
antecedents& ante = get_antecedents();
antecedents ante(*this);
collect_fixed_var_justifications(r, ante);
context & ctx = get_context();
ctx.set_conflict(
@ -754,7 +750,7 @@ namespace smt {
numeral l(consts);
numeral u(consts);
antecedents& ante = get_antecedents();
antecedents ante(*this);
typename vector<row_entry>::const_iterator it = r.begin_entries();

View file

@ -1910,11 +1910,10 @@ namespace smt {
*/
template<typename Ext>
void theory_arith<Ext>::set_conflict(v_dependency * d) {
bool is_lia = false; // TODO: fix it, but this is only used for debugging.
antecedents& ante = get_antecedents();
antecedents ante(*this);
derived_bound b(null_theory_var, inf_numeral(0), B_LOWER);
dependency2new_bound(d, b);
set_conflict(b.m_lits.size(), b.m_lits.c_ptr(), b.m_eqs.size(), b.m_eqs.c_ptr(), ante, is_lia, "arith_nl");
set_conflict(b, ante, "arith_nl");
TRACE("non_linear",
for (unsigned i = 0; i < b.m_lits.size(); ++i) {
tout << b.m_lits[i] << " ";

View file

@ -399,6 +399,18 @@ namespace smt {
out << "\n";
}
template<typename Ext>
std::ostream& theory_arith<Ext>::antecedents_t::display(theory_arith& th, std::ostream & out) const {
th.get_context().display_literals_verbose(out, lits().size(), lits().c_ptr());
if (!lits().empty()) out << "\n";
ast_manager& m = th.get_manager();
for (unsigned i = 0; i < m_eqs.size(); ++i) {
out << mk_pp(m_eqs[i].first->get_owner(), m) << " ";
out << mk_pp(m_eqs[i].second->get_owner(), m) << "\n";
}
return out;
}
template<typename Ext>
void theory_arith<Ext>::display_deps(std::ostream & out, v_dependency* dep) {
ptr_vector<void> bounds;

View file

@ -204,7 +204,7 @@ struct scoped_timer::imp {
throw default_exception("failed to destroy pthread attributes object");
#elif defined(_LINUX_) || defined(_FREEBSD_)
// Linux & FreeBSD
timer_delete(m_timerid);
timer_delete(m_timerid);
#else
// Other Platforms
#endif