mirror of
https://github.com/Z3Prover/z3
synced 2025-08-09 04:31:24 +00:00
wip based on notes
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
ab9a9d2308
commit
10589d59ba
2 changed files with 99 additions and 17 deletions
|
@ -1498,6 +1498,84 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
rational saturation::round(rational const& N, rational const& x) {
|
||||||
|
SASSERT(0 <= x && x < N);
|
||||||
|
if (x + N/2 > N)
|
||||||
|
return x - N;
|
||||||
|
else
|
||||||
|
return x;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool saturation::extract_linear_form(pdd const& q, pvar& y, rational& a, rational& b) {
|
||||||
|
auto & m = q.manager();
|
||||||
|
auto N = m.two_to_N();
|
||||||
|
|
||||||
|
if (q.is_val()) {
|
||||||
|
a = 0;
|
||||||
|
b = round(N, q.val());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
y = q.var();
|
||||||
|
if (!q.lo().is_val())
|
||||||
|
return false;
|
||||||
|
if (!q.hi().is_val())
|
||||||
|
return false;
|
||||||
|
a = round(N, q.hi().val());
|
||||||
|
b = round(N, q.lo().val());
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* write as p := a*x*y + b*x + c*y + d
|
||||||
|
*/
|
||||||
|
bool saturation::extract_bilinear_form(pvar x, pdd const& p, pvar& y, rational& a, rational& b, rational& c, rational& d) {
|
||||||
|
auto & m = s.var2pdd(x);
|
||||||
|
auto N = m.two_to_N();
|
||||||
|
auto eval_round = [&](pdd const& p, rational& r) {
|
||||||
|
if (!s.try_eval(p, r))
|
||||||
|
return false;
|
||||||
|
r = round(N, r);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
switch (p.degree(x)) {
|
||||||
|
case 0:
|
||||||
|
if (!s.try_eval(p, d))
|
||||||
|
return false;
|
||||||
|
a = b = c = 0;
|
||||||
|
return true;
|
||||||
|
case 1: {
|
||||||
|
pdd q = p, r = p, u = p, v = p;
|
||||||
|
p.factor(x, 1, q, r);
|
||||||
|
if (!extract_linear_form(q, y, a, b))
|
||||||
|
return false;
|
||||||
|
if (a == 0) {
|
||||||
|
c = 0;
|
||||||
|
return eval_round(r, d);
|
||||||
|
}
|
||||||
|
SASSERT(y != null_var);
|
||||||
|
switch (r.degree(y)) {
|
||||||
|
case 0:
|
||||||
|
if (!eval_round(r, d))
|
||||||
|
return false;
|
||||||
|
c = 0;
|
||||||
|
return true;
|
||||||
|
case 1:
|
||||||
|
r.factor(y, 1, u, v);
|
||||||
|
if (!eval_round(u, c))
|
||||||
|
return false;
|
||||||
|
if (!eval_round(v, d))
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool saturation::get_bound(pvar x, rational const& bound_x, pdd const& p, rational& bound_p) {
|
bool saturation::get_bound(pvar x, rational const& bound_x, pdd const& p, rational& bound_p) {
|
||||||
if (p.degree(x) == 0)
|
if (p.degree(x) == 0)
|
||||||
return s.try_eval(p, bound_p);
|
return s.try_eval(p, bound_p);
|
||||||
|
@ -1535,32 +1613,30 @@ namespace polysat {
|
||||||
x_max = hi;
|
x_max = hi;
|
||||||
SASSERT(x_min != x_max);
|
SASSERT(x_min != x_max);
|
||||||
if (x_min > x_max)
|
if (x_min > x_max)
|
||||||
x_min += m.two_to_N();
|
x_min -= m.two_to_N();
|
||||||
SASSERT(x_min <= x_max);
|
SASSERT(x_min <= x_max);
|
||||||
|
|
||||||
if (x_max == 0) {
|
if (x_max == 0) {
|
||||||
SASSERT(x_min == 0);
|
SASSERT(x_min == 0);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto isolate_y = [&](pvar x, pdd const& p, pdd& y, pdd& b) {
|
pvar y1 = null_var, y2 = null_var, y;
|
||||||
if (p.degree(x) != 1)
|
rational a1, a2, b1, b2, c1, c2, d1, d2;
|
||||||
return false;
|
if (!extract_bilinear_form(x, p, y1, a1, b1, c1, d1))
|
||||||
p.factor(x, 1, y, b);
|
|
||||||
return !y.is_val();
|
|
||||||
};
|
|
||||||
pdd y = p, b = p;
|
|
||||||
rational b_val, y_val;
|
|
||||||
// handle just one-side with x for now
|
|
||||||
if (p.degree(x) == 1 && q.degree(x) == 1)
|
|
||||||
return false;
|
return false;
|
||||||
if (!isolate_y(x, p, y, b) && !isolate_y(x, q, y, b))
|
if (!extract_bilinear_form(x, q, y2, a2, b2, c2, d2))
|
||||||
return false;
|
return false;
|
||||||
if (!s.try_eval(b, b_val))
|
if (y1 != null_var && y2 != null_var && y1 != y2)
|
||||||
return false;
|
return false;
|
||||||
if (!s.try_eval(y, y_val))
|
if (y1 == null_var && y2 == null_var)
|
||||||
return false;
|
return false;
|
||||||
// at this point p = x*y + b or q = x*y + b
|
y = (y1 == null_var) ? y2 : y1;
|
||||||
|
|
||||||
|
verbose_stream() << p << " v" << y << " " << a1 << " " << b1 << " " << c1 << " " << d1 << "\n";
|
||||||
|
verbose_stream() << q << " v" << y << " " << a2 << " " << b2 << " " << c2 << " " << d2 << "\n";
|
||||||
|
|
||||||
|
#if 0
|
||||||
auto is_bounded = [&](pdd& p, rational& lo, rational& hi) {
|
auto is_bounded = [&](pdd& p, rational& lo, rational& hi) {
|
||||||
verbose_stream() << "is-bounded " << p << "\n";
|
verbose_stream() << "is-bounded " << p << "\n";
|
||||||
if (!get_bound(x, x_min, p, lo))
|
if (!get_bound(x, x_min, p, lo))
|
||||||
|
@ -1614,6 +1690,8 @@ namespace polysat {
|
||||||
verbose_stream() << b << " " << b_val << " max-y " << max_y << "\n";
|
verbose_stream() << b << " " << b_val << " max-y " << max_y << "\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -65,6 +65,10 @@ namespace polysat {
|
||||||
bool try_add_mul_bound(pvar x, conflict& core, inequality const& axb_l_y);
|
bool try_add_mul_bound(pvar x, conflict& core, inequality const& axb_l_y);
|
||||||
bool try_add_mul_bound2(pvar x, conflict& core, inequality const& axb_l_y);
|
bool try_add_mul_bound2(pvar x, conflict& core, inequality const& axb_l_y);
|
||||||
|
|
||||||
|
rational round(rational const& N, rational const& x);
|
||||||
|
bool extract_linear_form(pdd const& q, pvar& y, rational& a, rational& b);
|
||||||
|
bool extract_bilinear_form(pvar x, pdd const& p, pvar& y, rational& a, rational& b, rational& c, rational& d);
|
||||||
|
|
||||||
bool get_bound(pvar x, rational const& bound_x, pdd const& p, rational& bound_p);
|
bool get_bound(pvar x, rational const& bound_x, pdd const& p, rational& bound_p);
|
||||||
|
|
||||||
// c := lhs ~ v
|
// c := lhs ~ v
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue