mirror of
https://github.com/Z3Prover/z3
synced 2025-06-15 18:36:16 +00:00
Add div and inv for binary rational intervals
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
0203fa56d2
commit
ff62948d90
3 changed files with 92 additions and 19 deletions
|
@ -35,6 +35,10 @@ Notes:
|
||||||
#define REALCLOSURE_INI_SEQ_SIZE 256
|
#define REALCLOSURE_INI_SEQ_SIZE 256
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifndef REALCLOSURE_INI_DIV_PRECISION
|
||||||
|
#define REALCLOSURE_INI_DIV_PRECISION 24
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace realclosure {
|
namespace realclosure {
|
||||||
|
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
|
@ -43,11 +47,29 @@ namespace realclosure {
|
||||||
//
|
//
|
||||||
// ---------------------------------
|
// ---------------------------------
|
||||||
|
|
||||||
class mpbq_config {
|
struct mpbq_config {
|
||||||
mpbq_manager & m_manager;
|
|
||||||
public:
|
struct numeral_manager : public mpbq_manager {
|
||||||
typedef mpbq_manager numeral_manager;
|
unsigned m_div_precision;
|
||||||
|
bool m_to_plus_inf;
|
||||||
|
|
||||||
|
numeral_manager(unsynch_mpq_manager & qm):mpbq_manager(qm), m_div_precision(REALCLOSURE_INI_DIV_PRECISION), m_to_plus_inf(true) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void div(mpbq const & a, mpbq const & b, mpbq & c) {
|
||||||
|
approx_div(a, b, c, m_div_precision, m_to_plus_inf);
|
||||||
|
}
|
||||||
|
|
||||||
|
void inv(mpbq & a) {
|
||||||
|
mpbq one(1);
|
||||||
|
scoped_mpbq r(*this);
|
||||||
|
approx_div(one, a, r, m_div_precision, m_to_plus_inf);
|
||||||
|
swap(a, r);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
typedef mpbq numeral;
|
typedef mpbq numeral;
|
||||||
|
numeral_manager & m_manager;
|
||||||
|
|
||||||
struct interval {
|
struct interval {
|
||||||
numeral m_lower;
|
numeral m_lower;
|
||||||
|
@ -59,12 +81,11 @@ namespace realclosure {
|
||||||
swap(m_lower, l);
|
swap(m_lower, l);
|
||||||
swap(m_upper, u);
|
swap(m_upper, u);
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void round_to_minus_inf() {}
|
void set_rounding(bool to_plus_inf) { m_manager.m_to_plus_inf = to_plus_inf; }
|
||||||
void round_to_plus_inf() {}
|
void round_to_minus_inf() { set_rounding(false); }
|
||||||
void set_rounding(bool to_plus_inf) {}
|
void round_to_plus_inf() { set_rounding(true); }
|
||||||
|
|
||||||
// Getters
|
// Getters
|
||||||
numeral const & lower(interval const & a) const { return a.m_lower; }
|
numeral const & lower(interval const & a) const { return a.m_lower; }
|
||||||
|
@ -110,13 +131,14 @@ namespace realclosure {
|
||||||
struct value {
|
struct value {
|
||||||
unsigned m_ref_count;
|
unsigned m_ref_count;
|
||||||
bool m_rational;
|
bool m_rational;
|
||||||
|
mpbqi m_interval; // approximation as a binary rational
|
||||||
value(bool rat):m_ref_count(0), m_rational(rat) {}
|
value(bool rat):m_ref_count(0), m_rational(rat) {}
|
||||||
bool is_rational() const { return m_rational; }
|
bool is_rational() const { return m_rational; }
|
||||||
|
mpbqi const & interval() const { return m_interval; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rational_value : public value {
|
struct rational_value : public value {
|
||||||
mpq m_value;
|
mpq m_value;
|
||||||
mpbqi m_interval; // approximation as a binary rational
|
|
||||||
rational_value():value(true) {}
|
rational_value():value(true) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -137,6 +159,7 @@ namespace realclosure {
|
||||||
extension * ext() const { return m_ext; }
|
extension * ext() const { return m_ext; }
|
||||||
bool is_real() const { return m_real; }
|
bool is_real() const { return m_real; }
|
||||||
polynomial const & p() const { return m_p; }
|
polynomial const & p() const { return m_p; }
|
||||||
|
mpbqi const & interval() const { return m_interval; }
|
||||||
};
|
};
|
||||||
|
|
||||||
struct rational_function_value : public value {
|
struct rational_function_value : public value {
|
||||||
|
@ -268,7 +291,7 @@ namespace realclosure {
|
||||||
small_object_allocator * m_allocator;
|
small_object_allocator * m_allocator;
|
||||||
bool m_own_allocator;
|
bool m_own_allocator;
|
||||||
unsynch_mpq_manager & m_qm;
|
unsynch_mpq_manager & m_qm;
|
||||||
mpbq_manager m_bqm;
|
mpbq_config::numeral_manager m_bqm;
|
||||||
mpqi_manager m_qim;
|
mpqi_manager m_qim;
|
||||||
mpbqi_manager m_bqim;
|
mpbqi_manager m_bqim;
|
||||||
ptr_vector<extension> m_extensions[3];
|
ptr_vector<extension> m_extensions[3];
|
||||||
|
@ -398,6 +421,7 @@ namespace realclosure {
|
||||||
}
|
}
|
||||||
|
|
||||||
void del_rational_function(rational_function_value * v) {
|
void del_rational_function(rational_function_value * v) {
|
||||||
|
bqim().del(v->m_interval);
|
||||||
if (v->num())
|
if (v->num())
|
||||||
del_polynomial_expr(v->num());
|
del_polynomial_expr(v->num());
|
||||||
if (v->den())
|
if (v->den())
|
||||||
|
@ -617,6 +641,18 @@ namespace realclosure {
|
||||||
return r;
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void updt_interval(rational_function_value & v) {
|
||||||
|
if (v.den() == 0) {
|
||||||
|
bqim().set(v.m_interval, v.num()->interval());
|
||||||
|
}
|
||||||
|
else if (v.num() == 0) {
|
||||||
|
bqim().inv(v.den()->interval(), v.m_interval);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
bqim().div(v.num()->interval(), v.den()->interval(), v.m_interval);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void mk_infinitesimal(symbol const & n, numeral & r) {
|
void mk_infinitesimal(symbol const & n, numeral & r) {
|
||||||
unsigned idx = next_infinitesimal_idx();
|
unsigned idx = next_infinitesimal_idx();
|
||||||
infinitesimal * eps = alloc(infinitesimal, idx, n);
|
infinitesimal * eps = alloc(infinitesimal, idx, n);
|
||||||
|
@ -626,8 +662,10 @@ namespace realclosure {
|
||||||
mpbq tiny(1, m_eps_prec);
|
mpbq tiny(1, m_eps_prec);
|
||||||
mpbqi interval(zero, tiny);
|
mpbqi interval(zero, tiny);
|
||||||
polynomial_expr * numerator = mk_polynomial_expr(2, p, eps, interval);
|
polynomial_expr * numerator = mk_polynomial_expr(2, p, eps, interval);
|
||||||
r.m_value = alloc(rational_function_value, numerator, 0);
|
rational_function_value * v = alloc(rational_function_value, numerator, 0);
|
||||||
|
r.m_value = v;
|
||||||
inc_ref(r.m_value);
|
inc_ref(r.m_value);
|
||||||
|
updt_interval(*v);
|
||||||
SASSERT(sign(r) > 0);
|
SASSERT(sign(r) > 0);
|
||||||
SASSERT(!is_real(r));
|
SASSERT(!is_real(r));
|
||||||
}
|
}
|
||||||
|
@ -1421,9 +1459,17 @@ namespace realclosure {
|
||||||
qm().display_decimal(out, to_mpq(a), precision);
|
qm().display_decimal(out, to_mpq(a), precision);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void display_interval(std::ostream & out, numeral const & a) const {
|
||||||
|
if (is_zero(a))
|
||||||
|
out << "[0, 0]";
|
||||||
|
else
|
||||||
|
bqim().display(out, a.m_value->interval());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
manager::manager(unsynch_mpq_manager & m, params_ref const & p, small_object_allocator * a) {
|
manager::manager(unsynch_mpq_manager & m, params_ref const & p, small_object_allocator * a) {
|
||||||
|
@ -1620,4 +1666,8 @@ namespace realclosure {
|
||||||
m_imp->display_decimal(out, a, precision);
|
m_imp->display_decimal(out, a, precision);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void manager::display_interval(std::ostream & out, numeral const & a) const {
|
||||||
|
m_imp->display_interval(out, a);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -245,6 +245,9 @@ namespace realclosure {
|
||||||
This procedure throws an exception if the \c a is not a real.
|
This procedure throws an exception if the \c a is not a real.
|
||||||
*/
|
*/
|
||||||
void display_decimal(std::ostream & out, numeral const & a, unsigned precision = 10) const;
|
void display_decimal(std::ostream & out, numeral const & a, unsigned precision = 10) const;
|
||||||
|
|
||||||
|
|
||||||
|
void display_interval(std::ostream & out, numeral const & a) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class value;
|
class value;
|
||||||
|
@ -330,30 +333,49 @@ inline bool is_int(scoped_rcnumeral const & a) {
|
||||||
return a.m().is_int(a);
|
return a.m().is_int(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sym_pp {
|
struct rc_sym_pp {
|
||||||
rcmanager & m;
|
rcmanager & m;
|
||||||
rcnumeral const & n;
|
rcnumeral const & n;
|
||||||
sym_pp(rcmanager & _m, rcnumeral const & _n):m(_m), n(_n) {}
|
rc_sym_pp(rcmanager & _m, rcnumeral const & _n):m(_m), n(_n) {}
|
||||||
sym_pp(scoped_rcnumeral const & _n):m(_n.m()), n(_n.get()) {}
|
rc_sym_pp(scoped_rcnumeral const & _n):m(_n.m()), n(_n.get()) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream & operator<<(std::ostream & out, sym_pp const & n) {
|
inline rc_sym_pp sym_pp(scoped_rcnumeral const & _n) {
|
||||||
|
return rc_sym_pp(_n);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline std::ostream & operator<<(std::ostream & out, rc_sym_pp const & n) {
|
||||||
n.m.display(out, n.n);
|
n.m.display(out, n.n);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct decimal_pp {
|
struct rc_decimal_pp {
|
||||||
rcmanager & m;
|
rcmanager & m;
|
||||||
rcnumeral const & n;
|
rcnumeral const & n;
|
||||||
unsigned prec;
|
unsigned prec;
|
||||||
decimal_pp(rcmanager & _m, rcnumeral const & _n, unsigned p):m(_m), n(_n), prec(p) {}
|
rc_decimal_pp(rcmanager & _m, rcnumeral const & _n, unsigned p):m(_m), n(_n), prec(p) {}
|
||||||
decimal_pp(scoped_rcnumeral const & _n, unsigned p):m(_n.m()), n(_n.get()), prec(p) {}
|
rc_decimal_pp(scoped_rcnumeral const & _n, unsigned p):m(_n.m()), n(_n.get()), prec(p) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
inline std::ostream & operator<<(std::ostream & out, decimal_pp const & n) {
|
inline std::ostream & operator<<(std::ostream & out, rc_decimal_pp const & n) {
|
||||||
n.m.display_decimal(out, n.n, n.prec);
|
n.m.display_decimal(out, n.n, n.prec);
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct rc_interval_pp {
|
||||||
|
rcmanager & m;
|
||||||
|
rcnumeral const & n;
|
||||||
|
rc_interval_pp(rcmanager & _m, rcnumeral const & _n):m(_m), n(_n) {}
|
||||||
|
rc_interval_pp(scoped_rcnumeral const & _n):m(_n.m()), n(_n.get()) {}
|
||||||
|
};
|
||||||
|
|
||||||
|
inline std::ostream & operator<<(std::ostream & out, rc_interval_pp const & n) {
|
||||||
|
n.m.display_interval(out, n.n);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline rc_interval_pp interval_pp(rc_interval_pp const & n) {
|
||||||
|
return rc_interval_pp(n);
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -27,6 +27,7 @@ static void tst1() {
|
||||||
scoped_rcnumeral eps(m);
|
scoped_rcnumeral eps(m);
|
||||||
m.mk_infinitesimal("eps", eps);
|
m.mk_infinitesimal("eps", eps);
|
||||||
std::cout << sym_pp(eps) << std::endl;
|
std::cout << sym_pp(eps) << std::endl;
|
||||||
|
std::cout << interval_pp(eps) << std::endl;
|
||||||
}
|
}
|
||||||
|
|
||||||
void tst_rcf() {
|
void tst_rcf() {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue