mirror of
https://github.com/Z3Prover/z3
synced 2025-04-24 01:25:31 +00:00
more cleanup
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
This commit is contained in:
parent
c2e95bb0c5
commit
683687b153
15 changed files with 2 additions and 508 deletions
1650
src/smt/diff_logic.h
Normal file
1650
src/smt/diff_logic.h
Normal file
File diff suppressed because it is too large
Load diff
642
src/smt/old_interval.cpp
Normal file
642
src/smt/old_interval.cpp
Normal file
|
@ -0,0 +1,642 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
old_interval.cpp
|
||||
|
||||
Abstract:
|
||||
|
||||
<abstract>
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-12-09.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
|
||||
#include"old_interval.h"
|
||||
|
||||
void ext_numeral::neg() {
|
||||
switch (m_kind) {
|
||||
case MINUS_INFINITY: m_kind = PLUS_INFINITY; break;
|
||||
case FINITE: m_value.neg(); break;
|
||||
case PLUS_INFINITY: m_kind = MINUS_INFINITY; break;
|
||||
}
|
||||
}
|
||||
|
||||
ext_numeral & ext_numeral::operator+=(ext_numeral const & other) {
|
||||
SASSERT(!is_infinite() || !other.is_infinite() || m_kind == other.m_kind);
|
||||
if (is_infinite())
|
||||
return *this;
|
||||
SASSERT(m_kind == FINITE);
|
||||
switch (other.m_kind) {
|
||||
case MINUS_INFINITY:
|
||||
m_kind = MINUS_INFINITY;
|
||||
m_value.reset();
|
||||
return *this;
|
||||
case FINITE:
|
||||
m_value += other.m_value;
|
||||
return *this;
|
||||
case PLUS_INFINITY:
|
||||
m_kind = PLUS_INFINITY;
|
||||
m_value.reset();
|
||||
return *this;
|
||||
}
|
||||
UNREACHABLE();
|
||||
return *this;
|
||||
}
|
||||
|
||||
ext_numeral & ext_numeral::operator-=(ext_numeral const & other) {
|
||||
SASSERT(!is_infinite() || !other.is_infinite() || (m_kind != other.m_kind));
|
||||
if (is_infinite())
|
||||
return *this;
|
||||
SASSERT(m_kind == FINITE);
|
||||
switch (other.m_kind) {
|
||||
case MINUS_INFINITY:
|
||||
m_kind = PLUS_INFINITY;
|
||||
m_value.reset();
|
||||
return *this;
|
||||
case FINITE:
|
||||
m_value -= other.m_value;
|
||||
return *this;
|
||||
case PLUS_INFINITY:
|
||||
m_kind = MINUS_INFINITY;
|
||||
m_value.reset();
|
||||
return *this;
|
||||
}
|
||||
UNREACHABLE();
|
||||
return *this;
|
||||
}
|
||||
|
||||
ext_numeral & ext_numeral::operator*=(ext_numeral const & other) {
|
||||
if (is_zero() || other.is_zero()) {
|
||||
m_kind = FINITE;
|
||||
m_value.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
if (is_infinite() || other.is_infinite()) {
|
||||
if (sign() == other.sign())
|
||||
m_kind = PLUS_INFINITY;
|
||||
else
|
||||
m_kind = MINUS_INFINITY;
|
||||
m_value.reset();
|
||||
return *this;
|
||||
}
|
||||
|
||||
SASSERT(m_kind == FINITE);
|
||||
m_value *= other.m_value;
|
||||
return *this;
|
||||
}
|
||||
|
||||
void ext_numeral::expt(unsigned n) {
|
||||
switch (m_kind) {
|
||||
case MINUS_INFINITY:
|
||||
if (n % 2 == 0)
|
||||
m_kind = PLUS_INFINITY;
|
||||
return;
|
||||
case FINITE:
|
||||
m_value = m_value.expt(n);
|
||||
break;
|
||||
case PLUS_INFINITY:
|
||||
// do nothing
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void ext_numeral::inv() {
|
||||
SASSERT(!is_zero());
|
||||
if (is_infinite()) {
|
||||
m_kind = FINITE;
|
||||
m_value.reset();
|
||||
}
|
||||
else {
|
||||
m_value = rational(1) / m_value;
|
||||
}
|
||||
}
|
||||
|
||||
void ext_numeral::display(std::ostream & out) const {
|
||||
switch (m_kind) {
|
||||
case MINUS_INFINITY:
|
||||
out << "-oo";
|
||||
break;
|
||||
case FINITE:
|
||||
out << m_value;
|
||||
break;
|
||||
case PLUS_INFINITY:
|
||||
out << "oo";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool operator==(ext_numeral const & n1, ext_numeral const & n2) {
|
||||
return n1.m_kind == n2.m_kind && (n1.is_infinite() || n1.m_value == n2.m_value);
|
||||
}
|
||||
|
||||
bool operator<(ext_numeral const & n1, ext_numeral const & n2) {
|
||||
if (n1.is_infinite())
|
||||
return n1.m_kind == ext_numeral::MINUS_INFINITY && n2.m_kind != ext_numeral::MINUS_INFINITY;
|
||||
if (n2.is_infinite())
|
||||
return n2.m_kind != ext_numeral::MINUS_INFINITY;
|
||||
return n1.m_value < n2.m_value;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Create interval (-oo, oo)
|
||||
*/
|
||||
interval::interval(v_dependency_manager & m):
|
||||
m_manager(m),
|
||||
m_lower(false),
|
||||
m_upper(true),
|
||||
m_lower_open(true),
|
||||
m_upper_open(true),
|
||||
m_lower_dep(0),
|
||||
m_upper_dep(0) {
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Create intervals [l,u], (l,u], [l, u), (l,u), where l and u are numerals.
|
||||
*/
|
||||
interval::interval(v_dependency_manager & m, rational const & lower, bool l_open, v_dependency * l_dep, rational const & upper, bool u_open, v_dependency * u_dep):
|
||||
m_manager(m),
|
||||
m_lower(lower),
|
||||
m_upper(upper),
|
||||
m_lower_open(l_open),
|
||||
m_upper_open(u_open),
|
||||
m_lower_dep(l_dep),
|
||||
m_upper_dep(u_dep) {
|
||||
SASSERT(lower <= upper);
|
||||
SASSERT(lower != upper || !l_open || !u_open);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Create intervals [l,u], (l,u], [l, u), (l,u), where l and u are ext_numerals.
|
||||
*/
|
||||
interval::interval(v_dependency_manager & m, ext_numeral const & lower, bool l_open, v_dependency * l_dep, ext_numeral const & upper, bool u_open, v_dependency * u_dep):
|
||||
m_manager(m),
|
||||
m_lower(lower),
|
||||
m_upper(upper),
|
||||
m_lower_open(l_open),
|
||||
m_upper_open(u_open),
|
||||
m_lower_dep(l_dep),
|
||||
m_upper_dep(u_dep) {
|
||||
SASSERT(lower <= upper);
|
||||
SASSERT(lower != upper || !l_open || !u_open);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Create interval [val,val]
|
||||
*/
|
||||
interval::interval(v_dependency_manager & m, rational const & val, v_dependency * l_dep, v_dependency * u_dep):
|
||||
m_manager(m),
|
||||
m_lower(val),
|
||||
m_upper(val),
|
||||
m_lower_open(false),
|
||||
m_upper_open(false),
|
||||
m_lower_dep(l_dep),
|
||||
m_upper_dep(u_dep) {
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Create intervals (-oo, val], (-oo, val), [val, oo), (val, oo)
|
||||
*/
|
||||
interval::interval(v_dependency_manager & m, rational const & val, bool open, bool lower, v_dependency * d):
|
||||
m_manager(m) {
|
||||
if (lower) {
|
||||
m_lower = ext_numeral(val);
|
||||
m_lower_open = open;
|
||||
m_lower_dep = d;
|
||||
m_upper = ext_numeral(true);
|
||||
m_upper_open = true;
|
||||
m_upper_dep = 0;
|
||||
}
|
||||
else {
|
||||
m_lower = ext_numeral(false);
|
||||
m_lower_open = true;
|
||||
m_lower_dep = 0;
|
||||
m_upper = ext_numeral(val);
|
||||
m_upper_open = open;
|
||||
m_upper_dep = d;
|
||||
}
|
||||
}
|
||||
|
||||
interval::interval(interval const & other):
|
||||
m_manager(other.m_manager),
|
||||
m_lower(other.m_lower),
|
||||
m_upper(other.m_upper),
|
||||
m_lower_open(other.m_lower_open),
|
||||
m_upper_open(other.m_upper_open),
|
||||
m_lower_dep(other.m_lower_dep),
|
||||
m_upper_dep(other.m_upper_dep) {
|
||||
}
|
||||
|
||||
interval & interval::operator=(interval const & other) {
|
||||
m_lower = other.m_lower;
|
||||
m_upper = other.m_upper;
|
||||
m_lower_open = other.m_lower_open;
|
||||
m_upper_open = other.m_upper_open;
|
||||
m_lower_dep = other.m_lower_dep;
|
||||
m_upper_dep = other.m_upper_dep;
|
||||
return *this;
|
||||
}
|
||||
|
||||
interval & interval::operator+=(interval const & other) {
|
||||
m_lower += other.m_lower;
|
||||
m_upper += other.m_upper;
|
||||
m_lower_open |= other.m_lower_open;
|
||||
m_upper_open |= other.m_upper_open;
|
||||
m_lower_dep = m_lower.is_infinite() ? 0 : m_manager.mk_join(m_lower_dep, other.m_lower_dep);
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : m_manager.mk_join(m_upper_dep, other.m_upper_dep);
|
||||
return *this;
|
||||
}
|
||||
|
||||
void interval::neg() {
|
||||
std::swap(m_lower, m_upper);
|
||||
std::swap(m_lower_open, m_upper_open);
|
||||
std::swap(m_lower_dep, m_upper_dep);
|
||||
m_lower.neg();
|
||||
m_upper.neg();
|
||||
}
|
||||
|
||||
interval & interval::operator-=(interval const & other) {
|
||||
interval tmp(other);
|
||||
tmp.neg();
|
||||
return operator+=(tmp);
|
||||
}
|
||||
|
||||
v_dependency * interval::join(v_dependency * d1, v_dependency * d2, v_dependency * d3, v_dependency * d4) {
|
||||
return m_manager.mk_join(m_manager.mk_join(d1, d2), m_manager.mk_join(d3,d4));
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Create a new v_dependency using d1, d2, and (opt1 or opt2).
|
||||
*/
|
||||
v_dependency * interval::join_opt(v_dependency * d1, v_dependency * d2, v_dependency * opt1, v_dependency * opt2) {
|
||||
if (opt1 == d1 || opt1 == d2)
|
||||
return join(d1, d2);
|
||||
if (opt2 == d1 || opt2 == d2)
|
||||
return join(d1, d2);
|
||||
if (opt1 == 0 || opt2 == 0)
|
||||
return join(d1, d2);
|
||||
// TODO: more opts...
|
||||
return join(d1, d2, opt1);
|
||||
}
|
||||
|
||||
interval & interval::operator*=(interval const & other) {
|
||||
#if Z3DEBUG || _TRACE
|
||||
bool contains_zero1 = contains_zero();
|
||||
bool contains_zero2 = other.contains_zero();
|
||||
#endif
|
||||
if (is_zero()) {
|
||||
return *this;
|
||||
}
|
||||
if (other.is_zero()) {
|
||||
*this = other;
|
||||
return *this;
|
||||
}
|
||||
|
||||
ext_numeral const & a = m_lower;
|
||||
ext_numeral const & b = m_upper;
|
||||
ext_numeral const & c = other.m_lower;
|
||||
ext_numeral const & d = other.m_upper;
|
||||
bool a_o = m_lower_open;
|
||||
bool b_o = m_upper_open;
|
||||
bool c_o = other.m_lower_open;
|
||||
bool d_o = other.m_upper_open;
|
||||
v_dependency * a_d = m_lower_dep;
|
||||
v_dependency * b_d = m_upper_dep;
|
||||
v_dependency * c_d = other.m_lower_dep;
|
||||
v_dependency * d_d = other.m_upper_dep;
|
||||
|
||||
TRACE("interval_bug", tout << "operator*= " << *this << " " << other << "\n";);
|
||||
|
||||
if (is_N()) {
|
||||
if (other.is_N()) {
|
||||
// x <= b <= 0, y <= d <= 0 --> b*d <= x*y
|
||||
// a <= x <= b <= 0, c <= y <= d <= 0 --> x*y <= a*c (we can use the fact that x or y is always negative (i.e., b is neg or d is neg))
|
||||
TRACE("interval_bug", tout << "(N, N)\n";);
|
||||
ext_numeral new_lower = b * d;
|
||||
ext_numeral new_upper = a * c;
|
||||
// if b = 0 (and the interval is closed), then the lower bound is closed
|
||||
m_lower_open = (is_N0() || other.is_N0()) ? false : (b_o || d_o);
|
||||
m_upper_open = a_o || c_o; SASSERT(a.is_neg() && c.is_neg());
|
||||
m_lower = new_lower;
|
||||
m_upper = new_upper;
|
||||
m_lower_dep = m_lower.is_infinite() ? 0 : join(b_d, d_d);
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : join_opt(a_d, c_d, b_d, d_d);
|
||||
}
|
||||
else if (other.is_M()) {
|
||||
// a <= x <= b <= 0, y <= d, d > 0 --> a*d <= x*y (uses the fact that b is not positive)
|
||||
// a <= x <= b <= 0, c <= y, c < 0 --> x*y <= a*c (uses the fact that b is not positive)
|
||||
TRACE("interval_bug", tout << "(N, M)\n";);
|
||||
ext_numeral new_lower = a * d; SASSERT(new_lower.is_neg());
|
||||
ext_numeral new_upper = a * c; SASSERT(new_upper.is_pos());
|
||||
m_lower_open = a_o || d_o;
|
||||
m_upper_open = a_o || c_o;
|
||||
m_lower = new_lower;
|
||||
m_upper = new_upper;
|
||||
m_lower_dep = m_lower.is_infinite() ? 0 : join(a_d, d_d, b_d);
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : join(a_d, c_d, b_d);
|
||||
}
|
||||
else {
|
||||
// a <= x <= b <= 0, 0 <= c <= y <= d --> a*d <= x*y (uses the fact that x is neg (b is not positive) or y is pos (c is not negative))
|
||||
// x <= b <= 0, 0 <= c <= y --> x*y <= b*c
|
||||
TRACE("interval_bug", tout << "(N, P)\n";);
|
||||
SASSERT(other.is_P());
|
||||
ext_numeral new_lower = a * d;
|
||||
ext_numeral new_upper = b * c;
|
||||
bool is_N0_old = is_N0(); // see comment in (P, N) case
|
||||
m_lower_open = a_o || d_o; SASSERT(a.is_neg() && d.is_pos());
|
||||
m_upper_open = (is_N0_old || other.is_P0()) ? false : (b_o || c_o);
|
||||
m_lower = new_lower;
|
||||
m_upper = new_upper;
|
||||
m_lower_dep = m_lower.is_infinite() ? 0 : join_opt(a_d, d_d, b_d, c_d);
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : join(b_d, c_d);
|
||||
}
|
||||
}
|
||||
else if (is_M()) {
|
||||
if (other.is_N()) {
|
||||
// b > 0, x <= b, c <= y <= d <= 0 --> b*c <= x*y (uses the fact that d is not positive)
|
||||
// a < 0, a <= x, c <= y <= d <= 0 --> x*y <= a*c (uses the fact that d is not positive)
|
||||
TRACE("interval_bug", tout << "(M, N)\n";);
|
||||
ext_numeral new_lower = b * c; SASSERT(new_lower.is_neg());
|
||||
ext_numeral new_upper = a * c; SASSERT(new_upper.is_pos());
|
||||
m_lower_open = b_o || c_o; SASSERT(b.is_pos() && c.is_neg());
|
||||
m_upper_open = a_o || c_o; SASSERT(a.is_neg() && c.is_neg());
|
||||
m_lower = new_lower;
|
||||
m_upper = new_upper;
|
||||
m_lower_dep = m_lower.is_infinite() ? 0 : join(b_d, c_d, d_d);
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : join(a_d, c_d, d_d);
|
||||
}
|
||||
else if (other.is_M()) {
|
||||
TRACE("interval_bug", tout << "(M, M)\n";);
|
||||
SASSERT(!a.is_zero() && !b.is_zero() && !c.is_zero() && !d.is_zero());
|
||||
ext_numeral ad = a*d; SASSERT(!ad.is_zero());
|
||||
ext_numeral bc = b*c; SASSERT(!bc.is_zero());
|
||||
ext_numeral ac = a*c; SASSERT(!ac.is_zero());
|
||||
ext_numeral bd = b*d; SASSERT(!bd.is_zero());
|
||||
bool ad_o = a_o || d_o;
|
||||
bool bc_o = b_o || c_o;
|
||||
bool ac_o = a_o || c_o;
|
||||
bool bd_o = b_o || d_o;
|
||||
if (ad < bc || (ad == bc && !ad_o && bc_o)) {
|
||||
m_lower = ad;
|
||||
m_lower_open = ad_o;
|
||||
}
|
||||
else {
|
||||
m_lower = bc;
|
||||
m_lower_open = bc_o;
|
||||
}
|
||||
if (ac > bd || (ac == bd && !ac_o && bd_o)) {
|
||||
m_upper = ac;
|
||||
m_upper_open = ac_o;
|
||||
}
|
||||
else {
|
||||
m_upper = bd;
|
||||
m_upper_open = bd_o;
|
||||
}
|
||||
m_lower_dep = m_lower.is_infinite() ? 0 : join(a_d, b_d, c_d, d_d);
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : join(a_d, b_d, c_d, d_d);
|
||||
}
|
||||
else {
|
||||
// a < 0, a <= x, 0 <= c <= y <= d --> a*d <= x*y (uses the fact that c is not negative)
|
||||
// b > 0, x <= b, 0 <= c <= y <= d --> x*y <= b*d (uses the fact that c is not negative)
|
||||
TRACE("interval_bug", tout << "(M, P)\n";);
|
||||
SASSERT(other.is_P());
|
||||
ext_numeral new_lower = a * d; SASSERT(new_lower.is_neg());
|
||||
ext_numeral new_upper = b * d; SASSERT(new_upper.is_pos());
|
||||
m_lower_open = a_o || d_o; SASSERT(a.is_neg() && d.is_pos());
|
||||
m_upper_open = b_o || d_o; SASSERT(b.is_pos() && d.is_pos());
|
||||
m_lower = new_lower;
|
||||
m_upper = new_upper;
|
||||
m_lower_dep = m_lower.is_infinite() ? 0 : join(a_d, d_d, c_d);
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : join(b_d, d_d, c_d);
|
||||
}
|
||||
}
|
||||
else {
|
||||
SASSERT(is_P());
|
||||
if (other.is_N()) {
|
||||
// 0 <= a <= x <= b, c <= y <= d <= 0 --> x*y <= b*c (uses the fact that x is pos (a is not neg) or y is neg (d is not pos))
|
||||
// 0 <= a <= x, y <= d <= 0 --> a*d <= x*y
|
||||
TRACE("interval_bug", tout << "(P, N)\n";);
|
||||
ext_numeral new_lower = b * c;
|
||||
ext_numeral new_upper = a * d;
|
||||
bool is_P0_old = is_P0(); // cache the value of is_P0(), since it may be affected by the next update.
|
||||
m_lower_open = b_o || c_o; SASSERT(b.is_pos() && c.is_neg());
|
||||
m_upper_open = (is_P0_old || other.is_N0()) ? false : a_o || d_o;
|
||||
m_lower = new_lower;
|
||||
m_upper = new_upper;
|
||||
m_lower_dep = m_lower.is_infinite() ? 0 : join_opt(b_d, c_d, a_d, d_d);
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : join(a_d, d_d);
|
||||
}
|
||||
else if (other.is_M()) {
|
||||
// 0 <= a <= x <= b, c <= y --> b*c <= x*y (uses the fact that a is not negative)
|
||||
// 0 <= a <= x <= b, y <= d --> x*y <= b*d (uses the fact that a is not negative)
|
||||
TRACE("interval_bug", tout << "(P, M)\n";);
|
||||
ext_numeral new_lower = b * c; SASSERT(new_lower.is_neg());
|
||||
ext_numeral new_upper = b * d; SASSERT(new_upper.is_pos());
|
||||
m_lower_open = b_o || c_o;
|
||||
m_upper_open = b_o || d_o;
|
||||
m_lower = new_lower;
|
||||
m_upper = new_upper;
|
||||
m_lower_dep = m_lower.is_infinite() ? 0 : join(b_d, c_d, a_d);
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : join(b_d, d_d, a_d);
|
||||
}
|
||||
else {
|
||||
// 0 <= a <= x, 0 <= c <= y --> a*c <= x*y
|
||||
// x <= b, y <= d --> x*y <= b*d (uses the fact that x is pos (a is not negative) or y is pos (c is not negative))
|
||||
TRACE("interval_bug", tout << "(P, P)\n";);
|
||||
SASSERT(other.is_P());
|
||||
ext_numeral new_lower = a * c;
|
||||
ext_numeral new_upper = b * d;
|
||||
m_lower_open = (is_P0() || other.is_P0()) ? false : a_o || c_o;
|
||||
m_upper_open = b_o || d_o; SASSERT(b.is_pos() && d.is_pos());
|
||||
m_lower = new_lower;
|
||||
m_upper = new_upper;
|
||||
m_lower_dep = m_lower.is_infinite() ? 0 : join(a_d, c_d);
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : join_opt(b_d, d_d, a_d, c_d);
|
||||
}
|
||||
}
|
||||
TRACE("interval_bug", tout << "operator*= result: " << *this << "\n";);
|
||||
CTRACE("interval", !(!(contains_zero1 || contains_zero2) || contains_zero()),
|
||||
tout << "contains_zero1: " << contains_zero1 << ", contains_zero2: " << contains_zero2 << ", contains_zero(): " << contains_zero() << "\n";);
|
||||
SASSERT(!(contains_zero1 || contains_zero2) || contains_zero());
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool interval::contains_zero() const {
|
||||
TRACE("interval_zero_bug", tout << "contains_zero info: " << *this << "\n";
|
||||
tout << "m_lower.is_neg(): " << m_lower.is_neg() << "\n";
|
||||
tout << "m_lower.is_zero: " << m_lower.is_zero() << "\n";
|
||||
tout << "m_lower_open: " << m_lower_open << "\n";
|
||||
tout << "m_upper.is_pos(): " << m_upper.is_pos() << "\n";
|
||||
tout << "m_upper.is_zero: " << m_upper.is_zero() << "\n";
|
||||
tout << "m_upper_open: " << m_upper_open << "\n";
|
||||
tout << "result: " << ((m_lower.is_neg() || (m_lower.is_zero() && !m_lower_open)) && (m_upper.is_pos() || (m_upper.is_zero() && !m_upper_open))) << "\n";);
|
||||
return
|
||||
(m_lower.is_neg() || (m_lower.is_zero() && !m_lower_open)) &&
|
||||
(m_upper.is_pos() || (m_upper.is_zero() && !m_upper_open));
|
||||
}
|
||||
|
||||
bool interval::contains(rational const& v) const {
|
||||
if (!inf().is_infinite()) {
|
||||
if (v < inf().to_rational()) return false;
|
||||
if (v == inf().to_rational() && m_lower_open) return false;
|
||||
}
|
||||
if (!sup().is_infinite()) {
|
||||
if (v > sup().to_rational()) return false;
|
||||
if (v == sup().to_rational() && m_upper_open) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
interval & interval::inv() {
|
||||
// If the interval [l,u] does not contain 0, then 1/[l,u] = [1/u, 1/l]
|
||||
SASSERT(!contains_zero());
|
||||
if (is_P1()) {
|
||||
// 0 < a <= x --> 1/x <= 1/a
|
||||
// 0 < a <= x <= b --> 1/b <= 1/x (use lower and upper bounds)
|
||||
ext_numeral new_lower = m_upper; SASSERT(!m_upper.is_zero());
|
||||
new_lower.inv();
|
||||
ext_numeral new_upper;
|
||||
if (m_lower.is_zero()) {
|
||||
SASSERT(m_lower_open);
|
||||
ext_numeral plus_infinity(true);
|
||||
new_upper = plus_infinity;
|
||||
}
|
||||
else {
|
||||
new_upper = m_lower;
|
||||
new_upper.inv();
|
||||
}
|
||||
m_lower = new_lower;
|
||||
m_upper = new_upper;
|
||||
std::swap(m_lower_open, m_upper_open);
|
||||
v_dependency * new_upper_dep = m_lower_dep;
|
||||
SASSERT(!m_lower.is_infinite());
|
||||
m_lower_dep = m_manager.mk_join(m_lower_dep, m_upper_dep);
|
||||
m_upper_dep = new_upper_dep;
|
||||
}
|
||||
else if (is_N1()) {
|
||||
// x <= a < 0 --> 1/a <= 1/x
|
||||
// b <= x <= a < 0 --> 1/b <= 1/x (use lower and upper bounds)
|
||||
ext_numeral new_upper = m_lower; SASSERT(!m_lower.is_zero());
|
||||
new_upper.inv();
|
||||
ext_numeral new_lower;
|
||||
if (m_upper.is_zero()) {
|
||||
SASSERT(m_upper_open);
|
||||
ext_numeral minus_infinity(false);
|
||||
new_lower = minus_infinity;
|
||||
}
|
||||
else {
|
||||
new_lower = m_upper;
|
||||
new_lower.inv();
|
||||
}
|
||||
m_lower = new_lower;
|
||||
m_upper = new_upper;
|
||||
std::swap(m_lower_open, m_upper_open);
|
||||
v_dependency * new_lower_dep = m_upper_dep;
|
||||
SASSERT(!m_upper.is_infinite());
|
||||
m_upper_dep = m_manager.mk_join(m_lower_dep, m_upper_dep);
|
||||
m_lower_dep = new_lower_dep;
|
||||
}
|
||||
else {
|
||||
UNREACHABLE();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
interval & interval::operator/=(interval const & other) {
|
||||
SASSERT(!other.contains_zero());
|
||||
if (is_zero()) {
|
||||
// 0/other = 0 if other != 0
|
||||
TRACE("interval", other.display_with_dependencies(tout););
|
||||
if (other.m_lower.is_pos() || (other.m_lower.is_zero() && other.m_lower_open)) {
|
||||
// other.lower > 0
|
||||
m_lower_dep = join(m_lower_dep, other.m_lower_dep);
|
||||
m_upper_dep = join(m_upper_dep, other.m_lower_dep);
|
||||
}
|
||||
else {
|
||||
// assertion must hold since !other.contains_zero()
|
||||
SASSERT(other.m_upper.is_neg() || (other.m_upper.is_zero() && other.m_upper_open));
|
||||
// other.upper < 0
|
||||
m_lower_dep = join(m_lower_dep, other.m_upper_dep);
|
||||
m_upper_dep = join(m_upper_dep, other.m_upper_dep);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
else {
|
||||
interval tmp(other);
|
||||
tmp.inv();
|
||||
return operator*=(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
void interval::expt(unsigned n) {
|
||||
if (n == 1)
|
||||
return;
|
||||
if (n % 2 == 0) {
|
||||
if (m_lower.is_pos()) {
|
||||
// [l, u]^n = [l^n, u^n] if l > 0
|
||||
// 0 < a <= x --> a^n <= x^n (lower bound guarantees that is positive)
|
||||
// 0 < a <= x <= b --> x^n <= b^n (use lower and upper bound -- need the fact that x is positive)
|
||||
m_lower.expt(n);
|
||||
m_upper.expt(n);
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : m_manager.mk_join(m_lower_dep, m_upper_dep);
|
||||
}
|
||||
else if (m_upper.is_neg()) {
|
||||
// [l, u]^n = [u^n, l^n] if u < 0
|
||||
// a <= x <= b < 0 --> x^n <= a^n (use lower and upper bound -- need the fact that x is negative)
|
||||
// x <= b < 0 --> b^n <= x^n
|
||||
std::swap(m_lower, m_upper);
|
||||
std::swap(m_lower_open, m_upper_open);
|
||||
std::swap(m_lower_dep, m_upper_dep);
|
||||
m_lower.expt(n);
|
||||
m_upper.expt(n);
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : m_manager.mk_join(m_lower_dep, m_upper_dep);
|
||||
}
|
||||
else {
|
||||
// [l, u]^n = [0, max{l^n, u^n}] otherwise
|
||||
// we need both bounds to justify upper bound
|
||||
TRACE("interval", tout << "before: " << m_lower << " " << m_upper << " " << n << "\n";);
|
||||
m_lower.expt(n);
|
||||
m_upper.expt(n);
|
||||
TRACE("interval", tout << "after: " << m_lower << " " << m_upper << "\n";);
|
||||
if (m_lower > m_upper || (m_lower == m_upper && !m_lower_open && m_upper_open)) {
|
||||
m_upper = m_lower;
|
||||
m_upper_open = m_lower_open;
|
||||
}
|
||||
m_upper_dep = m_upper.is_infinite() ? 0 : m_manager.mk_join(m_lower_dep, m_upper_dep);
|
||||
m_lower = ext_numeral(0);
|
||||
m_lower_open = false;
|
||||
m_lower_dep = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Remark: when n is odd x^n is monotonic.
|
||||
m_lower.expt(n);
|
||||
m_upper.expt(n);
|
||||
}
|
||||
}
|
||||
|
||||
void interval::display(std::ostream & out) const {
|
||||
out << (m_lower_open ? "(" : "[") << m_lower << ", " << m_upper << (m_upper_open ? ")" : "]");
|
||||
}
|
||||
|
||||
void interval::display_with_dependencies(std::ostream & out) const {
|
||||
ptr_vector<void> vs;
|
||||
m_manager.linearize(m_lower_dep, vs);
|
||||
m_manager.linearize(m_upper_dep, vs);
|
||||
out << "[";
|
||||
display(out);
|
||||
out << ", ";
|
||||
bool first = true;
|
||||
::display(out, vs.begin(), vs.end(), ", ", first);
|
||||
out << "]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
138
src/smt/old_interval.h
Normal file
138
src/smt/old_interval.h
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*++
|
||||
Copyright (c) 2006 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
old_interval.h
|
||||
|
||||
Abstract:
|
||||
|
||||
Old interval class. It is still used in some modules.
|
||||
|
||||
Author:
|
||||
|
||||
Leonardo de Moura (leonardo) 2008-12-09.
|
||||
|
||||
Revision History:
|
||||
|
||||
--*/
|
||||
#ifndef _OLD_INTERVAL_H_
|
||||
#define _OLD_INTERVAL_H_
|
||||
|
||||
#include"rational.h"
|
||||
#include"dependency.h"
|
||||
|
||||
class ext_numeral {
|
||||
public:
|
||||
enum kind { MINUS_INFINITY, FINITE, PLUS_INFINITY };
|
||||
private:
|
||||
kind m_kind;
|
||||
rational m_value;
|
||||
explicit ext_numeral(kind k):m_kind(k) {}
|
||||
public:
|
||||
ext_numeral():m_kind(FINITE) {} /* zero */
|
||||
explicit ext_numeral(bool plus_infinity):m_kind(plus_infinity ? PLUS_INFINITY : MINUS_INFINITY) {}
|
||||
explicit ext_numeral(rational const & val):m_kind(FINITE), m_value(val) {}
|
||||
explicit ext_numeral(int i):m_kind(FINITE), m_value(i) {}
|
||||
ext_numeral(ext_numeral const & other):m_kind(other.m_kind), m_value(other.m_value) {}
|
||||
bool is_infinite() const { return m_kind != FINITE; }
|
||||
bool sign() const { return m_kind == MINUS_INFINITY || (m_kind == FINITE && m_value.is_neg()); }
|
||||
void neg();
|
||||
bool is_zero() const { return m_kind == FINITE && m_value.is_zero(); }
|
||||
bool is_neg() const { return sign(); }
|
||||
bool is_pos() const { return !is_neg() && !is_zero(); }
|
||||
rational const & to_rational() const { SASSERT(!is_infinite()); return m_value; }
|
||||
ext_numeral & operator+=(ext_numeral const & other);
|
||||
ext_numeral & operator-=(ext_numeral const & other);
|
||||
ext_numeral & operator*=(ext_numeral const & other);
|
||||
void inv();
|
||||
void expt(unsigned n);
|
||||
void display(std::ostream & out) const;
|
||||
friend bool operator==(ext_numeral const & n1, ext_numeral const & n2);
|
||||
friend bool operator<(ext_numeral const & n1, ext_numeral const & n2);
|
||||
};
|
||||
|
||||
bool operator==(ext_numeral const & n1, ext_numeral const & n2);
|
||||
bool operator<(ext_numeral const & n1, ext_numeral const & n2);
|
||||
inline bool operator!=(ext_numeral const & n1, ext_numeral const & n2) { return !operator==(n1,n2); }
|
||||
inline bool operator>(ext_numeral const & n1, ext_numeral const & n2) { return operator<(n2, n1); }
|
||||
inline bool operator<=(ext_numeral const & n1, ext_numeral const & n2) { return !operator>(n1, n2); }
|
||||
inline bool operator>=(ext_numeral const & n1, ext_numeral const & n2) { return !operator<(n1, n2); }
|
||||
inline ext_numeral operator+(ext_numeral const & n1, ext_numeral const & n2) { return ext_numeral(n1) += n2; }
|
||||
inline ext_numeral operator-(ext_numeral const & n1, ext_numeral const & n2) { return ext_numeral(n1) -= n2; }
|
||||
inline ext_numeral operator*(ext_numeral const & n1, ext_numeral const & n2) { return ext_numeral(n1) *= n2; }
|
||||
inline std::ostream & operator<<(std::ostream & out, ext_numeral const & n) { n.display(out); return out; }
|
||||
|
||||
class old_interval {
|
||||
v_dependency_manager & m_manager;
|
||||
ext_numeral m_lower;
|
||||
ext_numeral m_upper;
|
||||
bool m_lower_open;
|
||||
bool m_upper_open;
|
||||
v_dependency * m_lower_dep; // justification for the lower bound
|
||||
v_dependency * m_upper_dep; // justification for the upper bound
|
||||
|
||||
v_dependency * join(v_dependency * d1, v_dependency * d2) { return m_manager.mk_join(d1, d2); }
|
||||
v_dependency * join(v_dependency * d1, v_dependency * d2, v_dependency * d3) { return m_manager.mk_join(m_manager.mk_join(d1, d2), d3); }
|
||||
v_dependency * join(v_dependency * d1, v_dependency * d2, v_dependency * d3, v_dependency * d4);
|
||||
v_dependency * join_opt(v_dependency * d1, v_dependency * d2, v_dependency * opt1, v_dependency * opt2);
|
||||
|
||||
public:
|
||||
explicit old_interval(v_dependency_manager & m);
|
||||
explicit old_interval(v_dependency_manager & m, rational const & lower, bool l_open, v_dependency * l_dep, rational const & upper, bool u_open, v_dependency * u_dep);
|
||||
explicit old_interval(v_dependency_manager & m, rational const & val, v_dependency * l_dep = 0, v_dependency * u_dep = 0);
|
||||
explicit old_interval(v_dependency_manager & m, rational const & val, bool open, bool lower, v_dependency * d);
|
||||
explicit old_interval(v_dependency_manager & m, ext_numeral const& lower, bool l_open, v_dependency * l_dep, ext_numeral const & upper, bool u_open, v_dependency * u_dep);
|
||||
old_interval(old_interval const & other);
|
||||
|
||||
bool minus_infinity() const { return m_lower.is_infinite(); }
|
||||
bool plus_infinity() const { return m_upper.is_infinite(); }
|
||||
bool is_lower_open() const { return m_lower_open; }
|
||||
bool is_upper_open() const { return m_upper_open; }
|
||||
v_dependency * get_lower_dependencies() const { return m_lower_dep; }
|
||||
v_dependency * get_upper_dependencies() const { return m_upper_dep; }
|
||||
rational const & get_lower_value() const { SASSERT(!minus_infinity()); return m_lower.to_rational(); }
|
||||
rational const & get_upper_value() const { SASSERT(!plus_infinity()); return m_upper.to_rational(); }
|
||||
old_interval & operator=(old_interval const & other);
|
||||
old_interval & operator+=(old_interval const & other);
|
||||
old_interval & operator-=(old_interval const & other);
|
||||
old_interval & operator*=(old_interval const & other);
|
||||
old_interval & operator*=(rational const & value);
|
||||
old_interval & operator/=(old_interval const & other);
|
||||
bool operator==(old_interval const & other) const { return m_lower == other.m_lower && m_upper == other.m_upper && m_lower_open == other.m_lower_open && m_upper_open == other.m_upper_open; }
|
||||
bool contains_zero() const;
|
||||
bool contains(rational const& v) const;
|
||||
old_interval & inv();
|
||||
void expt(unsigned n);
|
||||
void neg();
|
||||
void display(std::ostream & out) const;
|
||||
void display_with_dependencies(std::ostream & out) const;
|
||||
bool is_P() const { return m_lower.is_pos() || m_lower.is_zero(); }
|
||||
bool is_P0() const { return m_lower.is_zero() && !m_lower_open; }
|
||||
bool is_P1() const { return m_lower.is_pos() || (m_lower.is_zero() && m_lower_open); }
|
||||
bool is_N() const { return m_upper.is_neg() || m_upper.is_zero(); }
|
||||
bool is_N0() const { return m_upper.is_zero() && !m_upper_open; }
|
||||
bool is_N1() const { return m_upper.is_neg() || (m_upper.is_zero() && m_upper_open); }
|
||||
bool is_M() const { return m_lower.is_neg() && m_upper.is_pos(); }
|
||||
bool is_zero() const { return m_lower.is_zero() && m_upper.is_zero(); }
|
||||
|
||||
ext_numeral const& inf() const { return m_lower; }
|
||||
ext_numeral const& sup() const { return m_upper; }
|
||||
};
|
||||
|
||||
inline old_interval operator+(old_interval const & i1, old_interval const & i2) { return old_interval(i1) += i2; }
|
||||
inline old_interval operator-(old_interval const & i1, old_interval const & i2) { return old_interval(i1) -= i2; }
|
||||
inline old_interval operator*(old_interval const & i1, old_interval const & i2) { return old_interval(i1) *= i2; }
|
||||
inline old_interval operator/(old_interval const & i1, old_interval const & i2) { return old_interval(i1) /= i2; }
|
||||
inline old_interval expt(old_interval const & i, unsigned n) { old_interval tmp(i); tmp.expt(n); return tmp; }
|
||||
inline std::ostream & operator<<(std::ostream & out, old_interval const & i) { i.display(out); return out; }
|
||||
|
||||
struct interval_detail{};
|
||||
inline std::pair<old_interval, interval_detail> wd(old_interval const & i) { interval_detail d; return std::make_pair(i, d); }
|
||||
inline std::ostream & operator<<(std::ostream & out, std::pair<old_interval, interval_detail> const & p) { p.first.display_with_dependencies(out); return out; }
|
||||
|
||||
// allow "customers" of this file to keep using interval
|
||||
#define interval old_interval
|
||||
|
||||
#endif /* _OLD_INTERVAL_H_ */
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue