mirror of
https://github.com/Z3Prover/z3
synced 2025-07-19 10:52:02 +00:00
rollback but leave the change with llc::NE
Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
parent
649d47d92c
commit
34262ae02c
2 changed files with 36 additions and 79 deletions
|
@ -101,7 +101,7 @@ struct solver::imp {
|
||||||
std::unordered_map<unsigned_vector, unsigned, hash_svector> m_mkeys; // the key is the sorted vars of a monomial
|
std::unordered_map<unsigned_vector, unsigned, hash_svector> m_mkeys; // the key is the sorted vars of a monomial
|
||||||
|
|
||||||
unsigned find_monomial(const unsigned_vector& k) const {
|
unsigned find_monomial(const unsigned_vector& k) const {
|
||||||
TRACE("nla_solver", tout << "k = "; print_product_with_vars(k, tout););
|
TRACE("nla_solver_find", tout << "k = "; print_product_with_vars(k, tout););
|
||||||
auto it = m_mkeys.find(k);
|
auto it = m_mkeys.find(k);
|
||||||
if (it == m_mkeys.end()) {
|
if (it == m_mkeys.end()) {
|
||||||
TRACE("nla_solver", tout << "not found";);
|
TRACE("nla_solver", tout << "not found";);
|
||||||
|
@ -260,7 +260,6 @@ struct solver::imp {
|
||||||
// return true iff the monomial value is equal to the product of the values of the factors
|
// return true iff the monomial value is equal to the product of the values of the factors
|
||||||
bool check_monomial(const monomial& m) const {
|
bool check_monomial(const monomial& m) const {
|
||||||
SASSERT(m_lar_solver.get_column_value(m.var()).is_int());
|
SASSERT(m_lar_solver.get_column_value(m.var()).is_int());
|
||||||
TRACE("nla_solver_check", tout << "m = "; print_monomial_with_vars(m, tout););
|
|
||||||
return product_value(m) == m_lar_solver.get_column_value_rational(m.var());
|
return product_value(m) == m_lar_solver.get_column_value_rational(m.var());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -354,7 +353,6 @@ struct solver::imp {
|
||||||
print_var(m[k], out);
|
print_var(m[k], out);
|
||||||
}
|
}
|
||||||
return out;
|
return out;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& print_monomial_with_vars(const monomial& m, std::ostream& out) const {
|
std::ostream& print_monomial_with_vars(const monomial& m, std::ostream& out) const {
|
||||||
|
@ -792,6 +790,10 @@ struct solver::imp {
|
||||||
return zero_j;
|
return zero_j;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_set(unsigned j) {
|
||||||
|
return static_cast<int>(j) != -1;
|
||||||
|
}
|
||||||
|
|
||||||
bool try_get_non_strict_sign_from_bounds(lpvar j, int& sign) const {
|
bool try_get_non_strict_sign_from_bounds(lpvar j, int& sign) const {
|
||||||
SASSERT(sign);
|
SASSERT(sign);
|
||||||
if (has_lower_bound(j) && get_lower_bound(j) >= rational(0))
|
if (has_lower_bound(j) && get_lower_bound(j) >= rational(0))
|
||||||
|
@ -886,12 +888,14 @@ struct solver::imp {
|
||||||
return m_vars_equivalence.eq_vars(j);
|
return m_vars_equivalence.eq_vars(j);
|
||||||
}
|
}
|
||||||
|
|
||||||
void basic_sign_lemma_on_two_monomials(const monomial& m, const monomial& n, const rational& sign) {
|
bool basic_sign_lemma_on_two_monomials(const monomial& m, const monomial& n, const rational& sign) {
|
||||||
TRACE("nla_solver", tout << "m = "; print_monomial_with_vars(m, tout); tout << "n= "; print_monomial_with_vars(n, tout); );
|
TRACE("nla_solver", tout << "m = "; print_monomial_with_vars(m, tout); tout << "n= "; print_monomial_with_vars(n, tout); );
|
||||||
rational contr_sign;
|
rational contr_sign;
|
||||||
if (sign_contradiction(m, n, contr_sign)) {
|
if (sign_contradiction(m, n, contr_sign)) {
|
||||||
generate_sign_lemma(m, n, sign);
|
generate_sign_lemma(m, n, sign);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_abs_val_table() {
|
void init_abs_val_table() {
|
||||||
|
@ -967,7 +971,7 @@ struct solver::imp {
|
||||||
for (index_with_sign i_s : mons_to_explore) {
|
for (index_with_sign i_s : mons_to_explore) {
|
||||||
unsigned n = i_s.index();
|
unsigned n = i_s.index();
|
||||||
if (n == i) continue;
|
if (n == i) continue;
|
||||||
basic_sign_lemma_on_two_monomials(m, m_monomials[n], rm_i_s.sign()*i_s.sign());
|
if (basic_sign_lemma_on_two_monomials(m, m_monomials[n], rm_i_s.sign()*i_s.sign()))
|
||||||
if(done())
|
if(done())
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -979,18 +983,16 @@ struct solver::imp {
|
||||||
* \brief <generate lemma by using the fact that -ab = (-a)b) and
|
* \brief <generate lemma by using the fact that -ab = (-a)b) and
|
||||||
-ab = a(-b)
|
-ab = a(-b)
|
||||||
*/
|
*/
|
||||||
void basic_sign_lemma(bool derived) {
|
bool basic_sign_lemma(bool derived) {
|
||||||
if (!derived) {
|
if (!derived)
|
||||||
basic_sign_lemma_model_based();
|
return basic_sign_lemma_model_based();
|
||||||
} else {
|
|
||||||
std::unordered_set<unsigned> explored;
|
std::unordered_set<unsigned> explored;
|
||||||
for (unsigned i : m_to_refine){
|
for (unsigned i : m_to_refine){
|
||||||
basic_sign_lemma_on_mon(i, explored);
|
if (basic_sign_lemma_on_mon(i, explored))
|
||||||
if (done())
|
return true;
|
||||||
return;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool var_is_fixed_to_zero(lpvar j) const {
|
bool var_is_fixed_to_zero(lpvar j) const {
|
||||||
|
@ -1660,10 +1662,11 @@ struct solver::imp {
|
||||||
unsigned random() {return settings().random_next();}
|
unsigned random() {return settings().random_next();}
|
||||||
|
|
||||||
// use basic multiplication properties to create a lemma
|
// use basic multiplication properties to create a lemma
|
||||||
void basic_lemma(bool derived) {
|
bool basic_lemma(bool derived) {
|
||||||
basic_sign_lemma(derived);
|
if (basic_sign_lemma(derived))
|
||||||
|
return true;
|
||||||
if (derived)
|
if (derived)
|
||||||
return;
|
return false;
|
||||||
init_rm_to_refine();
|
init_rm_to_refine();
|
||||||
const auto& rm_ref = m_rm_table.to_refine();
|
const auto& rm_ref = m_rm_table.to_refine();
|
||||||
TRACE("nla_solver", tout << "rm_ref = "; print_vector(rm_ref, tout););
|
TRACE("nla_solver", tout << "rm_ref = "; print_vector(rm_ref, tout););
|
||||||
|
@ -1677,6 +1680,8 @@ struct solver::imp {
|
||||||
i = 0;
|
i = 0;
|
||||||
}
|
}
|
||||||
} while(i != start && !done());
|
} while(i != start && !done());
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void map_monomial_vars_to_monomial_indices(unsigned i) {
|
void map_monomial_vars_to_monomial_indices(unsigned i) {
|
||||||
|
@ -1708,7 +1713,6 @@ struct solver::imp {
|
||||||
void collect_equivs() {
|
void collect_equivs() {
|
||||||
const lp::lar_solver& s = m_lar_solver;
|
const lp::lar_solver& s = m_lar_solver;
|
||||||
|
|
||||||
|
|
||||||
for (unsigned i = 0; i < s.terms().size(); i++) {
|
for (unsigned i = 0; i < s.terms().size(); i++) {
|
||||||
unsigned ti = i + s.terms_start_index();
|
unsigned ti = i + s.terms_start_index();
|
||||||
if (!s.term_is_used_as_row(ti))
|
if (!s.term_is_used_as_row(ti))
|
||||||
|
@ -1719,27 +1723,6 @@ struct solver::imp {
|
||||||
add_equivalence_maybe(s.terms()[i], s.get_column_upper_bound_witness(j), s.get_column_lower_bound_witness(j));
|
add_equivalence_maybe(s.terms()[i], s.get_column_upper_bound_witness(j), s.get_column_lower_bound_witness(j));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::unordered_map<rational, lpvar> fixed_vars;
|
|
||||||
for (unsigned j = 0; j < s.number_of_vars(); j++) {
|
|
||||||
if (!var_is_fixed_to_zero(j)) continue;
|
|
||||||
rational v = abs(vvr(j));
|
|
||||||
auto it = fixed_vars.find(v);
|
|
||||||
if (it == fixed_vars.end()){
|
|
||||||
fixed_vars[v] = j;
|
|
||||||
} else {
|
|
||||||
lpvar k = it->second;
|
|
||||||
TRACE("nla_solver", tout << "fixed vars eq: " << k << ", " << j << ", fixed to " << vvr(j) << "\n";);
|
|
||||||
add_equivalence_of_two_vars(k, j,
|
|
||||||
s.get_column_upper_bound_witness(k),
|
|
||||||
s.get_column_lower_bound_witness(k),
|
|
||||||
s.get_column_upper_bound_witness(j),
|
|
||||||
s.get_column_lower_bound_witness(j));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_equivalence_maybe(const lp::lar_term *t, lpci c0, lpci c1) {
|
void add_equivalence_maybe(const lp::lar_term *t, lpci c0, lpci c1) {
|
||||||
|
@ -1766,11 +1749,6 @@ struct solver::imp {
|
||||||
rational sign((seen_minus && seen_plus)? 1 : -1);
|
rational sign((seen_minus && seen_plus)? 1 : -1);
|
||||||
m_vars_equivalence.add_equiv(i, j, sign, c0, c1);
|
m_vars_equivalence.add_equiv(i, j, sign, c0, c1);
|
||||||
}
|
}
|
||||||
void add_equivalence_of_two_vars(lpvar k, lpvar j, lpci c0, lpci c1, lpci c2, lpci c3) {
|
|
||||||
SASSERT(abs(vvr(k)) == abs(vvr(j)));
|
|
||||||
rational sign(vvr(k) == vvr(j)? 1 : -1);
|
|
||||||
m_vars_equivalence.add_equiv(k, j, sign, c0, c1, c2, c3);
|
|
||||||
}
|
|
||||||
|
|
||||||
// x is equivalent to y if x = +- y
|
// x is equivalent to y if x = +- y
|
||||||
void init_vars_equivalence() {
|
void init_vars_equivalence() {
|
||||||
|
|
|
@ -19,8 +19,6 @@
|
||||||
--*/
|
--*/
|
||||||
|
|
||||||
namespace nla {
|
namespace nla {
|
||||||
bool is_set(unsigned j) { return static_cast<int>(j) != -1; }
|
|
||||||
|
|
||||||
|
|
||||||
typedef lp::constraint_index lpci;
|
typedef lp::constraint_index lpci;
|
||||||
typedef lp::explanation expl_set;
|
typedef lp::explanation expl_set;
|
||||||
|
@ -41,24 +39,15 @@ struct vars_equivalence {
|
||||||
rational m_sign;
|
rational m_sign;
|
||||||
lpci m_c0;
|
lpci m_c0;
|
||||||
lpci m_c1;
|
lpci m_c1;
|
||||||
lpci m_c2;
|
|
||||||
lpci m_c3;
|
equiv(lpvar i, lpvar j, rational const& sign, lpci c0, lpci c1) :
|
||||||
equiv(lpvar i, lpvar j, rational const& sign,
|
|
||||||
lpci c0,
|
|
||||||
lpci c1,
|
|
||||||
lpci c2,
|
|
||||||
lpci c3
|
|
||||||
) :
|
|
||||||
m_i(i),
|
m_i(i),
|
||||||
m_j(j),
|
m_j(j),
|
||||||
m_sign(sign),
|
m_sign(sign),
|
||||||
m_c0(c0),
|
m_c0(c0),
|
||||||
m_c1(c1),
|
m_c1(c1) {
|
||||||
m_c2(c2),
|
|
||||||
m_c3(c3) {
|
|
||||||
SASSERT(m_i != m_j);
|
SASSERT(m_i != m_j);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct node {
|
struct node {
|
||||||
|
@ -150,11 +139,7 @@ struct vars_equivalence {
|
||||||
}
|
}
|
||||||
|
|
||||||
void add_equiv(lpvar i, lpvar j, rational const& sign, lpci c0, lpci c1) {
|
void add_equiv(lpvar i, lpvar j, rational const& sign, lpci c0, lpci c1) {
|
||||||
m_equivs.push_back(equiv(i, j, sign, c0, c1, -1, -1));
|
m_equivs.push_back(equiv(i, j, sign, c0, c1));
|
||||||
}
|
|
||||||
|
|
||||||
void add_equiv(lpvar i, lpvar j, rational const& sign, lpci c0, lpci c1, lpci c2, lpci c3) {
|
|
||||||
m_equivs.push_back(equiv(i, j, sign, c0, c1, c2, c3));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void connect_equiv_to_tree(unsigned k) {
|
void connect_equiv_to_tree(unsigned k) {
|
||||||
|
@ -262,14 +247,8 @@ struct vars_equivalence {
|
||||||
if (it->second.m_parent == static_cast<unsigned>(-1))
|
if (it->second.m_parent == static_cast<unsigned>(-1))
|
||||||
return;
|
return;
|
||||||
const equiv & e = m_equivs[it->second.m_parent];
|
const equiv & e = m_equivs[it->second.m_parent];
|
||||||
if (is_set(e.m_c0))
|
|
||||||
exp.add(e.m_c0);
|
exp.add(e.m_c0);
|
||||||
if (is_set(e.m_c1))
|
|
||||||
exp.add(e.m_c1);
|
exp.add(e.m_c1);
|
||||||
if (is_set(e.m_c2))
|
|
||||||
exp.add(e.m_c2);
|
|
||||||
if (is_set(e.m_c3))
|
|
||||||
exp.add(e.m_c3);
|
|
||||||
j = get_parent_node(j, e);
|
j = get_parent_node(j, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue