mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
moving remaining qsat functionality over
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
296addf246
commit
20bbdfe31a
23 changed files with 3876 additions and 225 deletions
|
@ -18,10 +18,12 @@ Revision History:
|
|||
|
||||
--*/
|
||||
#include"nlsat_evaluator.h"
|
||||
#include"nlsat_solver.h"
|
||||
|
||||
namespace nlsat {
|
||||
|
||||
struct evaluator::imp {
|
||||
solver& m_solver;
|
||||
assignment const & m_assignment;
|
||||
pmanager & m_pm;
|
||||
small_object_allocator & m_allocator;
|
||||
|
@ -357,7 +359,8 @@ namespace nlsat {
|
|||
|
||||
sign_table m_sign_table_tmp;
|
||||
|
||||
imp(assignment const & x2v, pmanager & pm, small_object_allocator & allocator):
|
||||
imp(solver& s, assignment const & x2v, pmanager & pm, small_object_allocator & allocator):
|
||||
m_solver(s),
|
||||
m_assignment(x2v),
|
||||
m_pm(pm),
|
||||
m_allocator(allocator),
|
||||
|
@ -420,10 +423,25 @@ namespace nlsat {
|
|||
scoped_anum_vector & roots = m_tmp_values;
|
||||
roots.reset();
|
||||
m_am.isolate_roots(polynomial_ref(a->p(), m_pm), undef_var_assignment(m_assignment, a->x()), roots);
|
||||
TRACE("nlsat",
|
||||
m_solver.display(tout << (neg?"!":""), *a); tout << "\n";
|
||||
if (roots.empty()) {
|
||||
tout << "No roots\n";
|
||||
}
|
||||
else {
|
||||
tout << "Roots for ";
|
||||
for (unsigned i = 0; i < roots.size(); ++i) {
|
||||
m_am.display_interval(tout, roots[i]); tout << " ";
|
||||
}
|
||||
tout << "\n";
|
||||
}
|
||||
m_assignment.display(tout);
|
||||
);
|
||||
SASSERT(a->i() > 0);
|
||||
if (a->i() > roots.size())
|
||||
return false; // p does have sufficient roots
|
||||
int sign = m_am.compare(m_assignment.value(a->x()), roots[a->i() - 1]);
|
||||
if (a->i() > roots.size()) {
|
||||
return neg;
|
||||
}
|
||||
int sign = m_am.compare(m_assignment.value(a->x()), roots[a->i() - 1]);
|
||||
return satisfied(sign, k, neg);
|
||||
}
|
||||
|
||||
|
@ -649,8 +667,8 @@ namespace nlsat {
|
|||
}
|
||||
};
|
||||
|
||||
evaluator::evaluator(assignment const & x2v, pmanager & pm, small_object_allocator & allocator) {
|
||||
m_imp = alloc(imp, x2v, pm, allocator);
|
||||
evaluator::evaluator(solver& s, assignment const & x2v, pmanager & pm, small_object_allocator & allocator) {
|
||||
m_imp = alloc(imp, s, x2v, pm, allocator);
|
||||
}
|
||||
|
||||
evaluator::~evaluator() {
|
||||
|
|
|
@ -26,11 +26,13 @@ Revision History:
|
|||
|
||||
namespace nlsat {
|
||||
|
||||
class solver;
|
||||
|
||||
class evaluator {
|
||||
struct imp;
|
||||
imp * m_imp;
|
||||
public:
|
||||
evaluator(assignment const & x2v, pmanager & pm, small_object_allocator & allocator);
|
||||
evaluator(solver& s, assignment const & x2v, pmanager & pm, small_object_allocator & allocator);
|
||||
~evaluator();
|
||||
|
||||
interval_set_manager & ism() const;
|
||||
|
|
|
@ -36,6 +36,7 @@ namespace nlsat {
|
|||
polynomial::cache & m_cache;
|
||||
pmanager & m_pm;
|
||||
polynomial_ref_vector m_ps;
|
||||
polynomial_ref_vector m_ps2;
|
||||
polynomial_ref_vector m_psc_tmp;
|
||||
polynomial_ref_vector m_factors;
|
||||
scoped_anum_vector m_roots_tmp;
|
||||
|
@ -43,6 +44,7 @@ namespace nlsat {
|
|||
bool m_full_dimensional;
|
||||
bool m_minimize_cores;
|
||||
bool m_factor;
|
||||
bool m_signed_project;
|
||||
|
||||
struct todo_set {
|
||||
polynomial::cache & m_cache;
|
||||
|
@ -137,6 +139,7 @@ namespace nlsat {
|
|||
m_cache(u),
|
||||
m_pm(u.pm()),
|
||||
m_ps(m_pm),
|
||||
m_ps2(m_pm),
|
||||
m_psc_tmp(m_pm),
|
||||
m_factors(m_pm),
|
||||
m_roots_tmp(m_am),
|
||||
|
@ -148,6 +151,7 @@ namespace nlsat {
|
|||
m_simplify_cores = false;
|
||||
m_full_dimensional = false;
|
||||
m_minimize_cores = false;
|
||||
m_signed_project = false;
|
||||
}
|
||||
|
||||
~imp() {
|
||||
|
@ -202,7 +206,7 @@ namespace nlsat {
|
|||
void reset_already_added() {
|
||||
SASSERT(m_result != 0);
|
||||
unsigned sz = m_result->size();
|
||||
for (unsigned i = 0; i < sz; i++)
|
||||
for (unsigned i = 0; i < sz; i++)
|
||||
m_already_added_literal[(*m_result)[i].index()] = false;
|
||||
}
|
||||
|
||||
|
@ -212,7 +216,7 @@ namespace nlsat {
|
|||
max_var(p) must be assigned in the current interpretation.
|
||||
*/
|
||||
int sign(polynomial_ref const & p) {
|
||||
TRACE("nlsat_explain", tout << "p: " << p << "\n";);
|
||||
TRACE("nlsat_explain", tout << "p: " << p << " var: " << max_var(p) << "\n";);
|
||||
SASSERT(max_var(p) == null_var || m_assignment.is_assigned(max_var(p)));
|
||||
return m_am.eval_sign_at(p, m_assignment);
|
||||
}
|
||||
|
@ -697,39 +701,163 @@ namespace nlsat {
|
|||
}
|
||||
}
|
||||
|
||||
void test_root_literal(atom::kind k, var y, unsigned i, poly * p, scoped_literal_vector& result) {
|
||||
m_result = &result;
|
||||
add_root_literal(k, y, i, p);
|
||||
reset_already_added();
|
||||
m_result = 0;
|
||||
}
|
||||
|
||||
void add_root_literal(atom::kind k, var y, unsigned i, poly * p) {
|
||||
polynomial_ref pr(p, m_pm);
|
||||
TRACE("nlsat_explain",
|
||||
display(tout << "x" << y << " " << k << "[" << i << "](", pr); tout << ")\n";);
|
||||
|
||||
if (!mk_linear_root(k, y, i, p) &&
|
||||
//!mk_plinear_root(k, y, i, p) &&
|
||||
!mk_quadratic_root(k, y, i, p)&&
|
||||
true) {
|
||||
bool_var b = m_solver.mk_root_atom(k, y, i, p);
|
||||
literal l(b, true);
|
||||
TRACE("nlsat_explain", tout << "adding literal\n"; display(tout, l); tout << "\n";);
|
||||
add_literal(l);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* literal can be expressed using a linear ineq_atom
|
||||
*/
|
||||
bool mk_linear_root(atom::kind k, var y, unsigned i, poly * p) {
|
||||
scoped_mpz c(m_pm.m());
|
||||
bool_var b;
|
||||
bool lsign = false;
|
||||
if (m_pm.degree(p, y) == 1 && m_pm.const_coeff(p, y, 1, c)) {
|
||||
SASSERT(!m_pm.m().is_zero(c));
|
||||
// literal can be expressed using a linear ineq_atom
|
||||
polynomial_ref p_prime(m_pm);
|
||||
p_prime = p;
|
||||
if (m_pm.m().is_neg(c))
|
||||
p_prime = neg(p_prime);
|
||||
p = p_prime.get();
|
||||
switch (k) {
|
||||
case atom::ROOT_EQ: k = atom::EQ; lsign = false; break;
|
||||
case atom::ROOT_LT: k = atom::LT; lsign = false; break;
|
||||
case atom::ROOT_GT: k = atom::GT; lsign = false; break;
|
||||
case atom::ROOT_LE: k = atom::GT; lsign = true; break;
|
||||
case atom::ROOT_GE: k = atom::LT; lsign = true; break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
bool is_even = false;
|
||||
b = m_solver.mk_ineq_atom(k, 1, &p, &is_even);
|
||||
mk_linear_root(k, y, i, p, m_pm.m().is_neg(c));
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
b = m_solver.mk_root_atom(k, y, i, p);
|
||||
lsign = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Create pseudo-linear root depending on the sign of the coefficient to y.
|
||||
*/
|
||||
bool mk_plinear_root(atom::kind k, var y, unsigned i, poly * p) {
|
||||
if (m_pm.degree(p, y) != 1) {
|
||||
return false;
|
||||
}
|
||||
lsign = !lsign; // adding as an assumption
|
||||
literal l(b, lsign);
|
||||
TRACE("nlsat_explain", tout << "adding literal\n"; display(tout, l); tout << "\n";);
|
||||
add_literal(l);
|
||||
polynomial_ref c(m_pm);
|
||||
c = m_pm.coeff(p, y, 1);
|
||||
int s = sign(c);
|
||||
if (s == 0) {
|
||||
return false;
|
||||
}
|
||||
ensure_sign(c);
|
||||
mk_linear_root(k, y, i, p, s < 0);
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
Encode root conditions for quadratic polynomials.
|
||||
|
||||
Basically implements Thom's theorem. The roots are characterized by the sign of polynomials and their derivatives.
|
||||
|
||||
b^2 - 4ac = 0:
|
||||
- there is only one root, which is -b/2a.
|
||||
- relation to root is a function of the sign of
|
||||
- 2ax + b
|
||||
b^2 - 4ac > 0:
|
||||
- assert i == 1 or i == 2
|
||||
- relation to root is a function of the signs of:
|
||||
- 2ax + b
|
||||
- ax^2 + bx + c
|
||||
*/
|
||||
|
||||
bool mk_quadratic_root(atom::kind k, var y, unsigned i, poly * p) {
|
||||
if (m_pm.degree(p, y) != 2) {
|
||||
return false;
|
||||
}
|
||||
if (i != 1 && i != 2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SASSERT(m_assignment.is_assigned(y));
|
||||
polynomial_ref A(m_pm), B(m_pm), C(m_pm), q(m_pm), p_diff(m_pm), yy(m_pm);
|
||||
A = m_pm.coeff(p, y, 2);
|
||||
B = m_pm.coeff(p, y, 1);
|
||||
C = m_pm.coeff(p, y, 0);
|
||||
// TBD throttle based on degree of q?
|
||||
q = (B*B) - (4*A*C);
|
||||
yy = m_pm.mk_polynomial(y);
|
||||
p_diff = 2*A*yy + B;
|
||||
p_diff = m_pm.normalize(p_diff);
|
||||
int sq = ensure_sign(q);
|
||||
if (sq < 0) {
|
||||
return false;
|
||||
}
|
||||
int sa = ensure_sign(A);
|
||||
if (sa == 0) {
|
||||
q = B*yy + C;
|
||||
return mk_plinear_root(k, y, i, q);
|
||||
}
|
||||
ensure_sign(p_diff);
|
||||
if (sq > 0) {
|
||||
polynomial_ref pr(p, m_pm);
|
||||
ensure_sign(pr);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int ensure_sign(polynomial_ref & p) {
|
||||
#if 0
|
||||
polynomial_ref f(m_pm);
|
||||
factor(p, m_factors);
|
||||
m_is_even.reset();
|
||||
unsigned num_factors = m_factors.size();
|
||||
int s = 1;
|
||||
for (unsigned i = 0; i < num_factors; i++) {
|
||||
f = m_factors.get(i);
|
||||
s *= sign(f);
|
||||
m_is_even.push_back(false);
|
||||
}
|
||||
if (num_factors > 0) {
|
||||
atom::kind k = atom::EQ;
|
||||
if (s == 0) k = atom::EQ;
|
||||
if (s < 0) k = atom::LT;
|
||||
if (s > 0) k = atom::GT;
|
||||
bool_var b = m_solver.mk_ineq_atom(k, num_factors, m_factors.c_ptr(), m_is_even.c_ptr());
|
||||
add_literal(literal(b, true));
|
||||
}
|
||||
return s;
|
||||
#else
|
||||
int s = sign(p);
|
||||
if (!is_const(p)) {
|
||||
add_simple_assumption(s == 0 ? atom::EQ : (s < 0 ? atom::LT : atom::GT), p);
|
||||
}
|
||||
return s;
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
Auxiliary function to linear roots.
|
||||
*/
|
||||
void mk_linear_root(atom::kind k, var y, unsigned i, poly * p, bool mk_neg) {
|
||||
polynomial_ref p_prime(m_pm);
|
||||
p_prime = p;
|
||||
bool lsign = false;
|
||||
if (mk_neg)
|
||||
p_prime = neg(p_prime);
|
||||
p = p_prime.get();
|
||||
switch (k) {
|
||||
case atom::ROOT_EQ: k = atom::EQ; lsign = false; break;
|
||||
case atom::ROOT_LT: k = atom::LT; lsign = false; break;
|
||||
case atom::ROOT_GT: k = atom::GT; lsign = false; break;
|
||||
case atom::ROOT_LE: k = atom::GT; lsign = true; break;
|
||||
case atom::ROOT_GE: k = atom::LT; lsign = true; break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
add_simple_assumption(k, p, lsign);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1332,10 +1460,333 @@ namespace nlsat {
|
|||
TRACE("nlsat_explain", tout << "[explain] result\n"; display(tout, result););
|
||||
CASSERT("nlsat", check_already_added());
|
||||
}
|
||||
|
||||
|
||||
void project(var x, unsigned num, literal const * ls, scoped_literal_vector & result) {
|
||||
m_result = &result;
|
||||
svector<literal> lits;
|
||||
TRACE("nlsat", tout << "project x" << x << "\n"; m_solver.display(tout););
|
||||
|
||||
DEBUG_CODE(
|
||||
for (unsigned i = 0; i < num; ++i) {
|
||||
SASSERT(m_solver.value(ls[i]) == l_true);
|
||||
atom* a = m_atoms[ls[i].var()];
|
||||
SASSERT(!a || m_evaluator.eval(a, ls[i].sign()));
|
||||
});
|
||||
split_literals(x, num, ls, lits);
|
||||
collect_polys(lits.size(), lits.c_ptr(), m_ps);
|
||||
var mx_var = max_var(m_ps);
|
||||
if (!m_ps.empty()) {
|
||||
svector<var> renaming;
|
||||
if (x != mx_var) {
|
||||
for (var i = 0; i < m_solver.num_vars(); ++i) {
|
||||
renaming.push_back(i);
|
||||
}
|
||||
std::swap(renaming[x], renaming[mx_var]);
|
||||
m_solver.reorder(renaming.size(), renaming.c_ptr());
|
||||
TRACE("qe", tout << "x: " << x << " max: " << mx_var << " num_vars: " << m_solver.num_vars() << "\n";
|
||||
m_solver.display(tout););
|
||||
}
|
||||
elim_vanishing(m_ps);
|
||||
if (m_signed_project) {
|
||||
signed_project(m_ps, mx_var);
|
||||
}
|
||||
else {
|
||||
project(m_ps, mx_var);
|
||||
}
|
||||
reset_already_added();
|
||||
m_result = 0;
|
||||
if (x != mx_var) {
|
||||
m_solver.restore_order();
|
||||
}
|
||||
}
|
||||
else {
|
||||
reset_already_added();
|
||||
m_result = 0;
|
||||
}
|
||||
for (unsigned i = 0; i < result.size(); ++i) {
|
||||
result.set(i, ~result[i]);
|
||||
}
|
||||
DEBUG_CODE(
|
||||
for (unsigned i = 0; i < result.size(); ++i) {
|
||||
SASSERT(l_true == m_solver.value(result[i]));
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
void split_literals(var x, unsigned n, literal const* ls, svector<literal>& lits) {
|
||||
var_vector vs;
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
vs.reset();
|
||||
m_solver.vars(ls[i], vs);
|
||||
if (vs.contains(x)) {
|
||||
lits.push_back(ls[i]);
|
||||
}
|
||||
else {
|
||||
add_literal(~ls[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Signed projection.
|
||||
|
||||
Assumptions:
|
||||
- any variable in ps is at most x.
|
||||
- root expressions are satisfied (positive literals)
|
||||
|
||||
Effect:
|
||||
- if x not in p, then
|
||||
- if sign(p) < 0: p < 0
|
||||
- if sign(p) = 0: p = 0
|
||||
- if sign(p) > 0: p > 0
|
||||
else:
|
||||
- let roots_j be the roots of p_j or roots_j[i]
|
||||
- let L = { roots_j[i] | M(roots_j[i]) < M(x) }
|
||||
- let U = { roots_j[i] | M(roots_j[i]) > M(x) }
|
||||
- let E = { roots_j[i] | M(roots_j[i]) = M(x) }
|
||||
- let glb in L, s.t. forall l in L . M(glb) >= M(l)
|
||||
- let lub in U, s.t. forall u in U . M(lub) <= M(u)
|
||||
- if root in E, then
|
||||
- add E x . x = root & x > lb for lb in L
|
||||
- add E x . x = root & x < ub for ub in U
|
||||
- add E x . x = root & x = root2 for root2 in E \ { root }
|
||||
- else
|
||||
- assume |L| <= |U| (other case is symmetric)
|
||||
- add E x . lb <= x & x <= glb for lb in L
|
||||
- add E x . x = glb & x < ub for ub in U
|
||||
*/
|
||||
|
||||
|
||||
void signed_project(polynomial_ref_vector& ps, var x) {
|
||||
|
||||
TRACE("nlsat_explain", tout << "Signed projection\n";);
|
||||
polynomial_ref p(m_pm);
|
||||
unsigned eq_index = 0;
|
||||
bool eq_valid = false;
|
||||
unsigned eq_degree = 0;
|
||||
for (unsigned i = 0; i < ps.size(); ++i) {
|
||||
p = ps.get(i);
|
||||
int s = sign(p);
|
||||
if (max_var(p) != x) {
|
||||
atom::kind k = (s == 0)?(atom::EQ):((s < 0)?(atom::LT):(atom::GT));
|
||||
add_simple_assumption(k, p, false);
|
||||
ps[i] = ps.back();
|
||||
ps.pop_back();
|
||||
--i;
|
||||
}
|
||||
else if (s == 0) {
|
||||
if (!eq_valid || degree(p, x) < eq_degree) {
|
||||
eq_index = i;
|
||||
eq_valid = true;
|
||||
eq_degree = degree(p, x);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (ps.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (ps.size() == 1) {
|
||||
project_single(x, ps.get(0));
|
||||
return;
|
||||
}
|
||||
|
||||
// ax + b = 0, p(x) > 0 ->
|
||||
|
||||
if (eq_valid) {
|
||||
p = ps.get(eq_index);
|
||||
if (degree(p, x) == 1) {
|
||||
// ax + b = 0
|
||||
// let d be maximal degree of x in p.
|
||||
// p(x) -> a^d*p(-b/a), a
|
||||
// perform virtual substitution with equality.
|
||||
solve_eq(x, eq_index, ps);
|
||||
}
|
||||
else {
|
||||
project_pairs(x, eq_index, ps);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned num_lub = 0, num_glb = 0;
|
||||
unsigned glb_index = 0, lub_index = 0;
|
||||
scoped_anum lub(m_am), glb(m_am), x_val(m_am);
|
||||
x_val = m_assignment.value(x);
|
||||
for (unsigned i = 0; i < ps.size(); ++i) {
|
||||
p = ps.get(i);
|
||||
scoped_anum_vector & roots = m_roots_tmp;
|
||||
roots.reset();
|
||||
m_am.isolate_roots(p, undef_var_assignment(m_assignment, x), roots);
|
||||
bool glb_valid = false, lub_valid = false;
|
||||
for (unsigned j = 0; j < roots.size(); ++j) {
|
||||
int s = m_am.compare(x_val, roots[j]);
|
||||
SASSERT(s != 0);
|
||||
lub_valid |= s < 0;
|
||||
glb_valid |= s > 0;
|
||||
|
||||
if (s < 0 && m_am.lt(roots[j], lub)) {
|
||||
lub_index = i;
|
||||
m_am.set(lub, roots[j]);
|
||||
}
|
||||
|
||||
if (s > 0 && m_am.lt(glb, roots[j])) {
|
||||
glb_index = i;
|
||||
m_am.set(glb, roots[j]);
|
||||
}
|
||||
}
|
||||
if (glb_valid) {
|
||||
++num_glb;
|
||||
}
|
||||
if (lub_valid) {
|
||||
++num_lub;
|
||||
}
|
||||
}
|
||||
|
||||
if (num_lub == 0) {
|
||||
project_plus_infinity(x, ps);
|
||||
return;
|
||||
}
|
||||
|
||||
if (num_glb == 0) {
|
||||
project_minus_infinity(x, ps);
|
||||
return;
|
||||
}
|
||||
|
||||
if (num_lub <= num_glb) {
|
||||
glb_index = lub_index;
|
||||
}
|
||||
|
||||
project_pairs(x, glb_index, ps);
|
||||
}
|
||||
|
||||
void project_plus_infinity(var x, polynomial_ref_vector const& ps) {
|
||||
polynomial_ref p(m_pm), lc(m_pm);
|
||||
for (unsigned i = 0; i < ps.size(); ++i) {
|
||||
p = ps.get(i);
|
||||
unsigned d = degree(p, x);
|
||||
lc = m_pm.coeff(p, x, d);
|
||||
if (!is_const(lc)) {
|
||||
unsigned s = sign(p);
|
||||
SASSERT(s != 0);
|
||||
atom::kind k = (s > 0)?(atom::GT):(atom::LT);
|
||||
add_simple_assumption(k, lc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void project_minus_infinity(var x, polynomial_ref_vector const& ps) {
|
||||
polynomial_ref p(m_pm), lc(m_pm);
|
||||
for (unsigned i = 0; i < ps.size(); ++i) {
|
||||
p = ps.get(i);
|
||||
unsigned d = degree(p, x);
|
||||
lc = m_pm.coeff(p, x, d);
|
||||
if (!is_const(lc)) {
|
||||
unsigned s = sign(p);
|
||||
SASSERT(s != 0);
|
||||
atom::kind k;
|
||||
if (s > 0) {
|
||||
k = (d % 2 == 0)?(atom::GT):(atom::LT);
|
||||
}
|
||||
else {
|
||||
k = (d % 2 == 0)?(atom::LT):(atom::GT);
|
||||
}
|
||||
add_simple_assumption(k, lc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void project_pairs(var x, unsigned idx, polynomial_ref_vector const& ps) {
|
||||
polynomial_ref p(m_pm);
|
||||
p = ps.get(idx);
|
||||
for (unsigned i = 0; i < ps.size(); ++i) {
|
||||
if (i != idx) {
|
||||
project_pair(x, ps.get(i), p);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void project_pair(var x, polynomial::polynomial* p1, polynomial::polynomial* p2) {
|
||||
m_ps2.reset();
|
||||
m_ps2.push_back(p1);
|
||||
m_ps2.push_back(p2);
|
||||
project(m_ps2, x);
|
||||
}
|
||||
|
||||
void project_single(var x, polynomial::polynomial* p) {
|
||||
m_ps2.reset();
|
||||
m_ps2.push_back(p);
|
||||
project(m_ps2, x);
|
||||
}
|
||||
|
||||
void solve_eq(var x, unsigned idx, polynomial_ref_vector const& ps) {
|
||||
polynomial_ref p(m_pm), A(m_pm), B(m_pm), C(m_pm), D(m_pm), E(m_pm), q(m_pm), r(m_pm);
|
||||
polynomial_ref_vector qs(m_pm);
|
||||
p = ps.get(idx);
|
||||
SASSERT(degree(p, x) == 1);
|
||||
A = m_pm.coeff(p, x, 1);
|
||||
B = m_pm.coeff(p, x, 0);
|
||||
B = neg(B);
|
||||
TRACE("nlsat_explain", tout << "p: " << p << " A: " << A << " B: " << B << "\n";);
|
||||
// x = B/A
|
||||
for (unsigned i = 0; i < ps.size(); ++i) {
|
||||
if (i != idx) {
|
||||
q = ps.get(i);
|
||||
unsigned d = degree(q, x);
|
||||
D = m_pm.mk_const(rational(1));
|
||||
E = D;
|
||||
r = m_pm.mk_zero();
|
||||
for (unsigned j = 0; j <= d; ++j) {
|
||||
qs.push_back(D);
|
||||
D = D*A;
|
||||
}
|
||||
for (unsigned j = 0; j <= d; ++j) {
|
||||
// A^d*p0 + A^{d-1}*B*p1 + ... + B^j*A^{d-j}*pj + ... + B^d*p_d
|
||||
C = m_pm.coeff(q, x, j);
|
||||
if (!is_zero(C)) {
|
||||
D = qs.get(d-j);
|
||||
r = r + D*E*C;
|
||||
}
|
||||
E = E*B;
|
||||
}
|
||||
TRACE("nlsat_explain", tout << "q: " << q << " r: " << r << "\n";);
|
||||
ensure_sign(r);
|
||||
}
|
||||
else {
|
||||
ensure_sign(A);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void maximize(var x, unsigned num, literal const * ls, scoped_anum& val, bool& unbounded) {
|
||||
svector<literal> lits;
|
||||
polynomial_ref p(m_pm);
|
||||
split_literals(x, num, ls, lits);
|
||||
collect_polys(lits.size(), lits.c_ptr(), m_ps);
|
||||
unbounded = true;
|
||||
scoped_anum x_val(m_am);
|
||||
x_val = m_assignment.value(x);
|
||||
for (unsigned i = 0; i < m_ps.size(); ++i) {
|
||||
p = m_ps.get(i);
|
||||
scoped_anum_vector & roots = m_roots_tmp;
|
||||
roots.reset();
|
||||
m_am.isolate_roots(p, undef_var_assignment(m_assignment, x), roots);
|
||||
for (unsigned j = 0; j < roots.size(); ++j) {
|
||||
int s = m_am.compare(x_val, roots[j]);
|
||||
if (s <= 0 && (unbounded || m_am.compare(roots[j], val) <= 0)) {
|
||||
unbounded = false;
|
||||
val = roots[j];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
explain::explain(solver & s, assignment const & x2v, polynomial::cache & u, atom_vector const & atoms, atom_vector const & x2eq,
|
||||
evaluator & ev) {
|
||||
explain::explain(solver & s, assignment const & x2v, polynomial::cache & u,
|
||||
atom_vector const& atoms, atom_vector const& x2eq, evaluator & ev) {
|
||||
m_imp = alloc(imp, s, x2v, u, atoms, x2eq, ev);
|
||||
}
|
||||
|
||||
|
@ -1364,10 +1815,26 @@ namespace nlsat {
|
|||
m_imp->m_factor = f;
|
||||
}
|
||||
|
||||
void explain::set_signed_project(bool f) {
|
||||
m_imp->m_signed_project = f;
|
||||
}
|
||||
|
||||
void explain::operator()(unsigned n, literal const * ls, scoped_literal_vector & result) {
|
||||
(*m_imp)(n, ls, result);
|
||||
}
|
||||
|
||||
void explain::project(var x, unsigned n, literal const * ls, scoped_literal_vector & result) {
|
||||
m_imp->project(x, n, ls, result);
|
||||
}
|
||||
|
||||
void explain::maximize(var x, unsigned n, literal const * ls, scoped_anum& val, bool& unbounded) {
|
||||
m_imp->maximize(x, n, ls, val, unbounded);
|
||||
}
|
||||
|
||||
void explain::test_root_literal(atom::kind k, var y, unsigned i, poly* p, scoped_literal_vector & result) {
|
||||
m_imp->test_root_literal(k, y, i, p, result);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#ifdef Z3DEBUG
|
||||
|
@ -1398,3 +1865,4 @@ void pp_lit(nlsat::explain::imp & ex, nlsat::literal l) {
|
|||
std::cout << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
|
@ -22,9 +22,11 @@ Revision History:
|
|||
#include"nlsat_solver.h"
|
||||
#include"nlsat_scoped_literal_vector.h"
|
||||
#include"polynomial_cache.h"
|
||||
#include"algebraic_numbers.h"
|
||||
|
||||
namespace nlsat {
|
||||
class evaluator;
|
||||
|
||||
|
||||
class explain {
|
||||
public:
|
||||
|
@ -32,8 +34,8 @@ namespace nlsat {
|
|||
private:
|
||||
imp * m_imp;
|
||||
public:
|
||||
explain(solver & s, assignment const & x2v, polynomial::cache & u, atom_vector const & atoms, atom_vector const & x2eq,
|
||||
evaluator & ev);
|
||||
explain(solver & s, assignment const & x2v, polynomial::cache & u,
|
||||
atom_vector const& atoms, atom_vector const& x2eq, evaluator & ev);
|
||||
~explain();
|
||||
|
||||
void reset();
|
||||
|
@ -41,6 +43,7 @@ namespace nlsat {
|
|||
void set_full_dimensional(bool f);
|
||||
void set_minimize_cores(bool f);
|
||||
void set_factor(bool f);
|
||||
void set_signed_project(bool f);
|
||||
|
||||
/**
|
||||
\brief Given a set of literals ls[0], ... ls[n-1] s.t.
|
||||
|
@ -60,6 +63,48 @@ namespace nlsat {
|
|||
- s_1, ..., s_m are false in the current interpretation
|
||||
*/
|
||||
void operator()(unsigned n, literal const * ls, scoped_literal_vector & result);
|
||||
|
||||
|
||||
/**
|
||||
\brief projection for a given variable.
|
||||
|
||||
Given: M |= l1[x] /\ ... /\ ln[x]
|
||||
|
||||
Find: M |= s1, ..., sm
|
||||
|
||||
Such that: |= ~s1 \/ ... \/ ~sm \/ E x. l1[x] /\ ... /\ ln[x]
|
||||
|
||||
Contrast this with with the core-based projection above:
|
||||
|
||||
Given: M |= A x . l1[x] \/ ... \/ ln[x]
|
||||
|
||||
Find: M |= ~s1, ..., ~sm.
|
||||
|
||||
Such that: |= s1 \/ ... \/ sm \/ A x . l1[x] \/ ... \/ ln[x]
|
||||
|
||||
Claim: the two compute the same solutions if the projection operators are independent of the value of x.
|
||||
Claim: A complete, convergent projection operator can be obtained from M in a way that is independent of x.
|
||||
|
||||
|
||||
*/
|
||||
void project(var x, unsigned n, literal const * ls, scoped_literal_vector & result);
|
||||
|
||||
/**
|
||||
Maximize the value of x (locally) under the current assignment to other variables and
|
||||
while maintaining the assignment to the literals ls.
|
||||
Set unbounded to 'true' if the value of x is unbounded.
|
||||
|
||||
Precondition: the set of literals are true in the current model.
|
||||
|
||||
By local optimization we understand that x is increased to the largest value within
|
||||
the signs delineated by the roots of the polynomials in ls.
|
||||
*/
|
||||
void maximize(var x, unsigned n, literal const * ls, scoped_anum& val, bool& unbounded);
|
||||
|
||||
/**
|
||||
Unit test routine.
|
||||
*/
|
||||
void test_root_literal(atom::kind k, var y, unsigned i, poly* p, scoped_literal_vector & result);
|
||||
};
|
||||
|
||||
};
|
||||
|
|
|
@ -66,7 +66,6 @@ namespace nlsat {
|
|||
typedef polynomial::cache cache;
|
||||
typedef ptr_vector<interval_set> interval_set_vector;
|
||||
|
||||
solver & m_solver;
|
||||
reslimit& m_rlimit;
|
||||
small_object_allocator m_allocator;
|
||||
unsynch_mpq_manager m_qm;
|
||||
|
@ -159,8 +158,7 @@ namespace nlsat {
|
|||
unsigned m_stages;
|
||||
unsigned m_irrational_assignments; // number of irrational witnesses
|
||||
|
||||
imp(solver & s, reslimit& rlim, params_ref const & p):
|
||||
m_solver(s),
|
||||
imp(solver& s, reslimit& rlim, params_ref const & p):
|
||||
m_rlimit(rlim),
|
||||
m_allocator("nlsat"),
|
||||
m_pm(rlim, m_qm, &m_allocator),
|
||||
|
@ -168,7 +166,7 @@ namespace nlsat {
|
|||
m_am(rlim, m_qm, p, &m_allocator),
|
||||
m_asm(*this, m_allocator),
|
||||
m_assignment(m_am),
|
||||
m_evaluator(m_assignment, m_pm, m_allocator),
|
||||
m_evaluator(s, m_assignment, m_pm, m_allocator),
|
||||
m_ism(m_evaluator.ism()),
|
||||
m_num_bool_vars(0),
|
||||
m_display_var(m_perm),
|
||||
|
@ -183,12 +181,7 @@ namespace nlsat {
|
|||
}
|
||||
|
||||
~imp() {
|
||||
m_explain.reset();
|
||||
m_lemma.reset();
|
||||
m_lazy_clause.reset();
|
||||
undo_until_size(0);
|
||||
del_clauses();
|
||||
del_unref_atoms();
|
||||
reset();
|
||||
}
|
||||
|
||||
void mk_true_bvar() {
|
||||
|
@ -216,6 +209,18 @@ namespace nlsat {
|
|||
m_am.updt_params(p.p);
|
||||
}
|
||||
|
||||
void reset() {
|
||||
m_explain.reset();
|
||||
m_lemma.reset();
|
||||
m_lazy_clause.reset();
|
||||
undo_until_size(0);
|
||||
del_clauses();
|
||||
del_unref_atoms();
|
||||
m_cache.reset();
|
||||
m_assignment.reset();
|
||||
}
|
||||
|
||||
|
||||
void checkpoint() {
|
||||
if (!m_rlimit.inc()) throw solver_exception(m_rlimit.get_cancel_msg());
|
||||
if (memory::get_allocation_size() > m_max_memory) throw solver_exception(Z3_MAX_MEMORY_MSG);
|
||||
|
@ -252,6 +257,7 @@ namespace nlsat {
|
|||
}
|
||||
|
||||
void inc_ref(bool_var b) {
|
||||
TRACE("ref", tout << "inc: " << b << "\n";);
|
||||
if (b == null_bool_var)
|
||||
return;
|
||||
if (m_atoms[b] == 0)
|
||||
|
@ -264,6 +270,7 @@ namespace nlsat {
|
|||
}
|
||||
|
||||
void dec_ref(bool_var b) {
|
||||
TRACE("ref", tout << "dec: " << b << "\n";);
|
||||
if (b == null_bool_var)
|
||||
return;
|
||||
atom * a = m_atoms[b];
|
||||
|
@ -412,6 +419,34 @@ namespace nlsat {
|
|||
return x;
|
||||
}
|
||||
|
||||
svector<bool> m_found_vars;
|
||||
void vars(literal l, var_vector& vs) {
|
||||
vs.reset();
|
||||
atom * a = m_atoms[l.var()];
|
||||
if (a == 0) {
|
||||
|
||||
}
|
||||
else if (a->is_ineq_atom()) {
|
||||
unsigned sz = to_ineq_atom(a)->size();
|
||||
var_vector new_vs;
|
||||
for (unsigned j = 0; j < sz; j++) {
|
||||
m_found_vars.reset();
|
||||
m_pm.vars(to_ineq_atom(a)->p(j), new_vs);
|
||||
for (unsigned i = 0; i < new_vs.size(); ++i) {
|
||||
if (!m_found_vars.get(new_vs[i], false)) {
|
||||
m_found_vars.setx(new_vs[i], true, false);
|
||||
vs.push_back(new_vs[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
m_pm.vars(to_root_atom(a)->p(), vs);
|
||||
//vs.erase(max_var(to_root_atom(a)->p()));
|
||||
vs.push_back(to_root_atom(a)->x());
|
||||
}
|
||||
}
|
||||
|
||||
void deallocate(ineq_atom * a) {
|
||||
unsigned obj_sz = ineq_atom::get_obj_size(a->size());
|
||||
a->~ineq_atom();
|
||||
|
@ -491,6 +526,7 @@ namespace nlsat {
|
|||
TRACE("nlsat_table_bug", ineq_atom::hash_proc h;
|
||||
tout << "mk_ineq_atom hash: " << h(new_atom) << "\n"; display(tout, *new_atom, m_display_var); tout << "\n";);
|
||||
ineq_atom * old_atom = m_ineq_atoms.insert_if_not_there(new_atom);
|
||||
CTRACE("nlsat_table_bug", old_atom->max_var() != max, display(tout, *old_atom, m_display_var); tout << "\n";);
|
||||
SASSERT(old_atom->max_var() == max);
|
||||
if (old_atom != new_atom) {
|
||||
deallocate(new_atom);
|
||||
|
@ -726,7 +762,7 @@ namespace nlsat {
|
|||
|
||||
template<typename Predicate>
|
||||
void undo_until(Predicate const & pred) {
|
||||
while (pred()) {
|
||||
while (pred() && !m_trail.empty()) {
|
||||
trail & t = m_trail.back();
|
||||
switch (t.m_kind) {
|
||||
case trail::BVAR_ASSIGNMENT:
|
||||
|
@ -803,6 +839,14 @@ namespace nlsat {
|
|||
SASSERT(m_bvalues[b] == l_undef);
|
||||
}
|
||||
|
||||
struct true_pred {
|
||||
bool operator()() const { return true; }
|
||||
};
|
||||
|
||||
void undo_until_empty() {
|
||||
undo_until(true_pred());
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Create a new scope level
|
||||
*/
|
||||
|
@ -868,10 +912,11 @@ namespace nlsat {
|
|||
var max = a->max_var();
|
||||
if (!m_assignment.is_assigned(max))
|
||||
return l_undef;
|
||||
TRACE("value_bug", tout << "value of: "; display(tout, l); tout << "\n"; tout << "xk: " << m_xk << ", a->max_var(): " << a->max_var() << "\n";
|
||||
display_assignment(tout);
|
||||
display_bool_assignment(tout););
|
||||
return to_lbool(m_evaluator.eval(a, l.sign()));
|
||||
val = to_lbool(m_evaluator.eval(a, l.sign()));
|
||||
TRACE("value_bug", tout << "value of: "; display(tout, l); tout << " := " << val << "\n";
|
||||
tout << "xk: " << m_xk << ", a->max_var(): " << a->max_var() << "\n";
|
||||
display_assignment(tout););
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -880,8 +925,10 @@ namespace nlsat {
|
|||
bool is_satisfied(clause const & cls) const {
|
||||
unsigned sz = cls.size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
if (const_cast<imp*>(this)->value(cls[i]) == l_true)
|
||||
if (const_cast<imp*>(this)->value(cls[i]) == l_true) {
|
||||
TRACE("value_bug:", tout << cls[i] << " := true\n";);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
@ -984,8 +1031,10 @@ namespace nlsat {
|
|||
If satisfy_learned is true, then learned clauses are satisfied even if m_lazy > 0
|
||||
*/
|
||||
bool process_arith_clause(clause const & cls, bool satisfy_learned) {
|
||||
if (!satisfy_learned && m_lazy >= 2 && cls.is_learned())
|
||||
if (!satisfy_learned && m_lazy >= 2 && cls.is_learned()) {
|
||||
TRACE("nlsat", tout << "skip learned\n";);
|
||||
return true; // ignore lemmas in super lazy mode
|
||||
}
|
||||
SASSERT(m_xk == max_var(cls));
|
||||
unsigned num_undef = 0; // number of undefined literals
|
||||
unsigned first_undef = UINT_MAX; // position of the first undefined literal
|
||||
|
@ -1064,7 +1113,7 @@ namespace nlsat {
|
|||
If satisfy_learned is true, then (arithmetic) learned clauses are satisfied even if m_lazy > 0
|
||||
*/
|
||||
bool process_clause(clause const & cls, bool satisfy_learned) {
|
||||
TRACE("nlsat", tout << "processing clause:\n"; display(tout, cls); tout << "\n";);
|
||||
TRACE("nlsat", tout << "processing clause: "; display(tout, cls); tout << "\n";);
|
||||
if (is_satisfied(cls))
|
||||
return true;
|
||||
if (m_xk == null_var)
|
||||
|
@ -1151,7 +1200,7 @@ namespace nlsat {
|
|||
}
|
||||
TRACE("nlsat_bug", tout << "xk: x" << m_xk << " bk: b" << m_bk << "\n";);
|
||||
if (m_bk == null_bool_var && m_xk >= num_vars()) {
|
||||
TRACE("nlsat", tout << "found model\n"; display_assignment(tout); display_bool_assignment(tout););
|
||||
TRACE("nlsat", tout << "found model\n"; display_assignment(tout););
|
||||
return l_true; // all variables were assigned, and all clauses were satisfied.
|
||||
}
|
||||
TRACE("nlsat", tout << "processing variable ";
|
||||
|
@ -1186,23 +1235,102 @@ namespace nlsat {
|
|||
lbool check() {
|
||||
TRACE("nlsat_smt2", display_smt2(tout););
|
||||
TRACE("nlsat_fd", tout << "is_full_dimensional: " << is_full_dimensional() << "\n";);
|
||||
m_xk = null_var;
|
||||
init_search();
|
||||
m_explain.set_full_dimensional(is_full_dimensional());
|
||||
if (m_random_order) {
|
||||
bool reordered = false;
|
||||
if (!can_reorder()) {
|
||||
|
||||
}
|
||||
else if (m_random_order) {
|
||||
shuffle_vars();
|
||||
reordered = true;
|
||||
}
|
||||
else if (m_reorder) {
|
||||
heuristic_reorder();
|
||||
reordered = true;
|
||||
}
|
||||
sort_watched_clauses();
|
||||
lbool r = search();
|
||||
CTRACE("nlsat_model", r == l_true, tout << "model before restore order\n"; display_assignment(tout); display_bool_assignment(tout););
|
||||
if (m_reorder)
|
||||
CTRACE("nlsat_model", r == l_true, tout << "model before restore order\n"; display_assignment(tout););
|
||||
if (reordered)
|
||||
restore_order();
|
||||
CTRACE("nlsat_model", r == l_true, tout << "model\n"; display_assignment(tout); display_bool_assignment(tout););
|
||||
CTRACE("nlsat_model", r == l_true, tout << "model\n"; display_assignment(tout););
|
||||
CTRACE("nlsat", r == l_false, display(tout););
|
||||
return r;
|
||||
}
|
||||
|
||||
void init_search() {
|
||||
undo_until_empty();
|
||||
while (m_scope_lvl > 0) {
|
||||
undo_new_level();
|
||||
}
|
||||
m_xk = null_var;
|
||||
for (unsigned i = 0; i < m_bvalues.size(); ++i) {
|
||||
m_bvalues[i] = l_undef;
|
||||
}
|
||||
m_assignment.reset();
|
||||
}
|
||||
|
||||
lbool check(literal_vector& assumptions) {
|
||||
literal_vector result;
|
||||
unsigned sz = assumptions.size();
|
||||
literal const* ptr = assumptions.c_ptr();
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
mk_clause(1, ptr+i, (assumption)(ptr+i));
|
||||
}
|
||||
lbool r = check();
|
||||
|
||||
if (r == l_false) {
|
||||
// collect used literals from m_lemma_assumptions
|
||||
vector<assumption, false> deps;
|
||||
m_asm.linearize(m_lemma_assumptions.get(), deps);
|
||||
for (unsigned i = 0; i < deps.size(); ++i) {
|
||||
literal const* lp = (literal const*)(deps[i]);
|
||||
if (ptr <= lp && lp < ptr + sz) {
|
||||
result.push_back(*lp);
|
||||
}
|
||||
}
|
||||
}
|
||||
collect(assumptions, m_clauses);
|
||||
collect(assumptions, m_learned);
|
||||
|
||||
assumptions.reset();
|
||||
assumptions.append(result);
|
||||
return r;
|
||||
}
|
||||
|
||||
void collect(literal_vector const& assumptions, clause_vector& clauses) {
|
||||
unsigned n = clauses.size();
|
||||
unsigned j = 0;
|
||||
for (unsigned i = 0; i < n; i++) {
|
||||
clause * c = clauses[i];
|
||||
if (collect(assumptions, *c)) {
|
||||
del_clause(c);
|
||||
}
|
||||
else {
|
||||
clauses[j] = c;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
clauses.shrink(j);
|
||||
}
|
||||
|
||||
bool collect(literal_vector const& assumptions, clause const& c) {
|
||||
unsigned sz = assumptions.size();
|
||||
literal const* ptr = assumptions.c_ptr();
|
||||
_assumption_set asms = static_cast<_assumption_set>(c.assumptions());
|
||||
if (asms == 0) {
|
||||
return false;
|
||||
}
|
||||
vector<assumption, false> deps;
|
||||
m_asm.linearize(asms, deps);
|
||||
bool found = false;
|
||||
for (unsigned i = 0; !found && i < deps.size(); ++i) {
|
||||
found = ptr <= deps[i] && deps[i] < ptr + sz;
|
||||
}
|
||||
return found;
|
||||
}
|
||||
|
||||
// -----------------------
|
||||
//
|
||||
// Conflict Resolution
|
||||
|
@ -1447,7 +1575,7 @@ namespace nlsat {
|
|||
TRACE("nlsat", tout << "resolve, conflicting clause:\n"; display(tout, *conflict_clause); tout << "\n";
|
||||
tout << "xk: "; if (m_xk != null_var) m_display_var(tout, m_xk); else tout << "<null>"; tout << "\n";
|
||||
tout << "scope_lvl: " << scope_lvl() << "\n";
|
||||
tout << "current assignment\n"; display_assignment(tout); display_bool_assignment(tout););
|
||||
tout << "current assignment\n"; display_assignment(tout););
|
||||
|
||||
// static unsigned counter = 0;
|
||||
// counter++;
|
||||
|
@ -1588,7 +1716,7 @@ namespace nlsat {
|
|||
conflict_clause = new_cls;
|
||||
goto start;
|
||||
}
|
||||
TRACE("nlsat_resolve_done", display_assignment(tout); display_bool_assignment(tout););
|
||||
TRACE("nlsat_resolve_done", display_assignment(tout););
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1801,6 +1929,15 @@ namespace nlsat {
|
|||
reorder(p.size(), p.c_ptr());
|
||||
}
|
||||
|
||||
bool can_reorder() const {
|
||||
for (unsigned i = 0; i < m_atoms.size(); ++i) {
|
||||
if (m_atoms[i]) {
|
||||
if (m_atoms[i]->is_root_atom()) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Reorder variables using the giving permutation.
|
||||
p maps internal variables to their new positions
|
||||
|
@ -1921,6 +2058,9 @@ namespace nlsat {
|
|||
void reinit_cache() {
|
||||
reinit_cache(m_clauses);
|
||||
reinit_cache(m_learned);
|
||||
for (unsigned i = 0; i < m_atoms.size(); ++i) {
|
||||
reinit_cache(m_atoms[i]);
|
||||
}
|
||||
}
|
||||
void reinit_cache(clause_vector const & cs) {
|
||||
unsigned sz = cs.size();
|
||||
|
@ -1934,10 +2074,13 @@ namespace nlsat {
|
|||
}
|
||||
void reinit_cache(literal l) {
|
||||
bool_var b = l.var();
|
||||
atom * a = m_atoms[b];
|
||||
if (a == 0)
|
||||
return;
|
||||
if (a->is_ineq_atom()) {
|
||||
reinit_cache(m_atoms[b]);
|
||||
}
|
||||
void reinit_cache(atom* a) {
|
||||
if (a == 0) {
|
||||
|
||||
}
|
||||
else if (a->is_ineq_atom()) {
|
||||
var max = 0;
|
||||
unsigned sz = to_ineq_atom(a)->size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
|
@ -2073,7 +2216,7 @@ namespace nlsat {
|
|||
//
|
||||
// -----------------------
|
||||
|
||||
void display_assignment(std::ostream & out, display_var_proc const & proc) const {
|
||||
void display_num_assignment(std::ostream & out, display_var_proc const & proc) const {
|
||||
for (var x = 0; x < num_vars(); x++) {
|
||||
if (m_assignment.is_assigned(x)) {
|
||||
proc(out, x);
|
||||
|
@ -2084,7 +2227,7 @@ namespace nlsat {
|
|||
}
|
||||
}
|
||||
|
||||
void display_bool_assignment(std::ostream & out, display_var_proc const & proc) const {
|
||||
void display_bool_assignment(std::ostream & out) const {
|
||||
unsigned sz = m_atoms.size();
|
||||
for (bool_var b = 0; b < sz; b++) {
|
||||
if (m_atoms[b] == 0 && m_bvalues[b] != l_undef) {
|
||||
|
@ -2112,12 +2255,13 @@ namespace nlsat {
|
|||
return !first;
|
||||
}
|
||||
|
||||
void display_assignment(std::ostream & out) const {
|
||||
display_assignment(out, m_display_var);
|
||||
void display_num_assignment(std::ostream & out) const {
|
||||
display_num_assignment(out, m_display_var);
|
||||
}
|
||||
|
||||
void display_bool_assignment(std::ostream & out) const {
|
||||
display_bool_assignment(out, m_display_var);
|
||||
void display_assignment(std::ostream& out) const {
|
||||
display_bool_assignment(out);
|
||||
display_num_assignment(out);
|
||||
}
|
||||
|
||||
void display(std::ostream & out, ineq_atom const & a, display_var_proc const & proc, bool use_star = false) const {
|
||||
|
@ -2511,6 +2655,7 @@ namespace nlsat {
|
|||
|
||||
void display(std::ostream & out) const {
|
||||
display(out, m_display_var);
|
||||
display_assignment(out);
|
||||
}
|
||||
|
||||
void display_vars(std::ostream & out) const {
|
||||
|
@ -2562,6 +2707,20 @@ namespace nlsat {
|
|||
return m_imp->check();
|
||||
}
|
||||
|
||||
lbool solver::check(literal_vector& assumptions) {
|
||||
return m_imp->check(assumptions);
|
||||
}
|
||||
|
||||
void solver::reset() {
|
||||
m_imp->reset();
|
||||
}
|
||||
|
||||
|
||||
void solver::updt_params(params_ref const & p) {
|
||||
m_imp->updt_params(p);
|
||||
}
|
||||
|
||||
|
||||
void solver::collect_param_descrs(param_descrs & d) {
|
||||
algebraic_numbers::manager::collect_param_descrs(d);
|
||||
nlsat_params::collect_param_descrs(d);
|
||||
|
@ -2583,6 +2742,10 @@ namespace nlsat {
|
|||
m_imp->m_display_var.m_proc = &proc;
|
||||
}
|
||||
|
||||
unsigned solver::num_vars() const {
|
||||
return m_imp->num_vars();
|
||||
}
|
||||
|
||||
bool solver::is_int(var x) const {
|
||||
return m_imp->is_int(x);
|
||||
}
|
||||
|
@ -2590,10 +2753,61 @@ namespace nlsat {
|
|||
bool_var solver::mk_bool_var() {
|
||||
return m_imp->mk_bool_var();
|
||||
}
|
||||
|
||||
literal solver::mk_true() {
|
||||
return literal(0, false);
|
||||
}
|
||||
|
||||
atom * solver::bool_var2atom(bool_var b) {
|
||||
return m_imp->m_atoms[b];
|
||||
}
|
||||
|
||||
void solver::vars(literal l, var_vector& vs) {
|
||||
m_imp->vars(l, vs);
|
||||
}
|
||||
|
||||
atom_vector const& solver::get_atoms() {
|
||||
return m_imp->m_atoms;
|
||||
}
|
||||
|
||||
atom_vector const& solver::get_var2eq() {
|
||||
return m_imp->m_var2eq;
|
||||
}
|
||||
|
||||
evaluator& solver::get_evaluator() {
|
||||
return m_imp->m_evaluator;
|
||||
}
|
||||
|
||||
explain& solver::get_explain() {
|
||||
return m_imp->m_explain;
|
||||
}
|
||||
|
||||
void solver::reorder(unsigned sz, var const* p) {
|
||||
m_imp->reorder(sz, p);
|
||||
}
|
||||
|
||||
void solver::restore_order() {
|
||||
m_imp->restore_order();
|
||||
}
|
||||
|
||||
void solver::set_rvalues(assignment const& as) {
|
||||
m_imp->m_assignment.copy(as);
|
||||
}
|
||||
|
||||
void solver::get_rvalues(assignment& as) {
|
||||
as.copy(m_imp->m_assignment);
|
||||
}
|
||||
|
||||
void solver::get_bvalues(svector<lbool>& vs) {
|
||||
vs.reset();
|
||||
vs.append(m_imp->m_bvalues);
|
||||
}
|
||||
|
||||
void solver::set_bvalues(svector<lbool> const& vs) {
|
||||
m_imp->m_bvalues.reset();
|
||||
m_imp->m_bvalues.append(vs);
|
||||
m_imp->m_bvalues.resize(m_imp->m_atoms.size(), l_undef);
|
||||
}
|
||||
|
||||
var solver::mk_var(bool is_int) {
|
||||
return m_imp->mk_var(is_int);
|
||||
|
@ -2631,10 +2845,21 @@ namespace nlsat {
|
|||
m_imp->display(out, l);
|
||||
}
|
||||
|
||||
void solver::display(std::ostream & out, unsigned n, literal const* ls) const {
|
||||
for (unsigned i = 0; i < n; ++i) {
|
||||
display(out, ls[i]);
|
||||
out << "; ";
|
||||
}
|
||||
}
|
||||
|
||||
void solver::display(std::ostream & out, var x) const {
|
||||
m_imp->m_display_var(out, x);
|
||||
}
|
||||
|
||||
void solver::display(std::ostream & out, atom const& a) const {
|
||||
m_imp->display(out, a, m_imp->m_display_var);
|
||||
}
|
||||
|
||||
display_var_proc const & solver::display_proc() const {
|
||||
return m_imp->m_display_var;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,9 @@ Revision History:
|
|||
|
||||
namespace nlsat {
|
||||
|
||||
class evaluator;
|
||||
class explain;
|
||||
|
||||
class solver {
|
||||
struct imp;
|
||||
imp * m_imp;
|
||||
|
@ -63,7 +66,9 @@ namespace nlsat {
|
|||
nonlinear arithmetic atom.
|
||||
*/
|
||||
bool_var mk_bool_var();
|
||||
|
||||
|
||||
literal mk_true();
|
||||
|
||||
/**
|
||||
\brief Create a real/integer variable.
|
||||
*/
|
||||
|
@ -121,6 +126,48 @@ namespace nlsat {
|
|||
*/
|
||||
atom * bool_var2atom(bool_var b);
|
||||
|
||||
/**
|
||||
\brief extract free variables from literal.
|
||||
*/
|
||||
void vars(literal l, var_vector& vs);
|
||||
|
||||
/**
|
||||
\brief provide access to atoms. Used by explain.
|
||||
*/
|
||||
atom_vector const& get_atoms();
|
||||
|
||||
/**
|
||||
\brief Access var -> asserted equality.
|
||||
*/
|
||||
|
||||
atom_vector const& get_var2eq();
|
||||
|
||||
/**
|
||||
\brief expose evaluator.
|
||||
*/
|
||||
|
||||
evaluator& get_evaluator();
|
||||
|
||||
/**
|
||||
\brief Access explanation module.
|
||||
*/
|
||||
explain& get_explain();
|
||||
|
||||
/**
|
||||
\brief Access assignments to variables.
|
||||
*/
|
||||
void get_rvalues(assignment& as);
|
||||
void set_rvalues(assignment const& as);
|
||||
|
||||
void get_bvalues(svector<lbool>& vs);
|
||||
void set_bvalues(svector<lbool> const& vs);
|
||||
|
||||
/**
|
||||
\brief reorder variables.
|
||||
*/
|
||||
void reorder(unsigned sz, var const* permutation);
|
||||
void restore_order();
|
||||
|
||||
/**
|
||||
\brief Return number of integer/real variables
|
||||
*/
|
||||
|
@ -135,6 +182,8 @@ namespace nlsat {
|
|||
// -----------------------
|
||||
lbool check();
|
||||
|
||||
lbool check(literal_vector& assumptions);
|
||||
|
||||
// -----------------------
|
||||
//
|
||||
// Model
|
||||
|
@ -154,6 +203,7 @@ namespace nlsat {
|
|||
void updt_params(params_ref const & p);
|
||||
static void collect_param_descrs(param_descrs & d);
|
||||
|
||||
void reset();
|
||||
void collect_statistics(statistics & st);
|
||||
void reset_statistics();
|
||||
void display_status(std::ostream & out) const;
|
||||
|
@ -174,6 +224,10 @@ namespace nlsat {
|
|||
*/
|
||||
void display(std::ostream & out, literal l) const;
|
||||
|
||||
void display(std::ostream & out, unsigned n, literal const* ls) const;
|
||||
|
||||
void display(std::ostream & out, atom const& a) const;
|
||||
|
||||
/**
|
||||
\brief Display variable
|
||||
*/
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue