#include "Term.hpp"
#include "LPO.hpp"
#include "TermOrderingDiagramLPO.hpp"
namespace Kernel {
using namespace std;
using namespace Lib;
using namespace Shell;
Ordering::Result LPO::comparePredicates(Literal* l1, Literal *l2) const
{
ASS(l1->shared());
ASS(l2->shared());
ASS(!l1->isEquality());
ASS(!l2->isEquality());
unsigned p1 = l1->functor();
unsigned p2 = l2->functor();
if (p1 == p2) {
ASS_EQ(l1->isNegative(), l1->isNegative())
for (unsigned i = 0; i < l1->arity(); i++) {
Result res = compare(*l1->nthArgument(i), *l2->nthArgument(i));
if (res != EQUAL)
return res;
}
return EQUAL;
}
ASS_NEQ(predicatePrecedence(p1), predicatePrecedence(p2)); return (predicatePrecedence(p1) > predicatePrecedence(p2)) ? GREATER : LESS;
}
Ordering::Result LPO::compare(TermList tl1, TermList tl2) const
{
return compare(AppliedTerm(tl1),AppliedTerm(tl2));
}
Ordering::Result LPO::compare(AppliedTerm tl1, AppliedTerm tl2) const
{
if(tl1.equalsShallow(tl2)) {
return EQUAL;
}
if(tl1.term.isVar()) {
return tl2.containsVar(tl1.term) ? LESS : INCOMPARABLE;
}
ASS(tl1.term.isTerm());
return clpo(tl1, tl2);
}
Ordering::Result LPO::compareUnidirectional(AppliedTerm lhs, AppliedTerm rhs) const
{
return lpo(lhs,rhs);
}
Ordering::Result LPO::clpo(AppliedTerm tl1, AppliedTerm tl2) const
{
ASS(tl1.term.isTerm());
if(tl2.term.isVar()) {
return tl1.containsVar(tl2.term) ? GREATER : INCOMPARABLE;
}
ASS(tl2.term.isTerm());
auto t1=tl1.term.term();
auto t2=tl2.term.term();
switch (comparePrecedences(t1, t2)) {
case EQUAL:
return cLMA(tl1, tl2, t1->args(), t2->args(), t1->arity());
case GREATER:
return cMA(tl1, tl2, t2->args(), t2->arity());
case LESS:
return Ordering::reverse(cMA(tl2, tl1, t1->args(), t1->arity()));
default:
ASSERTION_VIOLATION;
}
}
Ordering::Result LPO::cMA(AppliedTerm s, AppliedTerm t, const TermList* tl, unsigned arity) const
{
for (unsigned i = 0; i < arity; i++) {
switch(clpo(s, AppliedTerm(*(tl - i),t))) {
case EQUAL:
case LESS:
return LESS;
case INCOMPARABLE:
return reverse(alpha(tl - i - 1, arity - i - 1, t, s));
case GREATER:
break;
default:
ASSERTION_VIOLATION;
}
}
return GREATER;
}
Ordering::Result LPO::cLMA(AppliedTerm s, AppliedTerm t, const TermList* sl, const TermList* tl, unsigned arity) const
{
for (unsigned i = 0; i < arity; i++) {
switch(compare(AppliedTerm(*(sl - i),s), AppliedTerm(*(tl - i),t))) {
case EQUAL:
break;
case GREATER:
return cMA(s, t, tl - i - 1, arity - i - 1);
case LESS:
return reverse(cMA(t, s, sl - i - 1, arity - i - 1));
case INCOMPARABLE:
return cAA(s, t, sl - i - 1, tl - i - 1, arity - i - 1, arity - i - 1);
default:
ASSERTION_VIOLATION;
}
}
return EQUAL;
}
Ordering::Result LPO::cAA(AppliedTerm s, AppliedTerm t, const TermList* sl, const TermList* tl, unsigned arity1, unsigned arity2) const
{
switch (alpha(sl, arity1, s, t)) {
case GREATER:
return GREATER;
case INCOMPARABLE:
return reverse(alpha(tl, arity2, t, s));
default:
ASSERTION_VIOLATION;
}
}
Ordering::Result LPO::alpha(const TermList* sl, unsigned arity, AppliedTerm s, AppliedTerm t) const
{
ASS(t.term.isTerm());
for (unsigned i = 0; i < arity; i++) {
if (lpo(AppliedTerm(*(sl - i),s), t) != INCOMPARABLE) {
return GREATER;
}
}
return INCOMPARABLE;
}
Ordering::Result LPO::lpo(AppliedTerm tt1, AppliedTerm tt2) const
{
if(tt1.equalsShallow(tt2)) {
return EQUAL;
}
if (tt1.term.isVar()) {
return (tt1.term==tt2.term) ? EQUAL : INCOMPARABLE;
}
if (tt2.term.isVar()) {
return tt1.containsVar(tt2.term) ? GREATER : INCOMPARABLE;
}
auto t1=tt1.term.term();
auto t2=tt2.term.term();
switch (comparePrecedences(t1, t2)) {
case EQUAL:
return lexMAE(tt1, tt2, t1->args(), t2->args(), t1->arity());
case GREATER:
return majo(tt1, tt2, t2->args(), t2->arity());
default:
return alpha(t1->args(), t1->arity(), tt1, tt2);
}
}
Ordering::Result LPO::lexMAE(AppliedTerm s, AppliedTerm t, const TermList* sl, const TermList* tl, unsigned arity) const
{
for (unsigned i = 0; i < arity; i++) {
switch (lpo(AppliedTerm(*(sl - i),s), AppliedTerm(*(tl - i),t))) {
case EQUAL:
break;
case GREATER:
return majo(s, t, tl - i - 1, arity - i - 1);
case INCOMPARABLE:
return alpha(sl - i - 1, arity - i - 1, s, t);
default:
ASSERTION_VIOLATION;
}
}
return EQUAL;
}
Ordering::Result LPO::majo(AppliedTerm s, AppliedTerm t, const TermList* tl, unsigned arity) const
{
for (unsigned i = 0; i < arity; i++) {
if (lpo(s, AppliedTerm(*(tl - i), t)) != GREATER) {
return INCOMPARABLE;
}
}
return GREATER;
}
TermOrderingDiagramUP LPO::createTermOrderingDiagram(bool ground) const
{
return make_unique<TermOrderingDiagramLPO>(*this, ground);
}
void LPO::showConcrete(std::ostream&) const
{ }
}