3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-24 12:07:52 +00:00

make_asserting for unit coefficients

This commit is contained in:
Jakob Rath 2022-08-19 16:02:56 +02:00
parent 9766ad00b1
commit c3e7bd34d0
4 changed files with 90 additions and 0 deletions

View file

@ -1193,6 +1193,69 @@ namespace polysat {
if (all_ok) LOG("All good!");
return all_ok;
}
// All variables of clause 'cl' except 'z' are assigned.
// Goal: a possibly weaker clause that implies a restriction on z around z_val
clause_ref solver::make_asserting(clause& cl, pvar z, rational z_val) {
signed_constraints cz; // constraints of 'cl' that contain 'z'
sat::literal_vector lits; // literals of the new clause
for (sat::literal lit : cl) {
signed_constraint c = lit2cnstr(lit);
if (c.contains_var(z))
cz.push_back(c);
else
lits.push_back(lit);
}
SASSERT(!cz.empty());
if (cz.size() == 1) {
// TODO: even in this case, if the constraint is non-linear in z, we might want to extract a maximal forbidden interval around z_val.
return nullptr;
}
else {
// multiple constraints that contain z
find_implied_constraint(cz, z, z_val, lits);
return clause::from_literals(std::move(lits));
}
}
// Each constraint in 'cz' is univariate in 'z' under the current assignment.
// Goal: a literal that is implied by the disjunction of cz and ensures z != z_val in viable.
// (plus side conditions that do not depend on z)
void solver::find_implied_constraint(signed_constraints const& cz, pvar z, rational z_val, sat::literal_vector& out_lits)
{
unsigned const out_lits_original_size = out_lits.size();
forbidden_intervals fi(*this);
fi_record entry({ eval_interval::full(), {}, {}, rational::one()});
auto intersection = eval_interval::full();
bool all_unit = true;
for (signed_constraint const& c : cz) {
if (fi.get_interval(c, z, entry) && entry.coeff == 1) {
intersection = intersection.intersect(entry.interval);
for (auto const& sc : entry.side_cond)
out_lits.push_back(sc.blit());
} else {
all_unit = false;
break;
}
}
if (all_unit) {
// Unit intervals from all constraints
// => build constraint from intersection of forbidden intervals
// z \not\in [l;u[ <=> z - l >= u - l
auto c_new = ule(intersection.hi() - intersection.lo(), z - intersection.lo());
out_lits.push_back(c_new.blit());
return;
} else {
out_lits.shrink(out_lits_original_size);
// TODO: SAT-based approach
}
}
}