3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-21 05:13:39 +00:00
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2021-11-18 15:53:51 -08:00
commit 6bf4f001d9
6 changed files with 51 additions and 49 deletions

View file

@ -81,7 +81,7 @@ namespace polysat {
} }
else { else {
SASSERT(c.is_currently_false(s)); SASSERT(c.is_currently_false(s));
SASSERT(c.bvalue(s) == l_true); // TBD: fails with test_subst SASSERT(c.bvalue(s) == l_true);
c->set_var_dependent(); c->set_var_dependent();
insert(c); insert(c);
} }
@ -111,6 +111,8 @@ namespace polysat {
* The clause is conflicting in the current search state. * The clause is conflicting in the current search state.
*/ */
void conflict::set(clause const& cl) { void conflict::set(clause const& cl) {
if (!empty())
return;
LOG("Conflict: " << cl); LOG("Conflict: " << cl);
SASSERT(empty()); SASSERT(empty());
for (auto lit : cl) for (auto lit : cl)

View file

@ -369,7 +369,7 @@ namespace polysat {
rational const& a2, pdd const& b2, pdd const& e2, rational const& a2, pdd const& b2, pdd const& e2,
eval_interval& interval, vector<signed_constraint>& side_cond) { eval_interval& interval, vector<signed_constraint>& side_cond) {
if (a1.is_odd() && a2.is_zero() && b2.val().is_zero()) { if (a1.is_odd() && a2.is_zero() && b2.val().is_zero()) {
push_eq(false, e2, side_cond); push_eq(true, e2, side_cond);
rational a_inv, pow2 = e1.manager().max_value() + 1; rational a_inv, pow2 = e1.manager().max_value() + 1;
VERIFY(a1.mult_inverse(e1.manager().power_of_2(), a_inv)); VERIFY(a1.mult_inverse(e1.manager().power_of_2(), a_inv));
auto lo = -e1 * a_inv; auto lo = -e1 * a_inv;

View file

@ -77,6 +77,9 @@ namespace polysat {
if (!c.is_currently_false(s) && c.bvalue(s) != l_false) if (!c.is_currently_false(s) && c.bvalue(s) != l_false)
return false; return false;
if (c.bvalue(s) == l_true)
return false;
// avoid loops // avoid loops
if (core.contains(~c)) if (core.contains(~c))
return false; return false;

View file

@ -134,13 +134,15 @@ namespace polysat {
m_constraints.ensure_bvar(c.get()); m_constraints.ensure_bvar(c.get());
sat::literal lit = c.blit(); sat::literal lit = c.blit();
LOG("New constraint: " << c); LOG("New constraint: " << c);
if (m_bvars.is_false(lit) || c.is_currently_false(*this)) { if (m_bvars.is_false(lit))
set_conflict(c /*, dep */); set_conflict(c);
return; else {
m_bvars.asserted(lit, m_level, dep);
m_trail.push_back(trail_instr_t::assign_bool_i);
m_search.push_boolean(lit);
if (c.is_currently_false(*this))
set_conflict(c);
} }
m_bvars.asserted(lit, m_level, dep);
m_trail.push_back(trail_instr_t::assign_bool_i);
m_search.push_boolean(lit);
#if ENABLE_LINEAR_SOLVER #if ENABLE_LINEAR_SOLVER
m_linear_solver.new_constraint(*c.get()); m_linear_solver.new_constraint(*c.get());
@ -582,38 +584,43 @@ namespace polysat {
return; return;
case l_false: case l_false:
break; break;
case l_undef: case l_undef:
num_choices++;
if (lit2cnstr(lit).is_currently_false(*this)) { if (lit2cnstr(lit).is_currently_false(*this)) {
unsigned level = m_level; // TODO unsigned level = m_level; // TODO
assign_eval(level, lit); assign_eval(level, lit);
} }
else else {
num_choices++;
choice = lit; choice = lit;
}
break; break;
} }
} }
LOG_V("num_choices: " << num_choices); LOG_V("num_choices: " << num_choices);
if (choice == sat::null_literal) { switch (num_choices) {
// This case may happen when all undefined literals are false under the current variable assignment. case 0:
// TODO: The question is whether such lemmas should be generated? Check test_monot() for such a case.
set_conflict(lemma); set_conflict(lemma);
return; break;
} case 1:
signed_constraint c = lit2cnstr(choice);
if (num_choices > 1)
push_level();
if (num_choices == 1)
assign_propagate(choice, lemma); assign_propagate(choice, lemma);
else break;
default:
push_level();
assign_decision(choice, &lemma); assign_decision(choice, &lemma);
break;
}
} }
/** /**
* Revert a decision that caused a conflict. * Revert a decision that caused a conflict.
* Variable v was assigned by a decision at position i in the search stack. * Variable v was assigned by a decision at position i in the search stack.
*
* C & v = val is conflict.
*
* C => v != val
*
* l1 \/ l2 \/ ... \/ lk \/ v != val
*
*/ */
void solver::revert_decision(pvar v) { void solver::revert_decision(pvar v) {
rational val = m_value[v]; rational val = m_value[v];
@ -621,21 +628,14 @@ namespace polysat {
SASSERT(m_justification[v].is_decision()); SASSERT(m_justification[v].is_decision());
clause_ref lemma = m_conflict.build_lemma().build(); clause_ref lemma = m_conflict.build_lemma().build();
if (lemma->empty()) { if (lemma->empty())
report_unsat(); report_unsat();
return; else {
} m_conflict.reset();
m_conflict.reset(); backjump(get_level(v) - 1);
learn_lemma(*lemma);
backjump(get_level(v) - 1);
// The justification for this restriction is the guessed constraint from the lemma.
// cjust[v] will be updated accordingly by decide_bool.
// m_viable.add_non_viable(v, val);
learn_lemma(*lemma);
if (!is_conflict())
narrow(v); narrow(v);
}
} }
bool solver::is_decision(search_item const& item) const { bool solver::is_decision(search_item const& item) const {
@ -685,11 +685,8 @@ namespace polysat {
backjump(m_bvars.level(var) - 1); backjump(m_bvars.level(var) - 1);
add_lemma(*reason); add_lemma(*reason);
if (is_conflict()) {
LOG_H1("Conflict during revert_bool_decision/propagate_bool!"); if (!is_conflict() && lemma)
return;
}
if (lemma)
decide_bool(*lemma); decide_bool(*lemma);
} }
@ -763,7 +760,8 @@ namespace polysat {
* placeholder for factoring/gcd common factors * placeholder for factoring/gcd common factors
*/ */
void solver::narrow(pvar v) { void solver::narrow(pvar v) {
if (is_conflict())
return;
} }
// Add lemma to storage // Add lemma to storage

View file

@ -10,7 +10,6 @@ Author:
Nikolaj Bjorner (nbjorner) 2021-03-19 Nikolaj Bjorner (nbjorner) 2021-03-19
Jakob Rath 2021-04-6 Jakob Rath 2021-04-6
--*/ --*/
@ -46,13 +45,12 @@ namespace polysat {
void viable2::push_viable() { void viable2::push_viable() {
auto& [v, e] = m_trail.back(); auto& [v, e] = m_trail.back();
SASSERT(e->prev() != e || !m_viable[v]);
SASSERT(e->prev() != e || e->next() == e);
if (e->prev() != e) if (e->prev() != e)
e->prev()->insert_after(e); e->prev()->insert_after(e);
else { else
SASSERT(!m_viable[v]); m_viable[v] = e;
SASSERT(e->next() == e);
m_viable[v] = e;
}
m_trail.pop_back(); m_trail.pop_back();
} }

View file

@ -1071,11 +1071,12 @@ void tst_polysat() {
// polysat::test_ineq_axiom2(); // polysat::test_ineq_axiom2();
// polysat::test_ineq_axiom3(); // polysat::test_ineq_axiom3();
// polysat::test_ineq_non_axiom1(); // polysat::test_ineq_non_axiom1();
#if 0
polysat::test_ineq_non_axiom4(32, 5); polysat::test_ineq_non_axiom4(32, 5);
polysat::test_ineq_axiom4(); polysat::test_ineq_axiom4();
polysat::test_ineq_axiom5(); polysat::test_ineq_axiom5();
polysat::test_ineq_axiom6(); polysat::test_ineq_axiom6();
#endif
// working // working
// NOT: polysat::test_fixed_point_arith_mul_div_inverse(); // NOT: polysat::test_fixed_point_arith_mul_div_inverse();