#include <cstdarg>
#include "Kernel/TermIterators.hpp"
#include "Lib/Environment.hpp"
#include "SAT/SATClause.hpp"
#include "SAT/SATLiteral.hpp"
#include "TestUtils.hpp"
namespace Test {
using namespace Kernel;
using namespace Shell;
SAT::SATClause* TestUtils::buildSATClause(unsigned len,...)
{
using namespace SAT;
va_list litArgs;
va_start(litArgs,len);
static SATLiteralStack lits;
lits.reset();
for(unsigned i=0; i<len; ++i) {
int litVal = va_arg(litArgs, int);
bool pos = litVal>0;
unsigned var = pos ? litVal : -litVal;
lits.push(SATLiteral(var, pos));
}
va_end(litArgs);
return SATClause::fromStack(lits);
}
std::ostream& printOp(std::ostream& out, const Term* t, const char* op, bool par = true) {
auto l = *t->nthArgument(0);
auto r = *t->nthArgument(1);
if (par) out << "(";
out << pretty(l) << " " << op << " " << pretty(r);
if (par) out << ")";
return out;
}
template<>
std::ostream& Pretty<Kernel::TermList>::prettyPrint(std::ostream& out) const
{ return out << _self; }
template<>
std::ostream& Pretty<Literal*>::prettyPrint(std::ostream& out) const
{ return out << pretty(*_self); }
template<>
std::ostream& Pretty<Clause>::prettyPrint(std::ostream& out) const
{
if (_self.isEmpty()) {
return out << "_|_";
}
auto iter = _self.iterLits();
out << "{ ";
if (iter.hasNext()) {
out << pretty(*iter.next());
while(iter.hasNext()) {
out << " | " << pretty(*iter.next());
}
} else {
}
out << " }";
return out;
}
template<>
std::ostream& Pretty<Literal>::prettyPrint(std::ostream& out) const
{
const Literal& lit = _self;
auto print = [&]() -> std::ostream& {
auto func = lit.functor();
if(theory->isInterpretedPredicate(func)) {
switch(theory->interpretPredicate(func)) {
#define NUM_CASE(oper) \
case Kernel::Theory::INT_ ## oper: \
case Kernel::Theory::REAL_ ## oper: \
case Kernel::Theory::RAT_ ## oper
NUM_CASE(GREATER):
return printOp(out, &lit, ">", false);
NUM_CASE(GREATER_EQUAL):
return printOp(out, &lit, ">=", false);
NUM_CASE(LESS_EQUAL):
return printOp(out, &lit, "<=", false);
case Kernel::Theory::EQUAL:
return printOp(out, &lit, "=", false);
default:
{
}
#undef NUM_CASE
}
}
Signature::Symbol* sym = env.signature->getPredicate(func);
out << sym->name();
if (sym->arity() > 0) {
out << "(" << pretty(*lit.nthArgument(0));
for (unsigned i = 1; i < sym->arity(); i++) {
out << ", " << pretty(*lit.nthArgument(i));
}
out << ")";
}
return out;
};
if (!lit.polarity()) {
out << "~(";
}
print();
if (!lit.polarity()) {
out << ")";
}
return out;
}
bool TestUtils::isAC(Term* t)
{
auto f = t->functor();
if (t->isLiteral()) {
return theory->isInterpretedPredicate(f) && isAC(theory->interpretPredicate(f));
} else if (t->isSort()) {
return false;
} else {
return theory->isInterpretedFunction(f) && isAC(theory->interpretFunction(f));
}
}
bool TestUtils::isAC(Theory::Interpretation i)
{
switch (i) {
#define NUM_CASE(oper) \
case Kernel::Theory::INT_ ## oper: \
case Kernel::Theory::REAL_ ## oper: \
case Kernel::Theory::RAT_ ## oper
NUM_CASE(PLUS):
NUM_CASE(MULTIPLY):
case Kernel::Theory::EQUAL:
return true;
default:
return false;
#undef NUM_CASE
}
}
bool TestUtils::eqModAC(const Kernel::Clause* lhs, const Kernel::Clause* rhs)
{ return permEq(*lhs, *rhs, [](Literal* l, Literal* r) -> bool { return TestUtils::eqModAC(l, r); }); }
bool TestUtils::eqModAC(Kernel::Literal* lhs, Kernel::Literal* rhs)
{ return lhs->isPositive() == rhs->isPositive()
&& TestUtils::eqModAC(TermList(lhs), TermList(rhs)); }
void __collect(unsigned functor, Term* t, Stack<TermList>& out) {
ASS_EQ(t->functor(), functor);
for (unsigned i = 0; i < t->arity(); i++) {
auto trm = t->nthArgument(i);
if (trm->isVar()) {
out.push(*trm);
} else {
ASS(trm->isTerm());
if (trm->term()->functor() == functor) {
__collect(functor, trm->term(), out);
} else {
out.push(*trm);
}
}
}
}
Stack<TermList> collect(unsigned functor, Term* t) {
Stack<TermList> out;
__collect(functor, t, out);
return out;
}
template<class Comparisons>
bool TestUtils::eqModAC_(TermList lhs, TermList rhs, Comparisons comp)
{
if (lhs == rhs) { return true; }
if (lhs.isVar() && rhs.isVar()) {
return comp.var(lhs.var(), rhs.var());
} else if (lhs.isTerm() && rhs.isTerm()) {
auto& l = *lhs.term();
auto& r = *rhs.term();
if ( l.functor() != r.functor() ) return false;
auto fun = l.functor();
if (isAC(&l)) {
Stack<TermList> lstack = collect(fun, &l);
Stack<TermList> rstack = collect(fun, &r);
return permEq(lstack, rstack, [&](TermList l, TermList r) -> bool {
return comp.subterm(l, r);
});
} else {
for (unsigned i = 0; i < l.arity(); i++) {
if (!comp.subterm(*l.nthArgument(i), *r.nthArgument(i))) {
return false;
}
}
return true;
}
} else {
return false;
}
}
bool TestUtils::eqModAC(TermList lhs, TermList rhs)
{
struct Comparisons {
bool var(unsigned lhs, unsigned rhs) const
{ return lhs == rhs; }
bool subterm(TermList lhs, TermList rhs) const
{ return eqModAC(lhs,rhs); }
};
Comparisons c {};
return eqModAC_(lhs, rhs, c);
}
struct AcRectComp {
Stack<TermList> const& vl;
Stack<TermList> const& vr;
DArray<unsigned> const& perm;
bool var(unsigned lhs, unsigned rhs) const
{
auto l = iterTraits(getRangeIterator<unsigned>(0, vl.size()))
.find([&](auto i) { return vl[i].var() == lhs; })
.unwrap();
auto r = iterTraits(getRangeIterator<unsigned>(0, vr.size()))
.find([&](auto i) { return vr[perm[i]].var() == rhs; })
.unwrap();
return l == r;
}
bool subterm(TermList lhs, TermList rhs) const
{ return TestUtils::eqModAC_(lhs, rhs, *this); }
};
bool TestUtils::eqModACRect(Kernel::TermList lhs, Kernel::TermList rhs)
{
auto vl = iterTraits(vi(new VariableIterator(lhs))).collect<Stack>();
vl.sort();
vl.dedup();
auto vr = iterTraits(vi(new VariableIterator(lhs))).collect<Stack>();
vr.sort();
vr.dedup();
if (vl.size() != vr.size()) return false;
return anyPerm(vl.size(), [&](auto const& perm) {
AcRectComp c {vl, vr, perm};
return eqModAC_(lhs, rhs, c);
});
}
template<class Lits>
bool TestUtils::_eqModACRect(Lits const& lhs, Lits const& rhs)
{
auto vars = [](Lits const& lits) {
auto vs = iterTraits(getRangeIterator(0u, (unsigned) lits.size()))
.map([&](auto i) { return lits[i]; })
.flatMap([](Literal* lit) { return vi(new VariableIterator(lit)); })
.template collect<Stack>();
vs.sort();
vs.dedup();
return vs;
};
auto vl = vars(lhs);
auto vr = vars(rhs);
if (vl.size() != vr.size()) return false;
return anyPerm(vl.size(), [&](auto& perm) {
AcRectComp c {vl, vr, perm};
return permEq(lhs, rhs, [&](Literal* l, Literal* r) {
return l->isPositive() == r->isPositive()
&& eqModAC_(TermList(l), TermList(r), c);
});
});
}
bool TestUtils::eqModACRect(const Clause* lhs, const Clause* rhs)
{ return _eqModACRect(*lhs, *rhs); }
bool TestUtils::eqModACRect(Stack<Literal*> const& lhs, Stack<Literal*> const& rhs)
{ return _eqModACRect(lhs, rhs); }
bool TestUtils::eqModACRect(Literal* lhs, Literal* rhs)
{ return lhs->isPositive() == rhs->isPositive()
&& TestUtils::eqModACRect(TermList(lhs), TermList(rhs)); }
}