mirror of
https://github.com/Z3Prover/z3
synced 2026-01-19 16:53:18 +00:00
add option to propagation quotients
for equations x*y + z = 0, with x, y, z integer, enforce that x divides z It is (currently) enabled within Grobner completion and applied partially to x a variable, z linear, and only when |z| < |x|.
This commit is contained in:
parent
91b4873b79
commit
e91e432496
10 changed files with 516 additions and 258 deletions
|
|
@ -51,6 +51,10 @@ core::core(lp::lar_solver& s, params_ref const& p, reslimit & lim) :
|
|||
}
|
||||
};
|
||||
}
|
||||
|
||||
void core::updt_params(params_ref const& p) {
|
||||
m_grobner.updt_params(p);
|
||||
}
|
||||
|
||||
bool core::compare_holds(const rational& ls, llc cmp, const rational& rs) const {
|
||||
switch(cmp) {
|
||||
|
|
@ -172,108 +176,6 @@ bool core::check_monic(const monic& m) const {
|
|||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
std::ostream& core::print_product(const T & m, std::ostream& out) const {
|
||||
bool first = true;
|
||||
for (lpvar v : m) {
|
||||
if (!first) out << "*"; else first = false;
|
||||
if (lp_settings().print_external_var_name())
|
||||
out << "(" << lra.get_variable_name(v) << "=" << val(v) << ")";
|
||||
else
|
||||
out << "(j" << v << " = " << val(v) << ")";
|
||||
|
||||
}
|
||||
return out;
|
||||
}
|
||||
template <typename T>
|
||||
std::string core::product_indices_str(const T & m) const {
|
||||
std::stringstream out;
|
||||
bool first = true;
|
||||
for (lpvar v : m) {
|
||||
if (!first)
|
||||
out << "*";
|
||||
else
|
||||
first = false;
|
||||
out << "j" << v;;
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
||||
std::ostream & core::print_factor(const factor& f, std::ostream& out) const {
|
||||
if (f.sign())
|
||||
out << "- ";
|
||||
if (f.is_var()) {
|
||||
out << "VAR, " << pp(f.var());
|
||||
} else {
|
||||
out << "MON, v" << m_emons[f.var()] << " = ";
|
||||
print_product(m_emons[f.var()].rvars(), out);
|
||||
}
|
||||
out << "\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream & core::print_factor_with_vars(const factor& f, std::ostream& out) const {
|
||||
if (f.is_var()) {
|
||||
out << pp(f.var());
|
||||
}
|
||||
else {
|
||||
out << " MON = " << pp_mon_with_vars(*this, m_emons[f.var()]);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& core::print_monic(const monic& m, std::ostream& out) const {
|
||||
if (lp_settings().print_external_var_name())
|
||||
out << "([" << m.var() << "] = " << lra.get_variable_name(m.var()) << " = " << val(m.var()) << " = ";
|
||||
else
|
||||
out << "(j" << m.var() << " = " << val(m.var()) << " = ";
|
||||
print_product(m.vars(), out) << ")\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
std::ostream& core::print_bfc(const factorization& m, std::ostream& out) const {
|
||||
SASSERT(m.size() == 2);
|
||||
out << "( x = " << pp(m[0]) << "* y = " << pp(m[1]) << ")";
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& core::print_monic_with_vars(lpvar v, std::ostream& out) const {
|
||||
return print_monic_with_vars(m_emons[v], out);
|
||||
}
|
||||
template <typename T>
|
||||
std::ostream& core::print_product_with_vars(const T& m, std::ostream& out) const {
|
||||
print_product(m, out) << "\n";
|
||||
for (unsigned k = 0; k < m.size(); k++) {
|
||||
print_var(m[k], out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& core::print_monic_with_vars(const monic& m, std::ostream& out) const {
|
||||
out << "[" << pp(m.var()) << "]\n";
|
||||
out << "vars:"; print_product_with_vars(m.vars(), out) << "\n";
|
||||
if (m.vars() == m.rvars())
|
||||
out << "same rvars, and m.rsign = " << m.rsign() << " of course\n";
|
||||
else {
|
||||
out << "rvars:"; print_product_with_vars(m.rvars(), out) << "\n";
|
||||
out << "rsign:" << m.rsign() << "\n";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& core::print_explanation(const lp::explanation& exp, std::ostream& out) const {
|
||||
out << "expl: ";
|
||||
unsigned i = 0;
|
||||
for (auto p : exp) {
|
||||
out << "(" << p.ci() << ")";
|
||||
lra.constraints().display(out, [this](lpvar j) { return var_str(j);}, p.ci());
|
||||
if (++i < exp.size())
|
||||
out << " ";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
bool core::explain_upper_bound(const lp::lar_term& t, const rational& rs, lp::explanation& e) const {
|
||||
rational b(0); // the bound
|
||||
for (lp::lar_term::ival p : t) {
|
||||
|
|
@ -551,69 +453,6 @@ bool core::var_is_free(lpvar j) const {
|
|||
return lra.column_is_free(j);
|
||||
}
|
||||
|
||||
std::ostream & core::print_ineq(const ineq & in, std::ostream & out) const {
|
||||
lra.print_term_as_indices(in.term(), out);
|
||||
return out << " " << lconstraint_kind_string(in.cmp()) << " " << in.rs();
|
||||
}
|
||||
|
||||
std::ostream & core::print_var(lpvar j, std::ostream & out) const {
|
||||
if (is_monic_var(j))
|
||||
print_monic(m_emons[j], out);
|
||||
|
||||
lra.print_column_info(j, out);
|
||||
signed_var jr = m_evars.find(j);
|
||||
out << "root=";
|
||||
if (jr.sign()) {
|
||||
out << "-";
|
||||
}
|
||||
|
||||
out << lra.get_variable_name(jr.var()) << "\n";
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream & core::print_monics(std::ostream & out) const {
|
||||
for (auto &m : m_emons) {
|
||||
print_monic_with_vars(m, out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream & core::print_ineqs(const lemma& l, std::ostream & out) const {
|
||||
std::unordered_set<lpvar> vars;
|
||||
out << "ineqs: ";
|
||||
if (l.ineqs().size() == 0) {
|
||||
out << "conflict\n";
|
||||
} else {
|
||||
for (unsigned i = 0; i < l.ineqs().size(); i++) {
|
||||
auto & in = l.ineqs()[i];
|
||||
print_ineq(in, out);
|
||||
if (i + 1 < l.ineqs().size()) out << " or ";
|
||||
for (lp::lar_term::ival p: in.term())
|
||||
vars.insert(p.j());
|
||||
}
|
||||
out << std::endl;
|
||||
for (lpvar j : vars) {
|
||||
print_var(j, out);
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream & core::print_factorization(const factorization& f, std::ostream& out) const {
|
||||
if (f.is_mon()){
|
||||
out << "is_mon " << pp_mon(*this, f.mon());
|
||||
}
|
||||
else {
|
||||
for (unsigned k = 0; k < f.size(); k++ ) {
|
||||
out << "(" << pp(f[k]) << ")";
|
||||
if (k < f.size() - 1)
|
||||
out << "*";
|
||||
}
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
bool core::find_canonical_monic_of_vars(const svector<lpvar>& vars, lpvar & i) const {
|
||||
monic const* sv = m_emons.find_canonical(vars);
|
||||
return sv && (i = sv->var(), true);
|
||||
|
|
@ -623,16 +462,6 @@ bool core::is_canonical_monic(lpvar j) const {
|
|||
return m_emons.is_canonical_monic(j);
|
||||
}
|
||||
|
||||
|
||||
void core::trace_print_monic_and_factorization(const monic& rm, const factorization& f, std::ostream& out) const {
|
||||
out << "rooted vars: ";
|
||||
print_product(rm.rvars(), out) << "\n";
|
||||
out << "mon: " << pp_mon(*this, rm.var()) << "\n";
|
||||
out << "value: " << var_val(rm) << "\n";
|
||||
print_factorization(f, out << "fact: ") << "\n";
|
||||
}
|
||||
|
||||
|
||||
bool core::var_has_positive_lower_bound(lpvar j) const {
|
||||
return lra.column_has_lower_bound(j) && lra.get_lower_bound(j) > lp::zero_of_type<lp::impq>();
|
||||
}
|
||||
|
|
@ -771,35 +600,6 @@ bool core::vars_are_roots(const T& v) const {
|
|||
}
|
||||
|
||||
|
||||
|
||||
template <typename T>
|
||||
void core::trace_print_rms(const T& p, std::ostream& out) {
|
||||
out << "p = {\n";
|
||||
for (auto j : p) {
|
||||
out << "j = " << j << ", rm = " << m_emons[j] << "\n";
|
||||
}
|
||||
out << "}";
|
||||
}
|
||||
|
||||
void core::print_monic_stats(const monic& m, std::ostream& out) {
|
||||
if (m.size() == 2) return;
|
||||
monic_coeff mc = canonize_monic(m);
|
||||
for(unsigned i = 0; i < mc.vars().size(); i++){
|
||||
if (abs(val(mc.vars()[i])) == rational(1)) {
|
||||
auto vv = mc.vars();
|
||||
vv.erase(vv.begin()+i);
|
||||
monic const* sv = m_emons.find_canonical(vv);
|
||||
if (!sv) {
|
||||
out << "nf length" << vv.size() << "\n"; ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void core::print_stats(std::ostream& out) {
|
||||
}
|
||||
|
||||
|
||||
void core::clear() {
|
||||
m_lemmas.clear();
|
||||
m_literals.clear();
|
||||
|
|
@ -1620,40 +1420,11 @@ bool core::no_lemmas_hold() const {
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
lbool core::test_check() {
|
||||
lra.set_status(lp::lp_status::OPTIMAL);
|
||||
return check();
|
||||
}
|
||||
|
||||
std::ostream& core::print_terms(std::ostream& out) const {
|
||||
for (const auto * t: lra.terms()) {
|
||||
out << "term:"; print_term(*t, out) << std::endl;
|
||||
print_var(t->j(), out);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
std::string core::var_str(lpvar j) const {
|
||||
std::string result;
|
||||
if (is_monic_var(j))
|
||||
result += product_indices_str(m_emons[j].vars()) + (check_monic(m_emons[j])? "": "_");
|
||||
else
|
||||
result += std::string("j") + lp::T_to_string(j);
|
||||
// result += ":w" + lp::T_to_string(get_var_weight(j));
|
||||
return result;
|
||||
}
|
||||
|
||||
std::ostream& core::print_term( const lp::lar_term& t, std::ostream& out) const {
|
||||
return lp::print_linear_combination_customized(
|
||||
t.coeffs_as_vector(),
|
||||
[this](lpvar j) { return var_str(j); },
|
||||
out);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
std::unordered_set<lpvar> core::get_vars_of_expr_with_opening_terms(const nex *e ) {
|
||||
auto ret = get_vars_of_expr(e);
|
||||
auto & ls = lra;
|
||||
|
|
@ -1676,12 +1447,10 @@ std::unordered_set<lpvar> core::get_vars_of_expr_with_opening_terms(const nex *e
|
|||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool core::is_nl_var(lpvar j) const {
|
||||
return is_monic_var(j) || m_emons.is_used_in_monic(j);
|
||||
}
|
||||
|
||||
|
||||
unsigned core::get_var_weight(lpvar j) const {
|
||||
unsigned k = 0;
|
||||
switch (lra.get_column_type(j)) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue