mirror of
https://github.com/Z3Prover/z3
synced 2025-06-06 22:23:22 +00:00
fix solve bug
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
3178f7f86d
commit
fee7828b51
2 changed files with 68 additions and 36 deletions
|
@ -175,8 +175,7 @@ namespace opt {
|
||||||
rational new_x_val;
|
rational new_x_val;
|
||||||
rational x_coeff, eps(0);
|
rational x_coeff, eps(0);
|
||||||
vector<var> const& vars = r.m_vars;
|
vector<var> const& vars = r.m_vars;
|
||||||
for (unsigned j = 0; j < vars.size(); ++j) {
|
for (var const& v : vars) {
|
||||||
var const& v = vars[j];
|
|
||||||
if (x == v.m_id) {
|
if (x == v.m_id) {
|
||||||
x_coeff = v.m_coeff;
|
x_coeff = v.m_coeff;
|
||||||
}
|
}
|
||||||
|
@ -227,8 +226,7 @@ namespace opt {
|
||||||
--i;
|
--i;
|
||||||
unsigned x = bound_vars[i];
|
unsigned x = bound_vars[i];
|
||||||
unsigned_vector const& row_ids = m_var2row_ids[x];
|
unsigned_vector const& row_ids = m_var2row_ids[x];
|
||||||
for (unsigned j = 0; j < row_ids.size(); ++j) {
|
for (unsigned row_id : row_ids) {
|
||||||
unsigned row_id = row_ids[j];
|
|
||||||
row & r = m_rows[row_id];
|
row & r = m_rows[row_id];
|
||||||
r.m_value = get_row_value(r);
|
r.m_value = get_row_value(r);
|
||||||
SASSERT(invariant(row_id, r));
|
SASSERT(invariant(row_id, r));
|
||||||
|
@ -368,7 +366,7 @@ namespace opt {
|
||||||
tout << a1 << " " << a2 << ": ";
|
tout << a1 << " " << a2 << ": ";
|
||||||
display(tout, m_rows[row_dst]);
|
display(tout, m_rows[row_dst]);
|
||||||
display(tout, m_rows[row_src]););
|
display(tout, m_rows[row_src]););
|
||||||
if (a1.is_pos() != a2.is_pos()) {
|
if (a1.is_pos() != a2.is_pos() || m_rows[row_src].m_type == opt::t_eq) {
|
||||||
mul_add(x, a1, row_src, a2, row_dst);
|
mul_add(x, a1, row_src, a2, row_dst);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
@ -384,6 +382,18 @@ namespace opt {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void model_based_opt::solve(unsigned row_src, rational const& a1, unsigned row_dst, unsigned x) {
|
||||||
|
SASSERT(a1 == get_coefficient(row_src, x));
|
||||||
|
SASSERT(a1.is_pos());
|
||||||
|
SASSERT(row_src != row_dst);
|
||||||
|
SASSERT(m_rows[row_src].m_type == t_eq);
|
||||||
|
if (!m_rows[row_dst].m_alive) return;
|
||||||
|
rational a2 = get_coefficient(row_dst, x);
|
||||||
|
mul(row_dst, a1);
|
||||||
|
mul_add(false, row_dst, -a2, row_src);
|
||||||
|
SASSERT(get_coefficient(row_dst, x).is_zero());
|
||||||
|
}
|
||||||
|
|
||||||
// resolution for integer rows.
|
// resolution for integer rows.
|
||||||
void model_based_opt::mul_add(
|
void model_based_opt::mul_add(
|
||||||
unsigned x, rational const& src_c, unsigned row_src, rational const& dst_c, unsigned row_dst) {
|
unsigned x, rational const& src_c, unsigned row_src, rational const& dst_c, unsigned row_dst) {
|
||||||
|
@ -457,8 +467,8 @@ namespace opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_based_opt::mk_coeffs_without(vector<var>& dst, vector<var> const src, unsigned x) {
|
void model_based_opt::mk_coeffs_without(vector<var>& dst, vector<var> const src, unsigned x) {
|
||||||
for (unsigned i = 0; i < src.size(); ++i) {
|
for (var const & v : src) {
|
||||||
if (src[i].m_id != x) dst.push_back(src[i]);
|
if (v.m_id != x) dst.push_back(v);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -469,8 +479,8 @@ namespace opt {
|
||||||
void model_based_opt::mul(unsigned dst, rational const& c) {
|
void model_based_opt::mul(unsigned dst, rational const& c) {
|
||||||
if (c.is_one()) return;
|
if (c.is_one()) return;
|
||||||
row& r = m_rows[dst];
|
row& r = m_rows[dst];
|
||||||
for (unsigned i = 0; i < r.m_vars.size(); ++i) {
|
for (auto & v : r.m_vars) {
|
||||||
r.m_vars[i].m_coeff *= c;
|
v.m_coeff *= c;
|
||||||
}
|
}
|
||||||
r.m_coeff *= c;
|
r.m_coeff *= c;
|
||||||
r.m_value *= c;
|
r.m_value *= c;
|
||||||
|
@ -674,8 +684,8 @@ namespace opt {
|
||||||
unsigned dst = new_row();
|
unsigned dst = new_row();
|
||||||
row const& r = m_rows[src];
|
row const& r = m_rows[src];
|
||||||
set_row(dst, r.m_vars, r.m_coeff, r.m_mod, r.m_type);
|
set_row(dst, r.m_vars, r.m_coeff, r.m_mod, r.m_type);
|
||||||
for (unsigned i = 0; i < r.m_vars.size(); ++i) {
|
for (auto const& v : r.m_vars) {
|
||||||
m_var2row_ids[r.m_vars[i].m_id].push_back(dst);
|
m_var2row_ids[v.m_id].push_back(dst);
|
||||||
}
|
}
|
||||||
SASSERT(invariant(dst, m_rows[dst]));
|
SASSERT(invariant(dst, m_rows[dst]));
|
||||||
return dst;
|
return dst;
|
||||||
|
@ -692,8 +702,8 @@ namespace opt {
|
||||||
void model_based_opt::add_constraint(vector<var> const& coeffs, rational const& c, rational const& m, ineq_type rel) {
|
void model_based_opt::add_constraint(vector<var> const& coeffs, rational const& c, rational const& m, ineq_type rel) {
|
||||||
unsigned row_id = new_row();
|
unsigned row_id = new_row();
|
||||||
set_row(row_id, coeffs, c, m, rel);
|
set_row(row_id, coeffs, c, m, rel);
|
||||||
for (unsigned i = 0; i < coeffs.size(); ++i) {
|
for (var const& coeff : coeffs) {
|
||||||
m_var2row_ids[coeffs[i].m_id].push_back(row_id);
|
m_var2row_ids[coeff.m_id].push_back(row_id);
|
||||||
}
|
}
|
||||||
SASSERT(invariant(row_id, m_rows[row_id]));
|
SASSERT(invariant(row_id, m_rows[row_id]));
|
||||||
}
|
}
|
||||||
|
@ -703,9 +713,9 @@ namespace opt {
|
||||||
}
|
}
|
||||||
|
|
||||||
void model_based_opt::get_live_rows(vector<row>& rows) {
|
void model_based_opt::get_live_rows(vector<row>& rows) {
|
||||||
for (unsigned i = 0; i < m_rows.size(); ++i) {
|
for (row const& r : m_rows) {
|
||||||
if (m_rows[i].m_alive) {
|
if (r.m_alive) {
|
||||||
rows.push_back(m_rows[i]);
|
rows.push_back(r);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -742,9 +752,9 @@ namespace opt {
|
||||||
glb_rows.reset();
|
glb_rows.reset();
|
||||||
mod_rows.reset();
|
mod_rows.reset();
|
||||||
bool lub_is_unit = false, glb_is_unit = false;
|
bool lub_is_unit = false, glb_is_unit = false;
|
||||||
|
unsigned eq_row = UINT_MAX;
|
||||||
// select the lub and glb.
|
// select the lub and glb.
|
||||||
for (unsigned i = 0; i < row_ids.size(); ++i) {
|
for (unsigned row_id : row_ids) {
|
||||||
unsigned row_id = row_ids[i];
|
|
||||||
if (visited.contains(row_id)) {
|
if (visited.contains(row_id)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
@ -758,8 +768,8 @@ namespace opt {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (r.m_type == t_eq) {
|
if (r.m_type == t_eq) {
|
||||||
solve_for(row_id, x);
|
eq_row = row_id;
|
||||||
return;
|
continue;
|
||||||
}
|
}
|
||||||
if (r.m_type == t_mod) {
|
if (r.m_type == t_mod) {
|
||||||
mod_rows.push_back(row_id);
|
mod_rows.push_back(row_id);
|
||||||
|
@ -796,6 +806,11 @@ namespace opt {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (eq_row != UINT_MAX) {
|
||||||
|
solve_for(eq_row, x);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
unsigned lub_size = lub_rows.size();
|
unsigned lub_size = lub_rows.size();
|
||||||
unsigned glb_size = glb_rows.size();
|
unsigned glb_size = glb_rows.size();
|
||||||
unsigned row_index = (lub_size <= glb_size) ? lub_index : glb_index;
|
unsigned row_index = (lub_size <= glb_size) ? lub_index : glb_index;
|
||||||
|
@ -803,8 +818,7 @@ namespace opt {
|
||||||
|
|
||||||
// There are only upper or only lower bounds.
|
// There are only upper or only lower bounds.
|
||||||
if (row_index == UINT_MAX) {
|
if (row_index == UINT_MAX) {
|
||||||
for (unsigned i = 0; i < glb_rows.size(); ++i) {
|
for (unsigned row_id : glb_rows) {
|
||||||
unsigned row_id = glb_rows[i];
|
|
||||||
SASSERT(m_rows[row_id].m_alive);
|
SASSERT(m_rows[row_id].m_alive);
|
||||||
SASSERT(!get_coefficient(row_id, x).is_zero());
|
SASSERT(!get_coefficient(row_id, x).is_zero());
|
||||||
retire_row(row_id);
|
retire_row(row_id);
|
||||||
|
@ -839,8 +853,7 @@ namespace opt {
|
||||||
|
|
||||||
// General case.
|
// General case.
|
||||||
rational coeff = get_coefficient(row_index, x);
|
rational coeff = get_coefficient(row_index, x);
|
||||||
for (unsigned i = 0; i < glb_rows.size(); ++i) {
|
for (unsigned row_id : glb_rows) {
|
||||||
unsigned row_id = glb_rows[i];
|
|
||||||
if (row_id != row_index) {
|
if (row_id != row_index) {
|
||||||
resolve(row_index, coeff, row_id, x);
|
resolve(row_index, coeff, row_id, x);
|
||||||
}
|
}
|
||||||
|
@ -866,8 +879,8 @@ namespace opt {
|
||||||
void model_based_opt::solve_mod(unsigned x, unsigned_vector const& mod_rows) {
|
void model_based_opt::solve_mod(unsigned x, unsigned_vector const& mod_rows) {
|
||||||
SASSERT(!mod_rows.empty());
|
SASSERT(!mod_rows.empty());
|
||||||
rational D(1);
|
rational D(1);
|
||||||
for (unsigned i = 0; i < mod_rows.size(); ++i) {
|
for (unsigned idx : mod_rows) {
|
||||||
D = lcm(D, m_rows[mod_rows[i]].m_mod);
|
D = lcm(D, m_rows[idx].m_mod);
|
||||||
}
|
}
|
||||||
if (D.is_zero()) {
|
if (D.is_zero()) {
|
||||||
throw default_exception("modulo 0 is not defined");
|
throw default_exception("modulo 0 is not defined");
|
||||||
|
@ -876,9 +889,9 @@ namespace opt {
|
||||||
rational val_x = m_var2value[x];
|
rational val_x = m_var2value[x];
|
||||||
rational u = mod(val_x, D);
|
rational u = mod(val_x, D);
|
||||||
SASSERT(u.is_nonneg() && u < D);
|
SASSERT(u.is_nonneg() && u < D);
|
||||||
for (unsigned i = 0; i < mod_rows.size(); ++i) {
|
for (unsigned idx : mod_rows) {
|
||||||
replace_var(mod_rows[i], x, u);
|
replace_var(idx, x, u);
|
||||||
SASSERT(invariant(mod_rows[i], m_rows[mod_rows[i]]));
|
SASSERT(invariant(idx, m_rows[idx]));
|
||||||
}
|
}
|
||||||
//
|
//
|
||||||
// update inequalities such that u is added to t and
|
// update inequalities such that u is added to t and
|
||||||
|
@ -894,8 +907,7 @@ namespace opt {
|
||||||
unsigned y = add_var(new_val, true);
|
unsigned y = add_var(new_val, true);
|
||||||
unsigned_vector const& row_ids = m_var2row_ids[x];
|
unsigned_vector const& row_ids = m_var2row_ids[x];
|
||||||
uint_set visited;
|
uint_set visited;
|
||||||
for (unsigned i = 0; i < row_ids.size(); ++i) {
|
for (unsigned row_id : row_ids) {
|
||||||
unsigned row_id = row_ids[i];
|
|
||||||
if (!visited.contains(row_id)) {
|
if (!visited.contains(row_id)) {
|
||||||
// x |-> D*y + u
|
// x |-> D*y + u
|
||||||
replace_var(row_id, x, D, y, u);
|
replace_var(row_id, x, D, y, u);
|
||||||
|
@ -954,23 +966,39 @@ namespace opt {
|
||||||
SASSERT(!a.is_zero());
|
SASSERT(!a.is_zero());
|
||||||
SASSERT(m_rows[row_id1].m_type == t_eq);
|
SASSERT(m_rows[row_id1].m_type == t_eq);
|
||||||
SASSERT(m_rows[row_id1].m_alive);
|
SASSERT(m_rows[row_id1].m_alive);
|
||||||
if (m_var2is_int[x] && !abs(a).is_one()) {
|
if (a.is_neg()) {
|
||||||
|
a.neg();
|
||||||
|
m_rows[row_id1].neg();
|
||||||
|
}
|
||||||
|
SASSERT(a.is_pos());
|
||||||
|
if (m_var2is_int[x] && !a.is_one()) {
|
||||||
row& r1 = m_rows[row_id1];
|
row& r1 = m_rows[row_id1];
|
||||||
vector<var> coeffs;
|
vector<var> coeffs;
|
||||||
mk_coeffs_without(coeffs, r1.m_vars, x);
|
mk_coeffs_without(coeffs, r1.m_vars, x);
|
||||||
rational c = r1.m_coeff;
|
rational c = r1.m_coeff;
|
||||||
add_divides(coeffs, c, abs(a));
|
add_divides(coeffs, c, a);
|
||||||
}
|
}
|
||||||
unsigned_vector const& row_ids = m_var2row_ids[x];
|
unsigned_vector const& row_ids = m_var2row_ids[x];
|
||||||
uint_set visited;
|
uint_set visited;
|
||||||
visited.insert(row_id1);
|
visited.insert(row_id1);
|
||||||
for (unsigned i = 0; i < row_ids.size(); ++i) {
|
for (unsigned row_id2 : row_ids) {
|
||||||
unsigned row_id2 = row_ids[i];
|
|
||||||
if (!visited.contains(row_id2)) {
|
if (!visited.contains(row_id2)) {
|
||||||
visited.insert(row_id2);
|
visited.insert(row_id2);
|
||||||
|
|
||||||
b = get_coefficient(row_id2, x);
|
b = get_coefficient(row_id2, x);
|
||||||
if (!b.is_zero()) {
|
if (!b.is_zero()) {
|
||||||
resolve(row_id1, a, row_id2, x);
|
row& dst = m_rows[row_id2];
|
||||||
|
switch (dst.m_type) {
|
||||||
|
case t_eq:
|
||||||
|
case t_lt:
|
||||||
|
case t_le:
|
||||||
|
solve(row_id1, a, row_id2, x);
|
||||||
|
break;
|
||||||
|
case t_mod:
|
||||||
|
// mod reduction already done.
|
||||||
|
UNREACHABLE();
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,6 +58,8 @@ namespace opt {
|
||||||
rational m_value; // value of m_vars + m_coeff under interpretation of m_var2value.
|
rational m_value; // value of m_vars + m_coeff under interpretation of m_var2value.
|
||||||
bool m_alive; // rows can be marked dead if they have been processed.
|
bool m_alive; // rows can be marked dead if they have been processed.
|
||||||
void reset() { m_vars.reset(); m_coeff.reset(); m_value.reset(); }
|
void reset() { m_vars.reset(); m_coeff.reset(); m_value.reset(); }
|
||||||
|
|
||||||
|
void neg() { for (var & v : m_vars) v.m_coeff.neg(); m_coeff.neg(); m_value.neg(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -85,6 +87,8 @@ namespace opt {
|
||||||
|
|
||||||
void resolve(unsigned row_src, rational const& a1, unsigned row_dst, unsigned x);
|
void resolve(unsigned row_src, rational const& a1, unsigned row_dst, unsigned x);
|
||||||
|
|
||||||
|
void solve(unsigned row_src, rational const& a1, unsigned row_dst, unsigned x);
|
||||||
|
|
||||||
void mul_add(bool same_sign, unsigned row_id1, rational const& c, unsigned row_id2);
|
void mul_add(bool same_sign, unsigned row_id1, rational const& c, unsigned row_id2);
|
||||||
|
|
||||||
void mul_add(unsigned x, rational const& a1, unsigned row_src, rational const& a2, unsigned row_dst);
|
void mul_add(unsigned x, rational const& a1, unsigned row_src, rational const& a2, unsigned row_dst);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue