3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-24 09:35:32 +00:00

Try to produce an op_constraint lemma before invoking the fallback solver

This commit is contained in:
Jakob Rath 2022-11-30 12:13:47 +01:00
parent 2bc1b3a6dd
commit b4b94c954b
3 changed files with 37 additions and 18 deletions

View file

@ -633,15 +633,32 @@ namespace polysat {
/// Verify the value we're trying to assign against the univariate solver
void solver::assign_verify(pvar v, rational val, justification j) {
SASSERT(j.is_decision() || j.is_propagation());
// First, check evaluation of the currently-univariate constraints
// TODO: we should add a better way to test constraints under assignments, without modifying the solver state.
m_value[v] = val;
m_search.push_assignment(v, val);
m_justification[v] = j;
bool is_valid = m_viable_fallback.check_constraints(v);
m_search.pop();
m_justification[v] = justification::unassigned();
if (!is_valid) {
signed_constraint c;
{
// Fake the assignment v := val so we can check the constraints using the new value.
m_value[v] = val;
m_search.push_assignment(v, val);
m_justification[v] = j;
on_scope_exit _undo([&](){
m_search.pop();
m_justification[v] = justification::unassigned();
});
// Check evaluation of the currently-univariate constraints.
c = m_viable_fallback.find_violated_constraint(v);
if (c) {
LOG("Violated constraint: " << c);
// op_constraints produce lemmas rather than forbidden intervals, so give it an opportunity to
// produce a lemma before invoking the fallback solver.
if (c->is_op()) {
c.narrow(*this, false);
if (is_conflict())
return;
}
}
}
if (c) {
LOG_H2("Chosen assignment " << assignment_pp(*this, v, val) << " is not actually viable!");
++m_stats.m_num_viable_fallback;
// Try to find a valid replacement value

View file

@ -837,17 +837,17 @@ namespace polysat {
m_constraints[v].pop_back();
}
bool viable_fallback::check_constraints(pvar v) {
for (auto const& c : m_constraints[v]) {
signed_constraint viable_fallback::find_violated_constraint(pvar v) {
for (signed_constraint const c : m_constraints[v]) {
// for this check, all variables need to be assigned
DEBUG_CODE(for (pvar w : c->vars()) { SASSERT(s.is_assigned(w)); });
if (c.is_currently_false(s)) {
LOG(assignment_pp(s, v, s.get_value(v)) << " violates constraint " << lit_pp(s, c));
return false;
return c;
}
SASSERT(c.is_currently_true(s));
}
return true;
return {};
}
dd::find_t viable_fallback::find_viable(pvar v, rational& out_val) {
@ -869,6 +869,7 @@ namespace polysat {
auto const& cs = m_constraints[v];
for (unsigned i = cs.size(); i-- > 0; ) {
LOG("Univariate constraint: " << cs[i]);
cs[i].add_to_univariate_solver(s, *us, i);
}

View file

@ -102,10 +102,9 @@ namespace polysat {
bool is_viable(pvar v, rational const& val);
/*
* Extract min and max viable values for v
*/
* Extract min and max viable values for v
*/
rational min_viable(pvar v);
rational max_viable(pvar v);
/**
@ -249,8 +248,10 @@ namespace polysat {
void push_constraint(pvar v, signed_constraint const& c);
void pop_constraint();
// Check whether all constraints for 'v' are satisfied.
bool check_constraints(pvar v);
// Check whether all constraints for 'v' are satisfied;
// or find an arbitrary violated constraint.
bool check_constraints(pvar v) { return !find_violated_constraint(v); }
signed_constraint find_violated_constraint(pvar v);
dd::find_t find_viable(pvar v, rational& out_val);
signed_constraints unsat_core(pvar v);