z3-z3-4.13.0.src.math.subpaving.subpaving.cpp Maven / Gradle / Ivy
The newest version!
/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
subpaving.cpp
Abstract:
Subpaving for non-linear arithmetic.
This is a wrapper for the different implementations
of the subpaving module.
This wrapper is the main interface between Z3 other modules and subpaving.
Thus, it assumes that polynomials have precise integer coefficients, and
bounds are rationals. If a particular implementation uses floats, then
internally the bounds are approximated.
Author:
Leonardo de Moura (leonardo) 2012-08-07.
Revision History:
--*/
#include "math/subpaving/subpaving.h"
#include "math/subpaving/subpaving_types.h"
#include "math/subpaving/subpaving_mpq.h"
#include "math/subpaving/subpaving_mpf.h"
#include "math/subpaving/subpaving_hwf.h"
#include "math/subpaving/subpaving_mpff.h"
#include "math/subpaving/subpaving_mpfx.h"
namespace subpaving {
template
class context_wrapper : public context {
protected:
CTX m_ctx;
public:
context_wrapper(reslimit& lim, typename CTX::numeral_manager & m, params_ref const & p, small_object_allocator * a):m_ctx(lim, m, p, a) {}
unsigned num_vars() const override { return m_ctx.num_vars(); }
var mk_var(bool is_int) override { return m_ctx.mk_var(is_int); }
bool is_int(var x) const override { return m_ctx.is_int(x); }
var mk_monomial(unsigned sz, power const * pws) override { return m_ctx.mk_monomial(sz, pws); }
void inc_ref(ineq * a) override { m_ctx.inc_ref(reinterpret_cast(a)); }
void dec_ref(ineq * a) override { m_ctx.dec_ref(reinterpret_cast(a)); }
void add_clause(unsigned sz, ineq * const * atoms) override { m_ctx.add_clause(sz, reinterpret_cast(atoms)); }
void display_constraints(std::ostream & out, bool use_star) const override { m_ctx.display_constraints(out, use_star); }
void set_display_proc(display_var_proc * p) override { m_ctx.set_display_proc(p); }
void reset_statistics() override { m_ctx.reset_statistics(); }
void collect_statistics(statistics & st) const override { m_ctx.collect_statistics(st); }
void collect_param_descrs(param_descrs & r) override { m_ctx.collect_param_descrs(r); }
void updt_params(params_ref const & p) override { m_ctx.updt_params(p); }
void operator()() override { m_ctx(); }
void display_bounds(std::ostream & out) const override { m_ctx.display_bounds(out); }
};
class context_mpq_wrapper : public context_wrapper {
scoped_mpq m_c;
scoped_mpq_vector m_as;
public:
context_mpq_wrapper(reslimit& lim, unsynch_mpq_manager & m, params_ref const & p, small_object_allocator * a):
context_wrapper(lim, m, p, a),
m_c(m),
m_as(m)
{}
unsynch_mpq_manager & qm() const override { return m_ctx.nm(); }
var mk_sum(mpz const & c, unsigned sz, mpz const * as, var const * xs) override {
m_as.reserve(sz);
for (unsigned i = 0; i < sz; i++) {
m_ctx.nm().set(m_as[i], as[i]);
}
m_ctx.nm().set(m_c, c);
return m_ctx.mk_sum(m_c, sz, m_as.data(), xs);
}
ineq * mk_ineq(var x, mpq const & k, bool lower, bool open) override {
return reinterpret_cast(m_ctx.mk_ineq(x, k, lower, open));
}
};
class context_mpf_wrapper : public context_wrapper {
unsynch_mpq_manager & m_qm;
scoped_mpf m_c;
scoped_mpf_vector m_as;
scoped_mpq m_q1, m_q2;
// Convert the mpz (integer) into a mpf, and throws an exception if the conversion is not precise.
void int2mpf(mpz const & a, mpf & o) {
m_qm.set(m_q1, a);
m_ctx.nm().set(o, m_q1);
m_ctx.nm().m().to_rational(o, m_q2);
if (!m_qm.eq(m_q1, m_q2))
throw subpaving::exception();
}
public:
context_mpf_wrapper(reslimit& lim, f2n & fm, params_ref const & p, small_object_allocator * a):
context_wrapper(lim, fm, p, a),
m_qm(fm.m().mpq_manager()),
m_c(fm.m()),
m_as(fm.m()),
m_q1(m_qm),
m_q2(m_qm) {
}
unsynch_mpq_manager & qm() const override { return m_qm; }
var mk_sum(mpz const & c, unsigned sz, mpz const * as, var const * xs) override {
try {
m_as.reserve(sz);
for (unsigned i = 0; i < sz; i++) {
int2mpf(as[i], m_as[i]);
}
int2mpf(c, m_c);
return m_ctx.mk_sum(m_c, sz, m_as.data(), xs);
}
catch (const f2n::exception &) {
throw subpaving::exception();
}
}
ineq * mk_ineq(var x, mpq const & k, bool lower, bool open) override {
try {
f2n & m = m_ctx.nm();
if (lower)
m.round_to_minus_inf();
else
m.round_to_plus_inf();
m.set(m_c, k);
return reinterpret_cast(m_ctx.mk_ineq(x, m_c, lower, open));
}
catch (const f2n::exception &) {
throw subpaving::exception();
}
}
};
class context_hwf_wrapper : public context_wrapper {
unsynch_mpq_manager & m_qm;
hwf m_c;
svector m_as;
// Convert the mpz (integer) into a hwf, and throws an exception if the conversion is not precise.
void int2hwf(mpz const & a, hwf & o) {
if (!m_qm.is_int64(a))
throw subpaving::exception();
int64_t val = m_qm.get_int64(a);
double dval = static_cast(val);
m_ctx.nm().set(o, dval);
double _dval = m_ctx.nm().m().to_double(o);
// TODO check the following test
if (static_cast(_dval) != val)
throw subpaving::exception();
}
public:
context_hwf_wrapper(reslimit& lim,f2n & fm, unsynch_mpq_manager & qm, params_ref const & p, small_object_allocator * a):
context_wrapper(lim, fm, p, a),
m_qm(qm) {
}
unsynch_mpq_manager & qm() const override { return m_qm; }
var mk_sum(mpz const & c, unsigned sz, mpz const * as, var const * xs) override {
try {
m_as.reserve(sz);
for (unsigned i = 0; i < sz; i++) {
int2hwf(as[i], m_as[i]);
}
int2hwf(c, m_c);
return m_ctx.mk_sum(m_c, sz, m_as.data(), xs);
}
catch (const f2n::exception &) {
throw subpaving::exception();
}
}
ineq * mk_ineq(var x, mpq const & k, bool lower, bool open) override {
try {
f2n & m = m_ctx.nm();
if (lower)
m.round_to_minus_inf();
else
m.round_to_plus_inf();
m.set(m_c, k);
return reinterpret_cast(m_ctx.mk_ineq(x, m_c, lower, open));
}
catch (const f2n::exception &) {
throw subpaving::exception();
}
}
};
template
class context_fpoint_wrapper : public context_wrapper {
unsynch_mpq_manager & m_qm;
_scoped_numeral m_c;
_scoped_numeral_vector m_as;
scoped_mpz m_z1, m_z2;
void int2fpoint(mpz const & a, typename context_fpoint::numeral & o) {
m_qm.set(m_z1, a);
this->m_ctx.nm().set(o, m_qm, m_z1);
this->m_ctx.nm().to_mpz(o, m_qm, m_z2);
if (!m_qm.eq(m_z1, m_z2))
throw subpaving::exception();
}
public:
context_fpoint_wrapper(reslimit& lim, typename context_fpoint::numeral_manager & m, unsynch_mpq_manager & qm, params_ref const & p, small_object_allocator * a):
context_wrapper(lim, m, p, a),
m_qm(qm),
m_c(m),
m_as(m),
m_z1(m_qm),
m_z2(m_qm) {
}
unsynch_mpq_manager & qm() const override { return m_qm; }
var mk_sum(mpz const & c, unsigned sz, mpz const * as, var const * xs) override {
try {
m_as.reserve(sz);
for (unsigned i = 0; i < sz; i++) {
int2fpoint(as[i], m_as[i]);
}
int2fpoint(c, m_c);
return this->m_ctx.mk_sum(m_c, sz, m_as.data(), xs);
}
catch (const typename context_fpoint::numeral_manager::exception &) {
throw subpaving::exception();
}
}
ineq * mk_ineq(var x, mpq const & k, bool lower, bool open) override {
try {
typename context_fpoint::numeral_manager & m = this->m_ctx.nm();
if (lower)
m.round_to_minus_inf();
else
m.round_to_plus_inf();
m.set(m_c, m_qm, k);
return reinterpret_cast(this->m_ctx.mk_ineq(x, m_c, lower, open));
}
catch (const typename context_fpoint::numeral_manager::exception &) {
throw subpaving::exception();
}
}
};
typedef context_fpoint_wrapper context_mpff_wrapper;
typedef context_fpoint_wrapper context_mpfx_wrapper;
context * mk_mpq_context(reslimit& lim, unsynch_mpq_manager & m, params_ref const & p, small_object_allocator * a) {
return alloc(context_mpq_wrapper, lim, m, p, a);
}
context * mk_mpf_context(reslimit& lim, f2n & m, params_ref const & p, small_object_allocator * a) {
return alloc(context_mpf_wrapper, lim, m, p, a);
}
context * mk_hwf_context(reslimit& lim, f2n & m, unsynch_mpq_manager & qm, params_ref const & p, small_object_allocator * a) {
return alloc(context_hwf_wrapper, lim, m, qm, p, a);
}
context * mk_mpff_context(reslimit& lim, mpff_manager & m, unsynch_mpq_manager & qm, params_ref const & p, small_object_allocator * a) {
return alloc(context_mpff_wrapper, lim, m, qm, p, a);
}
context * mk_mpfx_context(reslimit& lim, mpfx_manager & m, unsynch_mpq_manager & qm, params_ref const & p, small_object_allocator * a) {
return alloc(context_mpfx_wrapper, lim, m, qm, p, a);
}
};