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

Simplify find_viable

This commit is contained in:
Jakob Rath 2023-11-06 10:37:14 +01:00
parent f309dfeac7
commit 60a9472c8c
2 changed files with 24 additions and 71 deletions

View file

@ -35,8 +35,6 @@ TODO: plan to fix the FI "pumping":
namespace polysat { namespace polysat {
using namespace viable_query;
struct inf_fi : public inference { struct inf_fi : public inference {
viable& v; viable& v;
pvar var; pvar var;
@ -1441,11 +1439,6 @@ namespace {
} }
} }
lbool viable::find_viable2(pvar v, rational& lo, rational& hi) {
std::pair<rational&, rational&> args{lo, hi};
return query<query_t::find_viable>(v, args);
}
bool viable::has_upper_bound(pvar v, rational& out_hi, vector<signed_constraint>& out_c) { bool viable::has_upper_bound(pvar v, rational& out_hi, vector<signed_constraint>& out_c) {
entry const* first = m_units[v].get_entries(s.size(v)); // TODO: take other sizes into account entry const* first = m_units[v].get_entries(s.size(v)); // TODO: take other sizes into account
entry const* e = first; entry const* e = first;
@ -1618,8 +1611,7 @@ namespace {
} }
template <query_t mode> lbool viable::find_viable2(pvar v, rational& lo, rational& hi) {
lbool viable::query(pvar v, typename query_result<mode>::result_t& result) {
fixed_bits_info fbi; fixed_bits_info fbi;
@ -1695,16 +1687,7 @@ namespace {
unsigned refinements = refinement_budget; unsigned refinements = refinement_budget;
while (refinements--) { while (refinements--) {
lbool res = l_undef; lbool res = query_find(v, lo, hi, fbi);
if constexpr (mode == query_t::find_viable)
res = query_find(v, result.first, result.second, fbi);
else if constexpr (mode == query_t::has_viable) {
NOT_IMPLEMENTED_YET();
}
else {
UNREACHABLE();
}
IF_VERBOSE(10, { IF_VERBOSE(10, {
if (refinements % 100 == 0) if (refinements % 100 == 0)
verbose_stream() << "Refinements " << refinements << "\n"; verbose_stream() << "Refinements " << refinements << "\n";
@ -1714,7 +1697,8 @@ namespace {
} }
IF_VERBOSE(10, verbose_stream() << "Fallback\n";); IF_VERBOSE(10, verbose_stream() << "Fallback\n";);
LOG("Refinement budget exhausted! Fall back to univariate solver."); LOG("Refinement budget exhausted! Fall back to univariate solver.");
return query_fallback<mode>(v, result);
return find_viable_fallback(v, lo, hi);
} }
lbool viable::query_find(pvar v, rational& lo, rational& hi, fixed_bits_info const& fbi) { lbool viable::query_find(pvar v, rational& lo, rational& hi, fixed_bits_info const& fbi) {
@ -1770,6 +1754,14 @@ namespace {
return l_false; return l_false;
} }
// TODO: we could also try to continue the search at lo+1, if we get stuck at the upper bound.
// TODO: we only need (any) 2 viable values. some possibilities:
// - find lower and upper bound
// - find lower bound and next lowest value
// - find upper bound and next highest value
// - try a random sample and chase value from there
// find upper bound // find upper bound
hi = max_value; hi = max_value;
e = last; e = last;
@ -1788,14 +1780,13 @@ namespace {
return l_true; return l_true;
} }
template <query_t mode> lbool viable::find_viable_fallback(pvar v, rational& lo, rational& hi) {
lbool viable::query_fallback(pvar v, typename query_result<mode>::result_t& result) {
unsigned const bit_width = s.size(v); unsigned const bit_width = s.size(v);
univariate_solver* us = s.m_viable_fallback.usolver(bit_width); univariate_solver* us = s.m_viable_fallback.usolver(bit_width);
sat::literal_set added; sat::literal_set added;
// First step: only query the looping constraints and see if they alone are already UNSAT. // First step: only query the looping constraints and see if they alone are already UNSAT.
// The constraints which caused the refinement loop will be reached from m_units. // The constraints which caused the refinement loop can always be reached from m_units.
LOG_H3("Checking looping univariate constraints for v" << v << "..."); LOG_H3("Checking looping univariate constraints for v" << v << "...");
LOG("Assignment: " << assignments_pp(s)); LOG("Assignment: " << assignments_pp(s));
entry const* first = m_units[v].get_entries(s.size(v)); // TODO: take other sizes into account entry const* first = m_units[v].get_entries(s.size(v)); // TODO: take other sizes into account
@ -1847,30 +1838,14 @@ namespace {
s.set_conflict_by_viable_fallback(v, *us); s.set_conflict_by_viable_fallback(v, *us);
return l_false; return l_false;
case l_true: case l_true:
// pass solver to mode-specific query lo = us->model();
break; hi = -1;
return l_true;
// TODO: return us.find_two(lo, hi) ? l_true : l_undef; ???
default: default:
// resource limit // resource limit
return l_undef; return l_undef;
} }
if constexpr (mode == query_t::find_viable)
return query_find_fallback(v, *us, result.first, result.second);
if constexpr (mode == query_t::has_viable) {
NOT_IMPLEMENTED_YET();
return l_undef;
}
UNREACHABLE();
return l_undef;
}
lbool viable::query_find_fallback(pvar v, univariate_solver& us, rational& lo, rational& hi) {
lo = us.model();
hi = -1;
return l_true;
// return us.find_two(lo, hi) ? l_true : l_undef;
} }
bool viable::resolve_fallback(pvar v, univariate_solver& us, conflict& core) { bool viable::resolve_fallback(pvar v, univariate_solver& us, conflict& core) {

View file

@ -43,22 +43,6 @@ namespace polysat {
std::ostream& operator<<(std::ostream& out, find_t x); std::ostream& operator<<(std::ostream& out, find_t x);
namespace viable_query {
enum class query_t {
has_viable, // currently only used internally in resolve_viable
find_viable,
};
template <query_t mode>
struct query_result {
};
template <>
struct query_result<query_t::find_viable> {
using result_t = std::pair<rational&, rational&>;
};
}
class viable { class viable {
friend class test_fi; friend class test_fi;
friend class test_polysat; friend class test_polysat;
@ -203,25 +187,17 @@ namespace polysat {
lbool query_find(pvar v, rational& out_lo, rational& out_hi, fixed_bits_info const& fbi); lbool query_find(pvar v, rational& out_lo, rational& out_hi, fixed_bits_info const& fbi);
/** /**
* Bitblasting-based queries. * Find a next viable value for variable. Attempts to find two different values, to distinguish propagation/decision.
* The univariate solver has already been filled with all relevant constraints and check() returned l_true. * NOTE: out_hi is set to -1 by the fallback solver.
* @return l_true on success, l_false on conflict, l_undef on resource limit * @return l_true on success, l_false on conflict, l_undef on resource limit
*/ */
lbool query_find_fallback(pvar v, univariate_solver& us, rational& out_lo, rational& out_hi); lbool find_viable2(pvar v, rational& out_lo, rational& out_hi);
/**
* Interval-based query with bounded refinement and fallback to bitblasting.
* @return l_true on success, l_false on conflict, l_undef on resource limit
*/
template <viable_query::query_t mode>
lbool query(pvar v, typename viable_query::query_result<mode>::result_t& out_result);
/** /**
* Bitblasting-based query. * Bitblasting-based query.
* @return l_true on success, l_false on conflict, l_undef on resource limit * @return l_true on success, l_false on conflict, l_undef on resource limit
*/ */
template <viable_query::query_t mode> lbool find_viable_fallback(pvar v, rational& out_lo, rational& out_hi);
lbool query_fallback(pvar v, typename viable_query::query_result<mode>::result_t& out_result);
public: public:
viable(solver& s); viable(solver& s);
@ -291,6 +267,8 @@ namespace polysat {
* @return l_true on success, l_false on conflict, l_undef on resource limit * @return l_true on success, l_false on conflict, l_undef on resource limit
*/ */
lbool find_viable2(pvar v, rational& out_lo, rational& out_hi); lbool find_viable2(pvar v, rational& out_lo, rational& out_hi);
lbool find_viable_fallback(pvar v, rational& out_lo, rational& out_hi);
public: public:
#if 0 #if 0