mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
univariate::find_min
This commit is contained in:
parent
37536425f4
commit
31e0add966
3 changed files with 118 additions and 5 deletions
|
@ -98,14 +98,14 @@ namespace polysat {
|
|||
return mk_numeral(rational::zero());
|
||||
}
|
||||
else {
|
||||
expr* e = mk_numeral(p.back());
|
||||
expr* e = mk_numeral(p[0]);
|
||||
expr* xpow = x;
|
||||
for (unsigned i = p.size() - 1; i-- > 0; ) {
|
||||
for (unsigned i = 1; i < p.size(); ++i) {
|
||||
if (!p[i].is_zero()) {
|
||||
expr* t = mk_poly_term(p[i], xpow);
|
||||
e = bv->mk_bv_add(e, t);
|
||||
}
|
||||
if (i)
|
||||
if (i + 1 < p.size())
|
||||
xpow = bv->mk_bv_mul(xpow, x);
|
||||
}
|
||||
return e;
|
||||
|
@ -205,6 +205,34 @@ namespace polysat {
|
|||
return p.get_rational();
|
||||
}
|
||||
|
||||
bool find_min(rational& val) override {
|
||||
val = model();
|
||||
push();
|
||||
// try reducing val by setting bits to 0, starting at the msb.
|
||||
for (unsigned k = bit_width; k-- > 0; ) {
|
||||
if (!val.get_bit(k)) {
|
||||
add_bit0(k, 0);
|
||||
continue;
|
||||
}
|
||||
push();
|
||||
add_bit0(k, 0);
|
||||
lbool result = check();
|
||||
if (result == l_true) {
|
||||
SASSERT(model() < val);
|
||||
val = model();
|
||||
}
|
||||
pop(1);
|
||||
if (result == l_true)
|
||||
add_bit0(k, 0);
|
||||
else if (result == l_false)
|
||||
add_bit1(k, 0);
|
||||
else
|
||||
return false;
|
||||
}
|
||||
pop(1);
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ostream& display(std::ostream& out) const override {
|
||||
return out << *s;
|
||||
}
|
||||
|
|
|
@ -41,9 +41,17 @@ namespace polysat {
|
|||
virtual void pop(unsigned n) = 0;
|
||||
|
||||
virtual lbool check() = 0;
|
||||
|
||||
// Precondition: check() returned l_false
|
||||
virtual dep_vector unsat_core() = 0;
|
||||
|
||||
// Precondition: check() returned l_true
|
||||
virtual rational model() = 0;
|
||||
|
||||
// Precondition: check() returned l_true
|
||||
// Returns false on resource out.
|
||||
virtual bool find_min(rational& out_min) = 0;
|
||||
|
||||
virtual void add_ule(univariate const& lhs, univariate const& rhs, bool sign, dep_t dep) = 0;
|
||||
virtual void add_umul_ovfl(univariate const& lhs, univariate const& rhs, bool sign, dep_t dep) = 0;
|
||||
virtual void add_smul_ovfl(univariate const& lhs, univariate const& rhs, bool sign, dep_t dep) = 0;
|
||||
|
@ -65,6 +73,8 @@ namespace polysat {
|
|||
|
||||
/// Assert i-th bit of x
|
||||
virtual void add_bit(unsigned idx, bool sign, dep_t dep) = 0;
|
||||
void add_bit0(unsigned idx, dep_t dep) { add_bit(idx, true, dep); }
|
||||
void add_bit1(unsigned idx, dep_t dep) { add_bit(idx, false, dep); }
|
||||
|
||||
virtual std::ostream& display(std::ostream& out) const = 0;
|
||||
};
|
||||
|
|
|
@ -117,8 +117,8 @@ namespace polysat {
|
|||
|
||||
static void test_univariate() {
|
||||
std::cout << "\ntest_univariate\n";
|
||||
unsigned bw = 32;
|
||||
rational modulus = rational::power_of_two(bw);
|
||||
unsigned const bw = 32;
|
||||
rational const modulus = rational::power_of_two(bw);
|
||||
auto factory = mk_univariate_bitblast_factory();
|
||||
auto solver = (*factory)(bw);
|
||||
|
||||
|
@ -182,6 +182,80 @@ namespace polysat {
|
|||
std::cout << "status: " << solver->check() << "\n";
|
||||
std::cout << "core: " << solver->unsat_core() << "\n";
|
||||
}
|
||||
|
||||
static void test_univariate_min() {
|
||||
std::cout << "\ntest_univariate_min\n";
|
||||
unsigned const bw = 32;
|
||||
auto factory = mk_univariate_bitblast_factory();
|
||||
auto solver = (*factory)(bw);
|
||||
|
||||
vector<rational> lhs;
|
||||
vector<rational> rhs;
|
||||
rational min;
|
||||
|
||||
solver->push();
|
||||
|
||||
// c0: 123 <= 2x + 10
|
||||
lhs.clear();
|
||||
lhs.push_back(rational(123));
|
||||
rhs.clear();
|
||||
rhs.push_back(rational(10));
|
||||
rhs.push_back(rational(2));
|
||||
solver->add_ule(lhs, rhs, false, 0);
|
||||
std::cout << "status: " << solver->check() << "\n";
|
||||
std::cout << "model: " << solver->model() << "\n";
|
||||
VERIFY(solver->find_min(min));
|
||||
std::cout << "find_min: " << min << "\n";
|
||||
VERIFY(min == 57); // 57*2 + 10 = 124; 56*2 + 10 = 122
|
||||
|
||||
solver->push();
|
||||
|
||||
// c1: 127 <= x
|
||||
lhs.clear();
|
||||
lhs.push_back(rational(127));
|
||||
rhs.clear();
|
||||
rhs.push_back(rational(0));
|
||||
rhs.push_back(rational(1));
|
||||
solver->add_ule(lhs, rhs, false, 1);
|
||||
std::cout << "status: " << solver->check() << "\n";
|
||||
std::cout << "model: " << solver->model() << "\n";
|
||||
VERIFY(solver->find_min(min));
|
||||
std::cout << "find_min: " << min << "\n";
|
||||
VERIFY(min == 127);
|
||||
|
||||
solver->pop(1);
|
||||
|
||||
// c2: umul_ovfl(2, x)
|
||||
lhs.clear();
|
||||
lhs.push_back(rational(2));
|
||||
rhs.clear();
|
||||
rhs.push_back(rational(0));
|
||||
rhs.push_back(rational(1));
|
||||
solver->add_umul_ovfl(lhs, rhs, false, 2);
|
||||
std::cout << "status: " << solver->check() << "\n";
|
||||
std::cout << "model: " << solver->model() << "\n";
|
||||
VERIFY(solver->find_min(min));
|
||||
std::cout << "find_min: " << min << "\n";
|
||||
solver->add_ule_const(min - 1, false, 3);
|
||||
VERIFY(solver->check() == l_false);
|
||||
|
||||
solver->pop(1);
|
||||
|
||||
// c4: umul_ovfl(2, x)
|
||||
lhs.clear();
|
||||
lhs.push_back(rational(2));
|
||||
rhs.clear();
|
||||
rhs.push_back(rational(0));
|
||||
rhs.push_back(rational(1));
|
||||
solver->add_umul_ovfl(lhs, rhs, false, 4);
|
||||
std::cout << "status: " << solver->check() << "\n";
|
||||
std::cout << "model: " << solver->model() << "\n";
|
||||
VERIFY(solver->find_min(min));
|
||||
std::cout << "find_min: " << min << "\n";
|
||||
solver->add_ule_const(min - 1, false, 5);
|
||||
VERIFY(solver->check() == l_false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -189,5 +263,6 @@ namespace polysat {
|
|||
void tst_viable() {
|
||||
polysat::test1();
|
||||
polysat::test_univariate();
|
||||
polysat::test_univariate_min();
|
||||
polysat::test2(); // takes long
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue