3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-07 18:05:21 +00:00
z3/lib/lpo.cpp
Leonardo de Moura e9eab22e5c Z3 sources
Signed-off-by: Leonardo de Moura <leonardo@microsoft.com>
2012-10-02 11:35:25 -07:00

185 lines
5.4 KiB
C++

/*++
Copyright (c) 2006 Microsoft Corporation
Module Name:
lpo.h
Abstract:
Lexicographical Path Ordering
Author:
Leonardo de Moura (leonardo) 2008-02-01.
Revision History:
--*/
#include"lpo.h"
/**
\brief Check whether the variable in t1 occurs in t2.
*/
bool lpo::occurs(expr_offset const & t1, expr_offset const & t2) {
SASSERT(is_var(t1.get_expr()));
if (is_ground(t2.get_expr()))
return false;
m_todo.reset();
m_todo.push_back(t2);
while (!m_todo.empty()) {
expr_offset t = m_todo.back();
m_todo.pop_back();
t = find(t);
expr * n = t.get_expr();
if (is_ground(n))
continue;
unsigned offset = t.get_offset();
unsigned j;
switch (n->get_kind()) {
case AST_VAR:
if (t == t1)
return true;
break;
case AST_APP:
j = to_app(n)->get_num_args();
while (j > 0) {
--j;
expr * arg = to_app(n)->get_arg(j);
if (!is_ground(arg))
m_todo.push_back(expr_offset(arg, offset));
}
break;
default:
UNREACHABLE();
}
}
return false;
}
inline bool lpo::greater(expr_offset s, expr_offset t, unsigned depth) {
return lpo::compare(s, t, depth) == GREATER;
}
/**
\brief Return true if s >_{lpo} t_i forall children t_i of t.
*/
bool lpo::dominates_args(expr_offset s, expr_offset t, unsigned depth) {
SASSERT(is_app(t.get_expr()));
unsigned num_args = to_app(t.get_expr())->get_num_args();
unsigned off = t.get_offset();
for (unsigned i = 0; i < num_args; i++) {
expr * t_i = to_app(t.get_expr())->get_arg(i);
if (!greater(s, expr_offset(t_i, off), depth+1))
return false;
}
return true;
}
/**
\brief Return true if s_i >=_{lpo} t for some arg s_i of s.
*/
bool lpo::arg_dominates_expr(expr_offset s, expr_offset t, unsigned depth) {
SASSERT(is_app(s.get_expr()));
unsigned num_args = to_app(s.get_expr())->get_num_args();
unsigned off = s.get_offset();
for (unsigned i = 0; i < num_args; i++) {
expr * s_i = to_app(s.get_expr())->get_arg(i);
result r = compare(expr_offset(s_i, off), t, depth+1);
if (r == EQUAL || r == GREATER)
return true;
}
return false;
}
order::result lpo::lex_compare(expr_offset s, expr_offset t, unsigned depth) {
SASSERT(is_app(s.get_expr()));
SASSERT(is_app(t.get_expr()));
app * _s = to_app(s.get_expr());
app * _t = to_app(t.get_expr());
unsigned num_args1 = _s->get_num_args();
unsigned num_args2 = _t->get_num_args();
unsigned num_args = std::min(num_args1, num_args2);
unsigned off1 = s.get_offset();
unsigned off2 = t.get_offset();
result r = EQUAL;
for (unsigned i = 0; i < num_args; i++) {
r = compare(expr_offset(_s->get_arg(i), off1), expr_offset(_t->get_arg(i), off2), depth+1);
if (r != EQUAL)
break;
}
if (r == EQUAL) {
if (num_args1 > num_args2)
return GREATER;
if (num_args1 < num_args2)
return NOT_GTEQ;
}
return r;
}
inline order::result lpo::compare_core(expr_offset s, expr_offset t, unsigned depth) {
s = find(s);
t = find(t);
if (max_depth(depth))
return UNKNOWN;
if (is_var(s.get_expr()))
return s == t ? EQUAL : UNCOMPARABLE;
else if (is_var(t.get_expr()))
return occurs(t, s) ? GREATER : UNCOMPARABLE;
else {
func_decl * f = to_app(s.get_expr())->get_decl();
func_decl * g = to_app(t.get_expr())->get_decl();
if (f_greater(f, g))
return dominates_args(s, t, depth) ? GREATER : NOT_GTEQ;
else if (f != g)
return arg_dominates_expr(s, t, depth) ? GREATER : NOT_GTEQ;
else {
result r = lex_compare(s, t, depth);
if (r == GREATER) {
if (dominates_args(s, t, depth))
return GREATER;
}
else if (r == EQUAL)
return EQUAL;
return to_app(s.get_expr())->get_num_args() > 1 && arg_dominates_expr(s, t, depth) ? GREATER : NOT_GTEQ;
}
}
}
order::result lpo::compare(expr_offset s, expr_offset t, unsigned depth) {
TRACE("lpo", tout << "comparing:\n" << mk_pp(s.get_expr(), m_manager) << "\n" << mk_pp(t.get_expr(), m_manager) << "\n";);
result r = compare_core(s, t, depth);
TRACE("lpo", tout << "result of comparing:\n" << mk_pp(s.get_expr(), m_manager) << "\n" << mk_pp(t.get_expr(), m_manager) << "\nresult: " << r << "\n";);
return r;
}
bool lpo::greater(expr_offset const & t1, expr_offset const & t2, substitution * s) {
m_subst = s;
return greater(t1, t2, static_cast<unsigned>(0));
}
order::result lpo::compare(expr_offset const & t1, expr_offset const & t2, substitution * s) {
m_subst = s;
result r = compare(t1, t2, static_cast<unsigned>(0));
if (r != NOT_GTEQ)
return r;
r = compare(t2, t1, static_cast<unsigned>(0));
if (r == GREATER)
return LESSER;
if (r == UNKNOWN)
return UNKNOWN;
return UNCOMPARABLE;
}
int lpo::compare_ge(expr_offset const & t1, expr_offset const & t2, substitution * s) {
m_subst = s;
result r = compare(t1, t2, static_cast<unsigned>(0));
switch (r) {
case GREATER: return 1;
case EQUAL: return 0;
default: return -1;
}
}