mirror of
https://github.com/Z3Prover/z3
synced 2025-05-04 14:25:46 +00:00
add module for handling axioms for powers
This commit is contained in:
parent
9e2ec9d018
commit
e41dd91893
7 changed files with 343 additions and 201 deletions
|
@ -77,104 +77,7 @@ namespace nla {
|
|||
|
||||
// ensure r = x^y, add abstraction/refinement lemmas
|
||||
lbool solver::check_power(lpvar r, lpvar x, lpvar y, vector<lemma>& lemmas) {
|
||||
if (x == null_lpvar || y == null_lpvar || r == null_lpvar)
|
||||
return l_undef;
|
||||
|
||||
if (use_nra_model())
|
||||
return l_undef;
|
||||
|
||||
auto xval = m_core->val(x);
|
||||
auto yval = m_core->val(y);
|
||||
auto rval = m_core->val(r);
|
||||
|
||||
core& c = get_core();
|
||||
c.set_lemma_vec(lemmas);
|
||||
lemmas.reset();
|
||||
|
||||
// x >= x0 > 0, y >= y0 > 0 => r >= x0^y0
|
||||
// x >= x0 > 0, y <= y0 => r <= x0^y0
|
||||
// x != 0, y = 0 => r = 1
|
||||
// x = 0, y != 0 => r = 0
|
||||
//
|
||||
// for x fixed, it is exponentiation
|
||||
// => use tangent lemmas and error tolerance.
|
||||
|
||||
if (xval > 0 && yval.is_unsigned()) {
|
||||
auto r2val = power(xval, yval.get_unsigned());
|
||||
if (rval == r2val)
|
||||
return l_true;
|
||||
if (xval != 0 && yval == 0) {
|
||||
new_lemma lemma(c, "x != 0 => x^0 = 1");
|
||||
lemma |= ineq(x, llc::EQ, rational::zero());
|
||||
lemma |= ineq(y, llc::NE, rational::zero());
|
||||
lemma |= ineq(r, llc::EQ, rational::one());
|
||||
return l_false;
|
||||
}
|
||||
if (xval == 0 && yval > 0) {
|
||||
new_lemma lemma(c, "y != 0 => 0^y = 0");
|
||||
lemma |= ineq(x, llc::NE, rational::zero());
|
||||
lemma |= ineq(y, llc::EQ, rational::zero());
|
||||
lemma |= ineq(r, llc::EQ, rational::zero());
|
||||
return l_false;
|
||||
}
|
||||
if (xval > 0 && r2val < rval) {
|
||||
SASSERT(yval > 0);
|
||||
new_lemma lemma(c, "x >= x0 > 0, y >= y0 > 0 => r >= x0^y0");
|
||||
lemma |= ineq(x, llc::LT, xval);
|
||||
lemma |= ineq(y, llc::LT, yval);
|
||||
lemma |= ineq(r, llc::GE, r2val);
|
||||
return l_false;
|
||||
}
|
||||
if (xval > 0 && r2val < rval) {
|
||||
new_lemma lemma(c, "x >= x0 > 0, y <= y0 => r <= x0^y0");
|
||||
lemma |= ineq(x, llc::LT, xval);
|
||||
lemma |= ineq(y, llc::GT, yval);
|
||||
lemma |= ineq(r, llc::LE, r2val);
|
||||
return l_false;
|
||||
}
|
||||
}
|
||||
if (xval > 0 && yval > 0 && !yval.is_int()) {
|
||||
auto ynum = numerator(yval);
|
||||
auto yden = denominator(yval);
|
||||
if (!ynum.is_unsigned())
|
||||
return l_undef;
|
||||
if (!yden.is_unsigned())
|
||||
return l_undef;
|
||||
// r = x^{yn/yd}
|
||||
// <=>
|
||||
// r^yd = x^yn
|
||||
auto ryd = power(rval, yden.get_unsigned());
|
||||
auto xyn = power(xval, ynum.get_unsigned());
|
||||
if (ryd == xyn)
|
||||
return l_true;
|
||||
#if 0
|
||||
// try some root approximation instead?
|
||||
if (ryd > xyn) {
|
||||
// todo
|
||||
}
|
||||
if (ryd < xyn) {
|
||||
// todo
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
return l_undef;
|
||||
|
||||
// anum isn't initialized unless nra_solver is invoked.
|
||||
// there is no proviso for using algebraic numbers outside of the nra solver.
|
||||
// so either we have a rational refinement version _and_ an algebraic numeral refinement
|
||||
// loop or we introduce algebraic numerals outside of the nra_solver
|
||||
|
||||
#if 0
|
||||
scoped_anum xval(am()), yval(am()), rval(am());
|
||||
|
||||
am().set(xval, am_value(x));
|
||||
am().set(yval, am_value(y));
|
||||
am().set(rval, am_value(r));
|
||||
#endif
|
||||
|
||||
return m_core->check_power(r, x, y, lemmas);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue