3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-18 17:22:15 +00:00

produce the first lemma in niil_solver

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
Lev Nachmanson 2018-08-17 20:02:48 +08:00
parent 0911fc2bda
commit 49ae42cebd
6 changed files with 136 additions and 66 deletions

View file

@ -430,7 +430,6 @@ class theory_lra::imp {
} }
void ensure_niil() { void ensure_niil() {
if (!m_niil) { if (!m_niil) {
std::cout << "ensure_niil\n";
m_niil = alloc(niil::solver, *m_solver.get(), m.limit(), ctx().get_params()); m_niil = alloc(niil::solver, *m_solver.get(), m.limit(), ctx().get_params());
m_switcher.m_niil = &m_niil; m_switcher.m_niil = &m_niil;
for (auto const& _s : m_scopes) { for (auto const& _s : m_scopes) {

View file

@ -32,5 +32,6 @@ public:
m_explanation.push_back(std::make_pair(one_of_type<mpq>(), j)); m_explanation.push_back(std::make_pair(one_of_type<mpq>(), j));
} }
void reset() { m_explanation.reset(); } void reset() { m_explanation.reset(); }
template <typename A> void add(const A& a) { for (constraint_index j : a) push_justification(j); }
}; };
} }

View file

@ -195,9 +195,6 @@ public:
mpq big_number = m_abs_max.expt(3); mpq big_number = m_abs_max.expt(3);
mpq d = hnf_calc::determinant_of_rectangular_matrix(m_A, basis_rows, big_number); mpq d = hnf_calc::determinant_of_rectangular_matrix(m_A, basis_rows, big_number);
// std::cout << "max = " << m_abs_max << ", d = " << d << ", d/max = " << ceil (d /m_abs_max) << std::endl;
// std::cout << "max cube " << m_abs_max * m_abs_max * m_abs_max << std::endl;
if (d >= big_number) { if (d >= big_number) {
return lia_move::undef; return lia_move::undef;
} }

View file

@ -13,6 +13,8 @@ namespace nra {
svector<lp::var_index> m_vs; svector<lp::var_index> m_vs;
unsigned var() const { return m_v; } unsigned var() const { return m_v; }
unsigned size() const { return m_vs.size(); } unsigned size() const { return m_vs.size(); }
svector<lp::var_index>::const_iterator begin() const { return m_vs.begin(); }
svector<lp::var_index>::const_iterator end() const { return m_vs.end(); }
}; };
typedef std::unordered_map<lp::var_index, rational> variable_map_type; typedef std::unordered_map<lp::var_index, rational> variable_map_type;

View file

@ -22,30 +22,57 @@ Revision History:
#include "util/lp/mon_eq.h" #include "util/lp/mon_eq.h"
#include "util/lp/lp_utils.h" #include "util/lp/lp_utils.h"
namespace niil { namespace niil {
typedef std::unordered_set<lp::constraint_index> expl_set;
typedef nra::mon_eq mon_eq; typedef nra::mon_eq mon_eq;
typedef lp::var_index lpvar; typedef lp::var_index lpvar;
struct solver::imp { struct solver::imp {
struct vars_equivalence { struct vars_equivalence {
struct signed_var {
lpvar m_var;
int m_sign;
signed_var(lpvar j, int sign) : m_var(j), m_sign(sign) {}
};
struct equiv { struct equiv {
lpvar m_i; lpvar m_i;
signed_var m_signed_var; lpvar m_j;
equiv(lpvar i, lpvar j, int sign) :m_i(i), m_signed_var(j, sign) { int m_sign;
lp::constraint_index m_c0;
lp::constraint_index m_c1;
equiv(lpvar i, lpvar j, int sign, lp::constraint_index c0, lp::constraint_index c1) :
m_i(i),
m_j(j),
m_sign(sign),
m_c0(c0),
m_c1(c1)
{
SASSERT(i > j); SASSERT(i > j);
} }
}; };
// the resulting mapping struct eq_var {
std::unordered_map<lpvar, signed_var> m_map; lpvar m_var;
// all equivalences extracted from constraints int m_sign;
vector<equiv> m_equivs; expl_set m_explanation;
eq_var(const equiv& e) :
m_var(e.m_j),
m_sign(e.m_sign) {
m_explanation.insert(e.m_c0); m_explanation.insert(e.m_c1);
}
void improve(const equiv & e) {
SASSERT(e.m_j > m_var);
m_var = e.m_j;
m_sign *= e.m_sign;
m_explanation.insert(e.m_c0); m_explanation.insert(e.m_c1);
}
};
std::unordered_map<lpvar, eq_var> m_map; // the resulting mapping
vector<equiv> m_equivs; // all equivalences extracted from constraints
void clear() {
m_equivs.clear();
m_map.clear();
}
unsigned size() const { return m_map.size(); } unsigned size() const { return m_map.size(); }
void add_equivalence_maybe(const lp::lar_term *t) { void add_equivalence_maybe(const lp::lar_term *t, lp::constraint_index c0, lp::constraint_index c1) {
if (t->size() != 2 || ! t->m_v.is_zero()) if (t->size() != 2 || ! t->m_v.is_zero())
return; return;
bool seen_minus = false; bool seen_minus = false;
@ -72,7 +99,7 @@ struct solver::imp {
j = tmp; j = tmp;
} }
int sign = (seen_minus && seen_plus)? 1 : -1; int sign = (seen_minus && seen_plus)? 1 : -1;
m_equivs.push_back(equiv(i, j, sign)); m_equivs.push_back(equiv(i, j, sign, c0, c1));
} }
void collect_equivs(const lp::lar_solver& s) { void collect_equivs(const lp::lar_solver& s) {
@ -87,46 +114,42 @@ struct solver::imp {
if (s.get_upper_bound(j) != lp::zero_of_type<lp::impq>() || if (s.get_upper_bound(j) != lp::zero_of_type<lp::impq>() ||
s.get_lower_bound(j) != lp::zero_of_type<lp::impq>()) s.get_lower_bound(j) != lp::zero_of_type<lp::impq>())
continue; continue;
add_equivalence_maybe(s.terms()[i]); add_equivalence_maybe(s.terms()[i], s.get_column_upper_bound_witness(j), s.get_column_lower_bound_witness(j));
} }
} }
void create_map() { void create_map() {
bool progress = true; bool progress;
while (progress) { do {
progress = false; progress = false;
for (const auto & e : m_equivs) { for (const auto & e : m_equivs) {
unsigned i = e.m_i; unsigned i = e.m_i;
auto it = m_map.find(i); auto it = m_map.find(i);
if (it == m_map.end()) { if (it == m_map.end()) {
m_map.insert(std::pair<lpvar, signed_var>(i, e.m_signed_var)); m_map.emplace(i, eq_var(e));
progress = true; progress = true;
} else { } else {
if (it->second.m_var > e.m_signed_var.m_var) { if (it->second.m_var > e.m_j) {
it->second = signed_var( it->second.improve(e);
e.m_signed_var.m_var,
e.m_signed_var.m_sign * it->second.m_sign);
progress = true; progress = true;
} }
} }
} }
} } while(progress);
} }
void init(const lp::lar_solver& s) { void init(const lp::lar_solver& s) {
clear();
collect_equivs(s); collect_equivs(s);
create_map(); create_map();
} }
lpvar get_equivalent_var(lpvar j, bool & sign) {
SASSERT(false);
return false;
}
bool empty() const { bool empty() const {
return m_map.empty(); return m_map.empty();
} }
// the sign is flipped if needed // the sign is flipped if needed
lpvar map_to_min(lpvar j, int sign) const { lpvar map_to_min(lpvar j, int& sign) const {
auto it = m_map.find(j); auto it = m_map.find(j);
if (it == m_map.end()) if (it == m_map.end())
return j; return j;
@ -137,12 +160,27 @@ struct solver::imp {
return it->second.m_var; return it->second.m_var;
} }
}; template <typename T>
void add_expl_from_monomial(const T & m, expl_set & exp) const {
for (auto j : m)
add_equiv_exp(j, exp);
}
void add_equiv_exp(lpvar j, expl_set & exp) const {
auto it = m_map.find(j);
if (it == m_map.end())
return;
for (auto k : it->second.m_explanation)
exp.insert(k);
}
}; // end of vars_equivalence
vars_equivalence m_vars_equivalence; vars_equivalence m_vars_equivalence;
vector<mon_eq> m_monomials; vector<mon_eq> m_monomials;
unsigned_vector m_monomials_lim; unsigned_vector m_monomials_lim;
lp::lar_solver& m_lar_solver; lp::lar_solver& m_lar_solver;
std::unordered_map<lpvar, svector<unsigned>> m_var_to_monomials; std::unordered_map<lpvar, svector<unsigned>> m_var_to_monomials;
lp::explanation * m_expl;
lemma * m_lemma;
imp(lp::lar_solver& s, reslimit& lim, params_ref const& p) imp(lp::lar_solver& s, reslimit& lim, params_ref const& p)
: m_lar_solver(s) : m_lar_solver(s)
// m_limit(lim), // m_limit(lim),
@ -189,7 +227,7 @@ struct solver::imp {
unsigned i_mon, unsigned i_mon,
unsigned j_var, unsigned j_var,
const svector<unsigned> & mon_vars, const svector<unsigned> & mon_vars,
const mon_eq& other_m, int sign, lemma& l) { const mon_eq& other_m, int sign) {
if (mon_vars.size() != other_m.size()) if (mon_vars.size() != other_m.size())
return false; return false;
@ -199,7 +237,9 @@ struct solver::imp {
if (var_vectors_are_equal(mon_vars, other_vars_copy) if (var_vectors_are_equal(mon_vars, other_vars_copy)
&& values_are_different(m_monomials[i_mon].var(), && values_are_different(m_monomials[i_mon].var(),
sign * other_sign, other_m.var())) { sign * other_sign, other_m.var())) {
fill_lemma(); fill_explanation_and_lemma(m_monomials[i_mon],
other_m,
sign* other_sign);
return true; return true;
} }
@ -211,12 +251,45 @@ struct solver::imp {
return ! ( sign * m_lar_solver.get_column_value(j) == m_lar_solver.get_column_value(k)); return ! ( sign * m_lar_solver.get_column_value(j) == m_lar_solver.get_column_value(k));
} }
void fill_lemma() { void add_expl_from_monomial(const mon_eq& m, expl_set & eset) const {
SASSERT(false); // not implemented m_vars_equivalence.add_expl_from_monomial(m, eset);
}
void print_monomial(const mon_eq& m, std::ostream& out) {
out << m_lar_solver.get_column_name(m.var()) << " = ";
for (unsigned j : m) {
out << m_lar_solver.get_column_name(j) << "*";
}
}
// the monomials should be equal by modulo sign, but they are not equal in the model
void fill_explanation_and_lemma(const mon_eq& a, const mon_eq & b, int sign) {
expl_set expl;
SASSERT(sign == 1 || sign == -1);
add_expl_from_monomial(a, expl);
add_expl_from_monomial(b, expl);
m_expl->clear();
m_expl->add(expl);
TRACE("niil_solver",
for (auto &p : *m_expl)
m_lar_solver.print_constraint(p.second, tout); tout << "\n";
);
lp::lar_term t;
t.add_monomial(rational(1), a.var());
t.add_monomial(rational(- sign), b.var());
TRACE("niil_solver",
m_lar_solver.print_term(t, tout);
tout << "\n";
print_monomial(a, tout);
tout << "\n";
print_monomial(b, tout);
);
ineq in(lp::lconstraint_kind::NE, t);
m_lemma->push_back(in);
} }
bool generate_basic_lemma_for_mon_sign_var(unsigned i_mon, bool generate_basic_lemma_for_mon_sign_var(unsigned i_mon,
unsigned j_var, const svector<lpvar>& mon_vars, lemma& l, int sign) { unsigned j_var, const svector<lpvar>& mon_vars, int sign) {
auto it = m_var_to_monomials.find(j_var); auto it = m_var_to_monomials.find(j_var);
for (auto other_i_mon : it->second) { for (auto other_i_mon : it->second) {
if (other_i_mon == i_mon) continue; if (other_i_mon == i_mon) continue;
@ -225,8 +298,7 @@ struct solver::imp {
j_var, j_var,
mon_vars, mon_vars,
m_monomials[other_i_mon], m_monomials[other_i_mon],
sign, sign))
l))
return true; return true;
} }
return false; return false;
@ -239,12 +311,9 @@ struct solver::imp {
} }
} }
bool generate_basic_lemma_for_mon_sign(unsigned i_mon, lemma& l) { bool generate_basic_lemma_for_mon_sign(unsigned i_mon) {
if (m_vars_equivalence.empty()) { if (m_vars_equivalence.empty()) {
std::cout << "empty m_vars_equivalence\n";
return false; return false;
} else {
std::cout << "m_vars_equivalence size = " << m_vars_equivalence.size() << std::endl;
} }
const mon_eq& m_of_i = m_monomials[i_mon]; const mon_eq& m_of_i = m_monomials[i_mon];
int sign = 1; int sign = 1;
@ -252,33 +321,33 @@ struct solver::imp {
auto mon_vars = m_of_i.m_vs; auto mon_vars = m_of_i.m_vs;
reduce_monomial_to_minimal(mon_vars, sign); reduce_monomial_to_minimal(mon_vars, sign);
for (unsigned j_var : mon_vars) for (unsigned j_var : mon_vars)
if (generate_basic_lemma_for_mon_sign_var(i_mon, j_var, mon_vars, l, sign)) if (generate_basic_lemma_for_mon_sign_var(i_mon, j_var, mon_vars, sign))
return true; return true;
return false; return false;
} }
bool generate_basic_lemma_for_mon_zero(unsigned i_mon, lemma& l) { bool generate_basic_lemma_for_mon_zero(unsigned i_mon) {
return false; return false;
} }
bool generate_basic_lemma_for_mon_neutral(unsigned i_mon, lemma& l) { bool generate_basic_lemma_for_mon_neutral(unsigned i_mon) {
return false; return false;
} }
bool generate_basic_lemma_for_mon_proportionality(unsigned i_mon, lemma& l) { bool generate_basic_lemma_for_mon_proportionality(unsigned i_mon) {
return false; return false;
} }
bool generate_basic_lemma_for_mon(unsigned i_mon, lemma & l) { bool generate_basic_lemma_for_mon(unsigned i_mon) {
return generate_basic_lemma_for_mon_sign(i_mon, l) return generate_basic_lemma_for_mon_sign(i_mon)
|| generate_basic_lemma_for_mon_zero(i_mon, l) || generate_basic_lemma_for_mon_zero(i_mon)
|| generate_basic_lemma_for_mon_neutral(i_mon, l) || generate_basic_lemma_for_mon_neutral(i_mon)
|| generate_basic_lemma_for_mon_proportionality(i_mon, l); || generate_basic_lemma_for_mon_proportionality(i_mon);
} }
bool generate_basic_lemma(lemma & l, svector<unsigned> & to_refine) { bool generate_basic_lemma(svector<unsigned> & to_refine) {
for (unsigned i : to_refine) for (unsigned i : to_refine)
if (generate_basic_lemma_for_mon(i, l)) if (generate_basic_lemma_for_mon(i))
return true; return true;
return false; return false;
} }
@ -312,27 +381,27 @@ struct solver::imp {
init_vars_equivalence(); init_vars_equivalence();
} }
lbool check(lemma& l) { lbool check(lp::explanation & exp, lemma& l) {
m_expl = &exp;
m_lemma = &l;
lp_assert(m_lar_solver.get_status() == lp::lp_status::OPTIMAL); lp_assert(m_lar_solver.get_status() == lp::lp_status::OPTIMAL);
svector<unsigned> to_refine; svector<unsigned> to_refine;
for (unsigned i = 0; i < m_monomials.size(); i++) { for (unsigned i = 0; i < m_monomials.size(); i++) {
if (!check_monomial(m_monomials[i])) if (!check_monomial(m_monomials[i]))
to_refine.push_back(i); to_refine.push_back(i);
} }
std::cout << "to_refine size = " << to_refine.size() << std::endl;
if (to_refine.size() == 0) if (to_refine.size() == 0)
return l_true; return l_true;
init_search(); init_search();
if (generate_basic_lemma(l, to_refine)) if (generate_basic_lemma(to_refine))
return l_true; return l_false;
return l_undef; return l_undef;
} }
}; // end of imp
};
void solver::add_monomial(lpvar v, unsigned sz, lpvar const* vs) { void solver::add_monomial(lpvar v, unsigned sz, lpvar const* vs) {
m_imp->add(v, sz, vs); m_imp->add(v, sz, vs);
@ -341,7 +410,7 @@ void solver::add_monomial(lpvar v, unsigned sz, lpvar const* vs) {
bool solver::need_check() { return true; } bool solver::need_check() { return true; }
lbool solver::check(lp::explanation & ex, lemma& l) { lbool solver::check(lp::explanation & ex, lemma& l) {
return m_imp->check(l); return m_imp->check(ex, l);
} }

View file

@ -28,6 +28,8 @@ namespace niil {
struct ineq { struct ineq {
lp::lconstraint_kind m_cmp; lp::lconstraint_kind m_cmp;
lp::lar_term m_term; lp::lar_term m_term;
ineq(lp::lconstraint_kind cmp,
const lp::lar_term& term) : m_cmp(cmp), m_term(term) {}
}; };
typedef vector<ineq> lemma; typedef vector<ineq> lemma;