3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-24 06:43:40 +00:00

niil_solver basic case zero

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
Lev Nachmanson 2018-08-21 12:14:45 +08:00
parent eca5ddaa04
commit 237db5cb3d

View file

@ -252,7 +252,7 @@ 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_explanation_and_lemma(m_monomials[i_mon], fill_explanation_and_lemma_sign(m_monomials[i_mon],
other_m, other_m,
sign* other_sign); sign* other_sign);
return true; return true;
@ -277,7 +277,7 @@ struct solver::imp {
} }
} }
// the monomials should be equal by modulo sign, but they are not equal in the model // 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) { void fill_explanation_and_lemma_sign(const mon_eq& a, const mon_eq & b, int sign) {
expl_set expl; expl_set expl;
SASSERT(sign == 1 || sign == -1); SASSERT(sign == 1 || sign == -1);
add_expl_from_monomial(a, expl); add_expl_from_monomial(a, expl);
@ -341,26 +341,17 @@ struct solver::imp {
return false; return false;
} }
// Return 0 if the monomial has to to have a zero value, bool is_set(unsigned j) const {
// -1 if the monomial has to be negative return static_cast<unsigned>(-1) != j;
// 1 if positive. }
// Otherwise return 2. bool get_mon_sign_zero_var_loop_body(lpvar j, lpci ci, lpci & lci, lpci & uci,
int get_mon_sign_zero_var(unsigned j) { rational& lb, rational &ub) const {
auto it = m_var_lists.find(j);
if (it == m_var_lists.end())
return 2;
lpci lci = -1;
lpci uci = -1;
rational lb, ub;
for (lpci ci : it->second.m_constraints) {
const auto * c = m_lar_solver.constraints()[ci]; const auto * c = m_lar_solver.constraints()[ci];
if (c->size() != 1) if (c->size() != 1)
continue; return false;
const auto coeffs = c->get_left_side_coefficients(); const auto coeffs = c->get_left_side_coefficients();
SASSERT(coeffs[0].second == j); SASSERT(coeffs[0].second == j);
auto kind = c->m_kind; auto kind = c->m_kind;
const rational& a = coeffs[0].first; const rational& a = coeffs[0].first;
if (a.is_neg()) if (a.is_neg())
kind = lp::flip_kind(kind); kind = lp::flip_kind(kind);
@ -368,9 +359,9 @@ struct solver::imp {
rational rs = c->m_right_side / a ; rational rs = c->m_right_side / a ;
SASSERT(rs.is_int()); SASSERT(rs.is_int());
switch(kind) { switch(kind) {
lecase: le_case:
case lp::LE: case lp::LE:
if (uci == static_cast<unsigned>(-1)) { if (!is_set(uci)) {
uci = ci; uci = ci;
ub = rs; ub = rs;
} else { } else {
@ -383,11 +374,11 @@ struct solver::imp {
case lp::LT: case lp::LT:
rs -= 1; rs -= 1;
goto lecase; goto le_case;
gecase: ge_case:
case lp::GE: case lp::GE:
if (lci == static_cast<unsigned>(-1)) { if (!is_set(lci)) {
lci = ci; lci = ci;
lb = rs; lb = rs;
} else { } else {
@ -400,58 +391,139 @@ struct solver::imp {
case lp::GT: case lp::GT:
rs += 1; rs += 1;
goto gecase; goto ge_case;
case lp::EQ: case lp::EQ:
uci = lci = ci; uci = lci = ci;
ub = lb = rs; ub = lb = rs;
break; break;
default: default:
continue; return false;
} }
return true;
} }
return 2;
}
// Return 0 if the monomial has to to have a zero value, // Return 0 if the monomial has to to have a zero value,
// -1 if the monomial has to be negative // -1 if the monomial has to be negative
// 1 if positive. // 1 if positive.
// Otherwise return 2. // If strict is true on the entrance then it can be set to false,
int get_mon_sign_zero(unsigned i_mon) { // otherwise it remains false
// Returns true if the sign is not defined.
int get_mon_sign_zero_var(unsigned j, bool & strict) {
auto it = m_var_lists.find(j);
if (it == m_var_lists.end())
return 2;
lpci lci = -1;
lpci uci = -1;
rational lb, ub;
for (lpci ci : it->second.m_constraints) {
if (get_mon_sign_zero_var_loop_body(j, ci, lci, uci, lb, ub) == false)
continue;
if (is_set(uci) && is_set(lci) && ub == lb) {
if (ub.is_zero()){
m_expl->clear();
m_expl->push_justification(uci);
m_expl->push_justification(lci);
return 0;
}
m_expl->push_justification(uci);
m_expl->push_justification(lci);
return ub.is_pos() ? 1 : -1;
}
if (is_set(uci)) {
if (ub.is_neg()) {
m_expl->push_justification(uci);
return -1;
}
if (ub.is_zero()) {
strict = false;
m_expl->push_justification(uci);
return -1;
}
}
if (is_set(lci)) {
if (lb.is_pos()) {
m_expl->push_justification(lci);
return 1;
}
if (lb.is_zero()) {
strict = false;
m_expl->push_justification(lci);
return 1;
}
}
}
return 2; // the sign of the variable is not defined
}
// Return 0 if the monomial has to to have a zero value,
// -1 if the monomial has to be negative or zero
// 1 if positive or zero
// otherwise return 2 (2 is not a sign!)
// if strict is true then 0 is excluded
int get_mon_sign_zero(unsigned i_mon, bool & strict) {
int sign = 1; int sign = 1;
strict = true;
const mon_eq m = m_monomials[i_mon]; const mon_eq m = m_monomials[i_mon];
for (lpvar j : m.m_vs) { for (lpvar j : m.m_vs) {
int s = get_mon_sign_zero_var(j); int s = get_mon_sign_zero_var(j, strict);
if (s == 2) if (s == 2)
break; return 2;;
if (s == 0) if (s == 0)
return 0; return 0;
sign *= s; sign *= s;
} }
return 2; return sign;
} }
bool generate_basic_lemma_for_mon_zero(unsigned i_mon) { bool generate_basic_lemma_for_mon_zero(unsigned i_mon) {
int sign = get_mon_sign_zero(i_mon); const rational & mon_val = m_lar_solver.get_column_value(m_monomials[i_mon].var()).x;
bool strict;
int sign = get_mon_sign_zero(i_mon, strict);
lp::lconstraint_kind kind; lp::lconstraint_kind kind;
rational rs(0);
switch(sign) { switch(sign) {
case 0: case 0:
SASSERT(!mon_val.is_zero());
kind = lp::lconstraint_kind::EQ; kind = lp::lconstraint_kind::EQ;
break; break;
case 1: case 1:
kind = lp::lconstraint_kind::GT; if (strict)
rs = rational(1);
if (mon_val >= rs)
return false;
kind = lp::lconstraint_kind::GE;
break; break;
case -1: case -1:
kind = lp::lconstraint_kind::LT; if (strict)
rs = rational(-1);
if (mon_val <= rs)
return false;
kind = lp::lconstraint_kind::LE;
break; break;
default: default:
return false; return false;
} }
lp::lar_term t; lp::lar_term t;
t.add_monomial(rational(1), m_monomials[i_mon].var()); t.add_monomial(rational(1), m_monomials[i_mon].var());
t.m_v = -rs;
ineq in(kind, t); ineq in(kind, t);
m_lemma->push_back(in); m_lemma->push_back(in);
TRACE("niil_solver",
for (auto &p : *m_expl)
m_lar_solver.print_constraint(p.second, tout); tout << "\n";
m_lar_solver.print_term(t, tout);
tout << " " << lp::lconstraint_kind_string(kind) << " 0\n";
print_monomial(m_monomials[i_mon], tout); tout << "\n";
lpvar mon_var = m_monomials[i_mon].var();
tout << m_lar_solver.get_column_name(mon_var) << " = " << m_lar_solver.get_column_value(mon_var);
);
return true; return true;
} }