3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-08 10:25:18 +00:00

partition inequalities into conjuncts determined by equivalence classes of shared variables

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2013-09-10 22:23:09 -07:00
parent f4aae5e56a
commit f4e048c1e8

View file

@ -46,6 +46,9 @@ namespace pdr {
app_ref_vector m_ineqs;
vector<rational> m_coeffs;
unsigned m_time;
unsigned_vector m_roots, m_size, m_his, m_reps, m_ts;
void mk_coerce(expr*& e1, expr*& e2) {
if (a.is_int(e1) && a.is_real(e2)) {
e1 = a.mk_to_real(e1);
@ -146,7 +149,7 @@ namespace pdr {
}
public:
constr(ast_manager& m) : m(m), a(m), m_ineqs(m) {}
constr(ast_manager& m) : m(m), a(m), m_ineqs(m), m_time(0) {}
/** add a multiple of constraint c to the current constr */
void add(rational const & coef, app * c) {
@ -180,12 +183,133 @@ namespace pdr {
tout << m_coeffs[i] << ": " << mk_pp(m_ineqs[i].get(), m) << "\n";
}
);
res = extract_consequence(0, m_coeffs.size());
#if 1
// partition equalities into variable disjoint sets.
// take the conjunction of these instead of the
// linear combination.
partition_ineqs();
expr_ref_vector lits(m);
unsigned lo = 0;
for (unsigned i = 0; i < m_his.size(); ++i) {
unsigned hi = m_his[i];
lits.push_back(extract_consequence(lo, hi));
lo = hi;
}
res = qe::mk_or(lits);
IF_VERBOSE(2, { if (lits.size() > 1) { verbose_stream() << "combined lemma: " << mk_pp(res, m) << "\n"; } });
#endif
}
private:
// partition inequalities into variable disjoint sets.
void partition_ineqs() {
m_roots.reset();
m_size.reset();
m_reps.reset();
m_his.reset();
++m_time;
for (unsigned i = 0; i < m_ineqs.size(); ++i) {
m_reps.push_back(process_term(m_ineqs[i].get()));
}
unsigned head = 0;
while (head < m_ineqs.size()) {
unsigned r = find(m_reps[head]);
unsigned tail = head;
for (unsigned i = head+1; i < m_ineqs.size(); ++i) {
if (find(m_reps[i]) == r) {
++tail;
if (tail != i) {
SASSERT(tail < i);
std::swap(m_reps[tail], m_reps[i]);
app_ref tmp(m);
tmp = m_ineqs[i].get();
m_ineqs[i] = m_ineqs[tail].get();
m_ineqs[tail] = tmp;
std::swap(m_coeffs[tail], m_coeffs[i]);
}
}
}
head = tail + 1;
m_his.push_back(head);
}
}
unsigned find(unsigned idx) {
if (m_ts.size() <= idx) {
m_roots.resize(idx+1);
m_size.resize(idx+1);
m_ts.resize(idx+1);
m_roots[idx] = idx;
m_ts[idx] = m_time;
m_size[idx] = 1;
return idx;
}
if (m_ts[idx] != m_time) {
m_size[idx] = 1;
m_ts[idx] = m_time;
m_roots[idx] = idx;
return idx;
}
while (true) {
if (m_roots[idx] == idx) {
return idx;
}
idx = m_roots[idx];
}
}
void merge(unsigned i, unsigned j) {
i = find(i);
j = find(j);
if (i == j) {
return;
}
if (m_size[i] > m_size[j]) {
std::swap(i, j);
}
m_roots[i] = j;
m_size[j] += m_size[i];
}
unsigned process_term(expr* e) {
unsigned r = e->get_id();
ptr_vector<expr> todo;
ast_mark mark;
todo.push_back(e);
while (!todo.empty()) {
e = todo.back();
todo.pop_back();
if (mark.is_marked(e)) {
continue;
}
mark.mark(e, true);
if (is_uninterp(e)) {
merge(r, e->get_id());
}
if (is_app(e)) {
app* a = to_app(e);
for (unsigned i = 0; i < a->get_num_args(); ++i) {
todo.push_back(a->get_arg(i));
}
}
}
return r;
}
expr_ref extract_consequence(unsigned lo, unsigned hi) {
bool is_int = is_int_sort();
app_ref zero(a.mk_numeral(rational::zero(), is_int), m);
expr_ref res(m);
res = zero;
bool is_strict = false;
bool is_eq = true;
expr* x, *y;
for (unsigned i = 0; i < m_coeffs.size(); ++i) {
for (unsigned i = lo; i < hi; ++i) {
app* c = m_ineqs[i].get();
if (m.is_eq(c, x, y)) {
mul(m_coeffs[i], x, res);
@ -220,12 +344,12 @@ namespace pdr {
params.set_bool("gcd_rounding", true);
rw.updt_params(params);
proof_ref pr(m);
expr_ref tmp(m);
rw(res, tmp, pr);
fix_dl(tmp);
res = tmp;
expr_ref result(m);
rw(res, result, pr);
fix_dl(result);
return result;
}
// patch: swap addends to make static
// features recognize difference constraint.
void fix_dl(expr_ref& r) {