mirror of
https://github.com/Z3Prover/z3
synced 2025-10-08 17:01:55 +00:00
logging and bug fixes
This commit is contained in:
parent
c621f59740
commit
72f5fe1f7f
3 changed files with 69 additions and 28 deletions
|
@ -1554,6 +1554,7 @@ namespace lp {
|
||||||
|
|
||||||
mpq lar_solver::get_value(lpvar j) const {
|
mpq lar_solver::get_value(lpvar j) const {
|
||||||
SASSERT(get_status() == lp_status::OPTIMAL || get_status() == lp_status::FEASIBLE);
|
SASSERT(get_status() == lp_status::OPTIMAL || get_status() == lp_status::FEASIBLE);
|
||||||
|
SASSERT(m_imp->m_columns_with_changed_bounds.empty());
|
||||||
VERIFY(m_imp->m_columns_with_changed_bounds.empty());
|
VERIFY(m_imp->m_columns_with_changed_bounds.empty());
|
||||||
numeric_pair<mpq> const& rp = get_column_value(j);
|
numeric_pair<mpq> const& rp = get_column_value(j);
|
||||||
return from_model_in_impq_to_mpq(rp);
|
return from_model_in_impq_to_mpq(rp);
|
||||||
|
|
|
@ -231,19 +231,19 @@ namespace nla {
|
||||||
bound_justifications bounds;
|
bound_justifications bounds;
|
||||||
lbool sign = add_bounds(vars, bounds);
|
lbool sign = add_bounds(vars, bounds);
|
||||||
VERIFY(sign == l_undef);
|
VERIFY(sign == l_undef);
|
||||||
add_ineq(bounds, j, lp::lconstraint_kind::EQ, rational(0));
|
add_ineq("signs = 0", bounds, j, lp::lconstraint_kind::EQ, rational(0));
|
||||||
}
|
}
|
||||||
else if (val_j <= 0 && 0 < val_vars) {
|
else if (val_j <= 0 && 0 < val_vars) {
|
||||||
bound_justifications bounds;
|
bound_justifications bounds;
|
||||||
lbool sign = add_bounds(vars, bounds);
|
lbool sign = add_bounds(vars, bounds);
|
||||||
VERIFY(sign == l_false);
|
VERIFY(sign == l_false);
|
||||||
add_ineq(bounds, j, lp::lconstraint_kind::GT, rational(0));
|
add_ineq("signs > 0", bounds, j, lp::lconstraint_kind::GT, rational(0));
|
||||||
}
|
}
|
||||||
else if (val_j >= 0 && 0 > val_vars) {
|
else if (val_j >= 0 && 0 > val_vars) {
|
||||||
bound_justifications bounds;
|
bound_justifications bounds;
|
||||||
lbool sign = add_bounds(vars, bounds);
|
lbool sign = add_bounds(vars, bounds);
|
||||||
VERIFY(sign == l_true);
|
VERIFY(sign == l_true);
|
||||||
add_ineq(bounds, j, lp::lconstraint_kind::LT, rational(0));
|
add_ineq("signs < 0", bounds, j, lp::lconstraint_kind::LT, rational(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -277,7 +277,7 @@ namespace nla {
|
||||||
lp::lar_term lhs;
|
lp::lar_term lhs;
|
||||||
lhs.add_monomial(rational(1), j);
|
lhs.add_monomial(rational(1), j);
|
||||||
lhs.add_monomial(rational(sign ? 1 : -1), non_unit);
|
lhs.add_monomial(rational(sign ? 1 : -1), non_unit);
|
||||||
add_ineq(bounds, lhs, lp::lconstraint_kind::EQ, rational(0));
|
add_ineq("unit mul", bounds, lhs, lp::lconstraint_kind::EQ, rational(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
// Monotonicity axioms:
|
// Monotonicity axioms:
|
||||||
|
@ -313,6 +313,7 @@ namespace nla {
|
||||||
}
|
}
|
||||||
|
|
||||||
// x > 1, y > 0 => xy > y
|
// x > 1, y > 0 => xy > y
|
||||||
|
// x > 1, y < 1 => -xy > -y
|
||||||
void stellensatz::saturate_monotonicity(lpvar j, rational const& val_j, lpvar x, int sign_x, lpvar y, int sign_y) {
|
void stellensatz::saturate_monotonicity(lpvar j, rational const& val_j, lpvar x, int sign_x, lpvar y, int sign_y) {
|
||||||
bound_justifications bounds;
|
bound_justifications bounds;
|
||||||
bound b1(x, sign_x < 0 ? lp::lconstraint_kind::LT : lp::lconstraint_kind::GT, rational(sign_x));
|
bound b1(x, sign_x < 0 ? lp::lconstraint_kind::LT : lp::lconstraint_kind::GT, rational(sign_x));
|
||||||
|
@ -321,8 +322,8 @@ namespace nla {
|
||||||
bounds.push_back(b2);
|
bounds.push_back(b2);
|
||||||
lp::lar_term lhs;
|
lp::lar_term lhs;
|
||||||
lhs.add_monomial(rational(sign_x * sign_y), j);
|
lhs.add_monomial(rational(sign_x * sign_y), j);
|
||||||
lhs.add_monomial(rational(sign_y), y);
|
lhs.add_monomial(rational(-sign_y), y);
|
||||||
add_ineq(bounds, lhs, lp::lconstraint_kind::GT, rational(0));
|
add_ineq("monotonicity", bounds, lhs, lp::lconstraint_kind::GT, rational(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
void stellensatz::saturate_squares(lpvar j, rational const& val_j, svector<lpvar> const& vars) {
|
void stellensatz::saturate_squares(lpvar j, rational const& val_j, svector<lpvar> const& vars) {
|
||||||
|
@ -336,7 +337,7 @@ namespace nla {
|
||||||
}
|
}
|
||||||
// it is a square.
|
// it is a square.
|
||||||
bound_justifications bounds;
|
bound_justifications bounds;
|
||||||
add_ineq(bounds, j, lp::lconstraint_kind::GE, rational(0));
|
add_ineq("squares", bounds, j, lp::lconstraint_kind::GE, rational(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
rational stellensatz::value(lp::lar_term const &t) const {
|
rational stellensatz::value(lp::lar_term const &t) const {
|
||||||
|
@ -353,20 +354,24 @@ namespace nla {
|
||||||
return p;
|
return p;
|
||||||
}
|
}
|
||||||
|
|
||||||
lp::constraint_index stellensatz::add_ineq(bound_justifications const& bounds,
|
lp::constraint_index stellensatz::add_ineq(char const* rule,
|
||||||
|
bound_justifications const& bounds,
|
||||||
lp::lar_term const& t, lp::lconstraint_kind k,
|
lp::lar_term const& t, lp::lconstraint_kind k,
|
||||||
rational const& rhs) {
|
rational const& rhs) {
|
||||||
SASSERT(!t.coeffs_as_vector().empty());
|
SASSERT(!t.coeffs_as_vector().empty());
|
||||||
auto ti = m_solver.lra().add_term(t.coeffs_as_vector(), m_solver.lra().number_of_vars());
|
auto ti = m_solver.lra().add_term(t.coeffs_as_vector(), m_solver.lra().number_of_vars());
|
||||||
m_values.push_back(value(t));
|
m_values.push_back(value(t));
|
||||||
auto new_ci = m_solver.lra().add_var_bound(ti, k, rhs);
|
auto new_ci = m_solver.lra().add_var_bound(ti, k, rhs);
|
||||||
|
TRACE(arith,
|
||||||
|
display_constraint(tout << rule << ": ", new_ci) << "\n";
|
||||||
|
if (!bounds.empty()) display(tout << "\t <- ", bounds) << "\n";);
|
||||||
SASSERT(m_values.size() - 1 == ti);
|
SASSERT(m_values.size() - 1 == ti);
|
||||||
m_new_bounds.insert(new_ci, bounds);
|
m_new_bounds.insert(new_ci, bounds);
|
||||||
m_ci2dep.setx(new_ci, nullptr, nullptr);
|
m_ci2dep.setx(new_ci, nullptr, nullptr);
|
||||||
return new_ci;
|
return new_ci;
|
||||||
}
|
}
|
||||||
|
|
||||||
lp::constraint_index stellensatz::add_ineq(bound_justifications const& bounds, lpvar j, lp::lconstraint_kind k,
|
lp::constraint_index stellensatz::add_ineq(char const* rule, bound_justifications const& bounds, lpvar j, lp::lconstraint_kind k,
|
||||||
rational const& rhs) {
|
rational const& rhs) {
|
||||||
auto new_ci = m_solver.lra().add_var_bound(j, k, rhs);
|
auto new_ci = m_solver.lra().add_var_bound(j, k, rhs);
|
||||||
m_new_bounds.insert(new_ci, bounds);
|
m_new_bounds.insert(new_ci, bounds);
|
||||||
|
@ -422,13 +427,15 @@ namespace nla {
|
||||||
continue;
|
continue;
|
||||||
svector<lpvar> _vars;
|
svector<lpvar> _vars;
|
||||||
_vars.push_back(v);
|
_vars.push_back(v);
|
||||||
for (auto ci : var2cs[v]) {
|
auto cs = var2cs[v];
|
||||||
|
for (auto ci : cs) {
|
||||||
for (auto [coeff, u] : m_solver.lra().constraints()[ci].coeffs()) {
|
for (auto [coeff, u] : m_solver.lra().constraints()[ci].coeffs()) {
|
||||||
if (u == v)
|
if (u == v)
|
||||||
saturate_constraint(ci, j, _vars);
|
saturate_constraint(ci, j, _vars);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#if 0
|
||||||
for (auto v : vars) {
|
for (auto v : vars) {
|
||||||
if (v >= vars2cs.size())
|
if (v >= vars2cs.size())
|
||||||
continue;
|
continue;
|
||||||
|
@ -438,6 +445,7 @@ namespace nla {
|
||||||
saturate_constraint(ci, j, m_mon2vars[u]);
|
saturate_constraint(ci, j, m_mon2vars[u]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
IF_VERBOSE(5,
|
IF_VERBOSE(5,
|
||||||
c().lra_solver().display(verbose_stream() << "original\n");
|
c().lra_solver().display(verbose_stream() << "original\n");
|
||||||
|
@ -461,11 +469,13 @@ namespace nla {
|
||||||
|
|
||||||
// xs is a proper subset of vars in mi
|
// xs is a proper subset of vars in mi
|
||||||
svector<lpvar> vars(m_mon2vars[mi]);
|
svector<lpvar> vars(m_mon2vars[mi]);
|
||||||
|
|
||||||
for (auto x : xs) {
|
for (auto x : xs) {
|
||||||
SASSERT(vars.contains(x));
|
SASSERT(vars.contains(x));
|
||||||
vars.erase(x);
|
vars.erase(x);
|
||||||
}
|
}
|
||||||
SASSERT(!vars.empty());
|
SASSERT(!vars.empty());
|
||||||
|
SASSERT(vars.size() + xs.size() == m_mon2vars[mi].size());
|
||||||
|
|
||||||
bound_justifications bounds;
|
bound_justifications bounds;
|
||||||
// compute bounds constraints and sign of vars
|
// compute bounds constraints and sign of vars
|
||||||
|
@ -503,7 +513,7 @@ namespace nla {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto new_ci = add_ineq(bounds, new_lhs, k, new_rhs);
|
auto new_ci = add_ineq("superpose", bounds, new_lhs, k, new_rhs);
|
||||||
IF_VERBOSE(4, display_constraint(verbose_stream(), old_ci) << " -> ";
|
IF_VERBOSE(4, display_constraint(verbose_stream(), old_ci) << " -> ";
|
||||||
display_constraint(verbose_stream(), new_lhs.coeffs_as_vector(), k, new_rhs) << "\n");
|
display_constraint(verbose_stream(), new_lhs.coeffs_as_vector(), k, new_rhs) << "\n");
|
||||||
insert_monomials_from_constraint(new_ci);
|
insert_monomials_from_constraint(new_ci);
|
||||||
|
@ -595,7 +605,7 @@ namespace nla {
|
||||||
return;
|
return;
|
||||||
auto const& con = m_solver.lra().constraints()[ci];
|
auto const& con = m_solver.lra().constraints()[ci];
|
||||||
for (auto [coeff, v] : con.coeffs())
|
for (auto [coeff, v] : con.coeffs())
|
||||||
if (m_mon2vars.contains(v))
|
if (c().emons().is_monic_var(v))
|
||||||
m_to_refine.insert(v);
|
m_to_refine.insert(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -630,6 +640,35 @@ namespace nla {
|
||||||
display_product(out, vars);
|
display_product(out, vars);
|
||||||
out << "\n";
|
out << "\n";
|
||||||
}
|
}
|
||||||
|
for (auto ci : m_solver.lra().constraints().indices()) {
|
||||||
|
lp::constraint_index old_ci;
|
||||||
|
out << "(" << ci << ") ";
|
||||||
|
display_constraint(out, ci);
|
||||||
|
if (m_old_constraints.find(ci, old_ci))
|
||||||
|
out << " [parent (" << old_ci << ")] ";
|
||||||
|
out << "\n";
|
||||||
|
if (!m_new_bounds.contains(ci))
|
||||||
|
continue;
|
||||||
|
out << "\t<- ";
|
||||||
|
display(out, m_new_bounds[ci]);
|
||||||
|
out << "\n";
|
||||||
|
}
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ostream& stellensatz::display(std::ostream& out, bound_justifications const& bounds) const {
|
||||||
|
for (auto b : bounds) {
|
||||||
|
if (std::holds_alternative<u_dependency *>(b)) {
|
||||||
|
auto dep = *std::get_if<u_dependency *>(&b);
|
||||||
|
unsigned_vector cs;
|
||||||
|
c().lra_solver().dep_manager().linearize(dep, cs);
|
||||||
|
for (auto c : cs)
|
||||||
|
out << "[o " << c << "] "; // constraint index from c().lra_solver.
|
||||||
|
} else {
|
||||||
|
auto [v, k, rhs] = *std::get_if<bound>(&b);
|
||||||
|
out << "[j" << v << " " << k << " " << rhs << "] ";
|
||||||
|
}
|
||||||
|
}
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -687,10 +726,12 @@ namespace nla {
|
||||||
r = solve_lia(ex);
|
r = solve_lia(ex);
|
||||||
if (r != l_true)
|
if (r != l_true)
|
||||||
return r;
|
return r;
|
||||||
|
unsigned sz = lra_solver->number_of_vars();
|
||||||
if (update_values())
|
if (update_values())
|
||||||
return l_true;
|
return l_true;
|
||||||
unsigned sz = lra_solver->number_of_vars();
|
|
||||||
saturate_basic_linearize();
|
TRACE(arith, s.display(tout));
|
||||||
|
// return l_undef;
|
||||||
// s.saturate_constraints(); ?
|
// s.saturate_constraints(); ?
|
||||||
if (sz == lra_solver->number_of_vars())
|
if (sz == lra_solver->number_of_vars())
|
||||||
return l_undef;
|
return l_undef;
|
||||||
|
@ -698,15 +739,14 @@ namespace nla {
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool stellensatz::solver::solve_lra(lp::explanation &ex) {
|
lbool stellensatz::solver::solve_lra(lp::explanation &ex) {
|
||||||
auto st = lra_solver->solve();
|
auto status = lra_solver->find_feasible_solution();;
|
||||||
if (st == lp::lp_status::INFEASIBLE) {
|
if (lra_solver->is_feasible())
|
||||||
|
return l_true;
|
||||||
|
if (status == lp::lp_status::INFEASIBLE) {
|
||||||
lra_solver->get_infeasibility_explanation(ex);
|
lra_solver->get_infeasibility_explanation(ex);
|
||||||
return l_false;
|
return l_false;
|
||||||
}
|
}
|
||||||
else if (lra_solver->is_feasible())
|
return l_undef;
|
||||||
return l_true;
|
|
||||||
else
|
|
||||||
return l_undef;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool stellensatz::solver::solve_lia(lp::explanation &ex) {
|
lbool stellensatz::solver::solve_lia(lp::explanation &ex) {
|
||||||
|
@ -751,16 +791,15 @@ namespace nla {
|
||||||
for (auto v : s.m_coi.vars())
|
for (auto v : s.m_coi.vars())
|
||||||
s.c().lra_solver().set_column_value(v, lp::impq(s.m_values[v], rational(0)));
|
s.c().lra_solver().set_column_value(v, lp::impq(s.m_values[v], rational(0)));
|
||||||
}
|
}
|
||||||
return satisfies_products;
|
#if 1
|
||||||
}
|
|
||||||
|
|
||||||
void stellensatz::solver::saturate_basic_linearize() {
|
|
||||||
for (auto j : s.m_to_refine) {
|
for (auto j : s.m_to_refine) {
|
||||||
auto val_j = lra_solver->get_value(j);
|
auto val_j = values[j];
|
||||||
auto const &vars = s.m_mon2vars[j];
|
auto const &vars = s.m_mon2vars[j];
|
||||||
auto val_vars = s.m_values[j];
|
auto val_vars = s.m_values[j];
|
||||||
if (val_j != val_vars)
|
if (val_j != val_vars)
|
||||||
s.saturate_basic_linearize(j, val_j, vars, val_vars);
|
s.saturate_basic_linearize(j, val_j, vars, val_vars);
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
return satisfies_products;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,8 +82,8 @@ namespace nla {
|
||||||
|
|
||||||
// additional variables and monomials and constraints
|
// additional variables and monomials and constraints
|
||||||
lpvar add_monomial(svector<lp::lpvar> const& vars);
|
lpvar add_monomial(svector<lp::lpvar> const& vars);
|
||||||
lp::constraint_index add_ineq(bound_justifications const& bounds, lp::lar_term const &t, lp::lconstraint_kind k, rational const &rhs);
|
lp::constraint_index add_ineq(char const* rule, bound_justifications const& bounds, lp::lar_term const &t, lp::lconstraint_kind k, rational const &rhs);
|
||||||
lp::constraint_index add_ineq(bound_justifications const &bounds, lpvar j, lp::lconstraint_kind k,
|
lp::constraint_index add_ineq(char const* rule, bound_justifications const &bounds, lpvar j, lp::lconstraint_kind k,
|
||||||
rational const &rhs);
|
rational const &rhs);
|
||||||
|
|
||||||
bool is_int(svector<lp::lpvar> const& vars) const;
|
bool is_int(svector<lp::lpvar> const& vars) const;
|
||||||
|
@ -115,6 +115,7 @@ namespace nla {
|
||||||
std::ostream& display_constraint(std::ostream& out, lp::constraint_index ci) const;
|
std::ostream& display_constraint(std::ostream& out, lp::constraint_index ci) const;
|
||||||
std::ostream& display_constraint(std::ostream& out, vector<std::pair<rational, lpvar>> const& lhs,
|
std::ostream& display_constraint(std::ostream& out, vector<std::pair<rational, lpvar>> const& lhs,
|
||||||
lp::lconstraint_kind k, rational const& rhs) const;
|
lp::lconstraint_kind k, rational const& rhs) const;
|
||||||
|
std::ostream& display(std::ostream &out, bound_justifications const &bounds) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
stellensatz(core* core);
|
stellensatz(core* core);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue