3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-05-13 02:34:43 +00:00

Polysat: fixes in solver, forbidden intervals for eq_constraint (#5240)

* Rename to neg_cond

* Add some logging utilities

* Implement case of forbidden interval covering the whole domain

* Implement diseq_narrow

* Do not activate constraint if we are in a conflict state

* comments

* Assert that lemma isn't undefined

* Update revert_decision to work in the case where narrowing causes propagation

* Fix case of non-disjunctive lemma from forbidden intervals

* Conflict should not leak outside user scope

* Add guard to decide(), some notes

* Add test case

* Add constraints to watchlist of unassigned variable during propagation

* Move common propagation functionality into base class

* Combine eq/diseq narrow

* Compute forbidden interval for equality constraints by considering them as p <=u 0 (or p >u 0 for disequalities)
This commit is contained in:
Jakob Rath 2021-05-03 18:30:17 +02:00 committed by GitHub
parent 04876ba8b7
commit f7e476a4a0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 350 additions and 130 deletions

View file

@ -20,7 +20,7 @@ namespace polysat {
struct fi_record {
eval_interval interval;
scoped_ptr<constraint> cond; // could be multiple constraints later
scoped_ptr<constraint> neg_cond; // could be multiple constraints later
constraint* src;
};
@ -72,15 +72,12 @@ namespace polysat {
for (constraint* c : conflict) {
LOG("constraint: " << *c);
eval_interval interval = eval_interval::full();
constraint* cond = nullptr; // TODO: change to scoped_ptr
if (c->forbidden_interval(s, v, interval, cond)) {
constraint* neg_cond = nullptr; // TODO: change to scoped_ptr
if (c->forbidden_interval(s, v, interval, neg_cond)) {
LOG("~> interval: " << interval);
if (cond)
LOG(" cond: " << *cond);
else
LOG(" cond: <null>");
LOG(" neg_cond: " << show_deref(neg_cond));
if (interval.is_currently_empty()) {
dealloc(cond);
dealloc(neg_cond);
continue;
}
if (interval.is_full())
@ -92,19 +89,20 @@ namespace polysat {
longest_i = records.size();
}
}
records.push_back({std::move(interval), cond, c});
records.push_back({std::move(interval), neg_cond, c});
if (has_full)
break;
}
}
LOG("has_full: " << std::boolalpha << has_full);
if (has_full) {
auto const& full_record = records.back();
// We have a single interval covering the whole domain
// => the side conditions of that interval are enough to produce a conflict
auto& full_record = records.back();
SASSERT(full_record.interval.is_full());
LOG("has_full: " << std::boolalpha << has_full);
// TODO: use full interval to explain
NOT_IMPLEMENTED_YET();
return false;
out_lemma = std::move(full_record.neg_cond);
return true;
}
if (records.empty())
@ -153,9 +151,9 @@ namespace polysat {
literals.push_back(c);
// Side conditions
// TODO: check whether the condition is subsumed by c? maybe at the end do a "lemma reduction" step, to try and reduce branching?
scoped_ptr<constraint>& cond = records[i].cond;
if (cond)
literals.push_back(cond.detach());
scoped_ptr<constraint>& neg_cond = records[i].neg_cond;
if (neg_cond)
literals.push_back(neg_cond.detach());
}
out_lemma = std::move(literals);