mirror of
https://github.com/Z3Prover/z3
synced 2025-04-15 21:38:44 +00:00
make sure that the returned cross nested form is equal to the original
Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
This commit is contained in:
parent
4e59976c2f
commit
a844b88c32
|
@ -270,7 +270,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
nex* c_over_f = mk_div(*c, f);
|
nex* c_over_f = mk_div(*c, f);
|
||||||
to_sum(c_over_f)->simplify();
|
to_sum(c_over_f)->simplify(&c_over_f);
|
||||||
*c = mk_mul(f, c_over_f);
|
*c = mk_mul(f, c_over_f);
|
||||||
TRACE("nla_cn", tout << "common factor=" << *f << ", c=" << **c << "\ne = " << *m_e << "\n";);
|
TRACE("nla_cn", tout << "common factor=" << *f << ", c=" << **c << "\ne = " << *m_e << "\n";);
|
||||||
|
|
||||||
|
@ -463,8 +463,7 @@ public:
|
||||||
|| (ce->is_var() && to_var(ce)->var() == j);
|
|| (ce->is_var() && to_var(ce)->var() == j);
|
||||||
}
|
}
|
||||||
// all factors of j go to a, the rest to b
|
// all factors of j go to a, the rest to b
|
||||||
void pre_split(nex_sum * e, lpvar j, nex_sum* & a, nex* & b) {
|
void pre_split(nex_sum * e, lpvar j, nex_sum*& a, nex*& b) {
|
||||||
|
|
||||||
a = mk_sum();
|
a = mk_sum();
|
||||||
m_b_split_vec.clear();
|
m_b_split_vec.clear();
|
||||||
for (nex * ce: e->children()) {
|
for (nex * ce: e->children()) {
|
||||||
|
@ -478,7 +477,8 @@ public:
|
||||||
}
|
}
|
||||||
TRACE("nla_cn_details", tout << "a = " << *a << "\n";);
|
TRACE("nla_cn_details", tout << "a = " << *a << "\n";);
|
||||||
SASSERT(a->children().size() >= 2 && m_b_split_vec.size());
|
SASSERT(a->children().size() >= 2 && m_b_split_vec.size());
|
||||||
a->simplify();
|
nex* f;
|
||||||
|
a->simplify(&f);
|
||||||
|
|
||||||
if (m_b_split_vec.size() == 1) {
|
if (m_b_split_vec.size() == 1) {
|
||||||
b = m_b_split_vec[0];
|
b = m_b_split_vec[0];
|
||||||
|
@ -608,11 +608,13 @@ public:
|
||||||
for (unsigned j = 0; j < a->size(); j ++) {
|
for (unsigned j = 0; j < a->size(); j ++) {
|
||||||
a->children()[j] = normalize(a->children()[j]);
|
a->children()[j] = normalize(a->children()[j]);
|
||||||
}
|
}
|
||||||
a->simplify();
|
nex *r;
|
||||||
return a;
|
a->simplify(&r);
|
||||||
|
return r;
|
||||||
}
|
}
|
||||||
|
|
||||||
nex * normalize_mul(nex_mul* a) {
|
nex * normalize_mul(nex_mul* a) {
|
||||||
|
TRACE("nla_cn", tout << *a << "\n";);
|
||||||
int sum_j = -1;
|
int sum_j = -1;
|
||||||
for (unsigned j = 0; j < a->size(); j ++) {
|
for (unsigned j = 0; j < a->size(); j ++) {
|
||||||
a->children()[j] = normalize(a->children()[j]);
|
a->children()[j] = normalize(a->children()[j]);
|
||||||
|
@ -620,28 +622,36 @@ public:
|
||||||
sum_j = j;
|
sum_j = j;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sum_j == -1)
|
if (sum_j == -1) {
|
||||||
return a;
|
nex * r;
|
||||||
|
a->simplify(&r);
|
||||||
|
SASSERT(r->is_simplified());
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
nex_sum *r = mk_sum();
|
nex_sum *r = mk_sum();
|
||||||
nex_sum *as = to_sum(a->children()[sum_j]);
|
nex_sum *as = to_sum(a->children()[sum_j]);
|
||||||
for (unsigned k = 0; k < as->size(); k++) {
|
for (unsigned k = 0; k < as->size(); k++) {
|
||||||
nex_mul *b = mk_mul(as->children()[k]);
|
nex_mul *b = mk_mul(as->children()[k]);
|
||||||
r->add_child(b);
|
|
||||||
for (unsigned j = 0; j < a->size(); j ++) {
|
for (unsigned j = 0; j < a->size(); j ++) {
|
||||||
if ((int)j != sum_j)
|
if ((int)j != sum_j)
|
||||||
b->add_child(a->children()[j]);
|
b->add_child(a->children()[j]);
|
||||||
}
|
}
|
||||||
b->simplify();
|
nex *e;
|
||||||
|
b->simplify(&e);
|
||||||
|
r->add_child(e);
|
||||||
}
|
}
|
||||||
TRACE("nla_cn", tout << *r << "\n";);
|
TRACE("nla_cn", tout << *r << "\n";);
|
||||||
return normalize_sum(r);
|
nex *rs = normalize_sum(r);
|
||||||
|
SASSERT(rs->is_simplified());
|
||||||
|
return rs;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
nex * normalize(nex* a) {
|
nex * normalize(nex* a) {
|
||||||
if (a->is_simple())
|
if (a->is_elementary())
|
||||||
return a;
|
return a;
|
||||||
nex *r;
|
nex *r;
|
||||||
if (a->is_mul()) {
|
if (a->is_mul()) {
|
||||||
|
|
|
@ -49,7 +49,7 @@ public:
|
||||||
virtual expr_type type() const = 0;
|
virtual expr_type type() const = 0;
|
||||||
virtual std::ostream& print(std::ostream&) const = 0;
|
virtual std::ostream& print(std::ostream&) const = 0;
|
||||||
nex() {}
|
nex() {}
|
||||||
bool is_simple() const {
|
bool is_elementary() const {
|
||||||
switch(type()) {
|
switch(type()) {
|
||||||
case expr_type::SUM:
|
case expr_type::SUM:
|
||||||
case expr_type::MUL:
|
case expr_type::MUL:
|
||||||
|
@ -67,7 +67,10 @@ public:
|
||||||
virtual ~nex() {}
|
virtual ~nex() {}
|
||||||
virtual bool contains(lpvar j) const { return false; }
|
virtual bool contains(lpvar j) const { return false; }
|
||||||
virtual int get_degree() const = 0;
|
virtual int get_degree() const = 0;
|
||||||
virtual void simplify() {}
|
virtual void simplify(nex** ) = 0;
|
||||||
|
virtual bool is_simplified() const {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
virtual const ptr_vector<nex> * children_ptr() const {
|
virtual const ptr_vector<nex> * children_ptr() const {
|
||||||
UNREACHABLE();
|
UNREACHABLE();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
@ -103,6 +106,7 @@ public:
|
||||||
|
|
||||||
bool contains(lpvar j) const { return j == m_j; }
|
bool contains(lpvar j) const { return j == m_j; }
|
||||||
int get_degree() const { return 1; }
|
int get_degree() const { return 1; }
|
||||||
|
virtual void simplify(nex** e) { *e = this; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class nex_scalar : public nex {
|
class nex_scalar : public nex {
|
||||||
|
@ -119,28 +123,47 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_degree() const { return 0; }
|
int get_degree() const { return 0; }
|
||||||
|
virtual void simplify(nex** e) { *e = this; }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const nex_scalar * to_scalar(const nex* a);
|
||||||
|
|
||||||
|
static bool ignored_child(nex* e, expr_type t) {
|
||||||
|
switch(t) {
|
||||||
|
case expr_type::MUL:
|
||||||
|
return e->is_scalar() && to_scalar(e)->value().is_one();
|
||||||
|
case expr_type::SUM:
|
||||||
|
return e->is_scalar() && to_scalar(e)->value().is_zero();
|
||||||
|
default: return false;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
static void promote_children_by_type(ptr_vector<nex> * children, expr_type t) {
|
static void promote_children_by_type(ptr_vector<nex> * children, expr_type t) {
|
||||||
ptr_vector<nex> to_promote;
|
ptr_vector<nex> to_promote;
|
||||||
|
int skipped = 0;
|
||||||
for(unsigned j = 0; j < children->size(); j++) {
|
for(unsigned j = 0; j < children->size(); j++) {
|
||||||
nex* e = (*children)[j];
|
nex** e = &(*children)[j];
|
||||||
e->simplify();
|
(*e)->simplify(e);
|
||||||
if (e->type() == t) {
|
if ((*e)->type() == t) {
|
||||||
to_promote.push_back(e);
|
to_promote.push_back(*e);
|
||||||
|
} else if (ignored_child(*e, t)) {
|
||||||
|
skipped ++;
|
||||||
|
continue;
|
||||||
} else {
|
} else {
|
||||||
unsigned offset = to_promote.size();
|
unsigned offset = to_promote.size() + skipped;
|
||||||
if (offset) {
|
if (offset) {
|
||||||
(*children)[j - offset] = e;
|
(*children)[j - offset] = *e;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
children->shrink(children->size() - to_promote.size());
|
children->shrink(children->size() - to_promote.size() - skipped);
|
||||||
|
|
||||||
for (nex *e : to_promote) {
|
for (nex *e : to_promote) {
|
||||||
for (nex *ee : *(e->children_ptr())) {
|
for (nex *ee : *(e->children_ptr())) {
|
||||||
|
if (!ignored_child(ee, t))
|
||||||
children->push_back(ee);
|
children->push_back(ee);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -163,12 +186,12 @@ public:
|
||||||
std::string s = v->str();
|
std::string s = v->str();
|
||||||
if (first) {
|
if (first) {
|
||||||
first = false;
|
first = false;
|
||||||
if (v->is_simple())
|
if (v->is_elementary())
|
||||||
out << s;
|
out << s;
|
||||||
else
|
else
|
||||||
out << "(" << s << ")";
|
out << "(" << s << ")";
|
||||||
} else {
|
} else {
|
||||||
if (v->is_simple()) {
|
if (v->is_elementary()) {
|
||||||
if (s[0] == '-') {
|
if (s[0] == '-') {
|
||||||
out << "*(" << s << ")";
|
out << "*(" << s << ")";
|
||||||
} else {
|
} else {
|
||||||
|
@ -222,12 +245,29 @@ public:
|
||||||
return degree;
|
return degree;
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplify() {
|
void simplify(nex **e) {
|
||||||
|
*e = this;
|
||||||
TRACE("nla_cn_details", tout << *this << "\n";);
|
TRACE("nla_cn_details", tout << *this << "\n";);
|
||||||
promote_children_by_type(&m_children, expr_type::MUL);
|
promote_children_by_type(&m_children, expr_type::MUL);
|
||||||
|
if (size() == 1)
|
||||||
|
*e = m_children[0];
|
||||||
TRACE("nla_cn_details", tout << *this << "\n";);
|
TRACE("nla_cn_details", tout << *this << "\n";);
|
||||||
|
SASSERT((*e)->is_simplified());
|
||||||
}
|
}
|
||||||
#ifdef Z3DEBUG
|
|
||||||
|
virtual bool is_simplified() const {
|
||||||
|
if (size() < 2)
|
||||||
|
return false;
|
||||||
|
for (nex * e : children()) {
|
||||||
|
if (e->is_mul())
|
||||||
|
return false;
|
||||||
|
if (e->is_scalar() && to_scalar(e)->value().is_one())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef Z3DEBUG
|
||||||
virtual void sort() {
|
virtual void sort() {
|
||||||
for (nex * c : m_children) {
|
for (nex * c : m_children) {
|
||||||
c->sort();
|
c->sort();
|
||||||
|
@ -271,12 +311,12 @@ public:
|
||||||
std::string s = v->str();
|
std::string s = v->str();
|
||||||
if (first) {
|
if (first) {
|
||||||
first = false;
|
first = false;
|
||||||
if (v->is_simple())
|
if (v->is_elementary())
|
||||||
out << s;
|
out << s;
|
||||||
else
|
else
|
||||||
out << "(" << s << ")";
|
out << "(" << s << ")";
|
||||||
} else {
|
} else {
|
||||||
if (v->is_simple()) {
|
if (v->is_elementary()) {
|
||||||
if (s[0] == '-') {
|
if (s[0] == '-') {
|
||||||
out << s;
|
out << s;
|
||||||
} else {
|
} else {
|
||||||
|
@ -290,8 +330,21 @@ public:
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
void simplify() {
|
void simplify(nex **e) {
|
||||||
|
*e = this;
|
||||||
promote_children_by_type(&m_children, expr_type::SUM);
|
promote_children_by_type(&m_children, expr_type::SUM);
|
||||||
|
if (size() == 1)
|
||||||
|
*e = m_children[0];
|
||||||
|
}
|
||||||
|
virtual bool is_simplified() const {
|
||||||
|
if (size() < 2) return false;
|
||||||
|
for (nex * e : children()) {
|
||||||
|
if (e->is_sum())
|
||||||
|
return false;
|
||||||
|
if (e->is_scalar() && to_scalar(e)->value().is_zero())
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
int get_degree() const {
|
int get_degree() const {
|
||||||
|
@ -331,6 +384,11 @@ inline const nex_var* to_var(const nex*a) {
|
||||||
return static_cast<const nex_var*>(a);
|
return static_cast<const nex_var*>(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline const nex_scalar* to_scalar(const nex*a) {
|
||||||
|
SASSERT(a->is_scalar());
|
||||||
|
return static_cast<const nex_scalar*>(a);
|
||||||
|
}
|
||||||
|
|
||||||
inline const nex_mul* to_mul(const nex*a) {
|
inline const nex_mul* to_mul(const nex*a) {
|
||||||
SASSERT(a->is_mul());
|
SASSERT(a->is_mul());
|
||||||
return static_cast<const nex_mul*>(a);
|
return static_cast<const nex_mul*>(a);
|
||||||
|
@ -341,11 +399,6 @@ inline nex_mul* to_mul(nex*a) {
|
||||||
return static_cast<nex_mul*>(a);
|
return static_cast<nex_mul*>(a);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline const nex_scalar * to_scalar(const nex* a) {
|
|
||||||
SASSERT(a->is_scalar());
|
|
||||||
return static_cast<const nex_scalar*>(a);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline std::ostream& operator<<(std::ostream& out, const nex& e ) {
|
inline std::ostream& operator<<(std::ostream& out, const nex& e ) {
|
||||||
return e.print(out);
|
return e.print(out);
|
||||||
}
|
}
|
||||||
|
|
|
@ -102,8 +102,10 @@ void test_cn() {
|
||||||
nex* eac = cn.mk_mul(e, a, c);
|
nex* eac = cn.mk_mul(e, a, c);
|
||||||
nex* ed = cn.mk_mul(e, d);
|
nex* ed = cn.mk_mul(e, d);
|
||||||
nex* _6aad = cn.mk_mul(cn.mk_scalar(rational(6)), a, a, d);
|
nex* _6aad = cn.mk_mul(cn.mk_scalar(rational(6)), a, a, d);
|
||||||
|
#ifdef Z3DEBUG
|
||||||
nex * clone = cn.clone(cn.mk_sum(_6aad, abcd, aaccd, add, eae, eac, ed));
|
nex * clone = cn.clone(cn.mk_sum(_6aad, abcd, aaccd, add, eae, eac, ed));
|
||||||
TRACE("nla_cn", tout << "clone = " << *clone << "\n";);
|
TRACE("nla_cn", tout << "clone = " << *clone << "\n";);
|
||||||
|
#endif
|
||||||
// test_cn_on_expr(cn.mk_sum(aad, abcd, aaccd, add, eae, eac, ed), cn);
|
// test_cn_on_expr(cn.mk_sum(aad, abcd, aaccd, add, eae, eac, ed), cn);
|
||||||
test_cn_on_expr(cn.mk_sum(_6aad, abcd, aaccd, add, eae, eac, ed), cn);
|
test_cn_on_expr(cn.mk_sum(_6aad, abcd, aaccd, add, eae, eac, ed), cn);
|
||||||
// TRACE("nla_cn", tout << "done\n";);
|
// TRACE("nla_cn", tout << "done\n";);
|
||||||
|
|
Loading…
Reference in a new issue