#include <fstream>
#include "Debug/Assertion.hpp"
#include "Forwards.hpp"
#include "Indexing/TermSharing.hpp"
#include "Lib/Environment.hpp"
#include "Lib/DHMap.hpp"
#include "Lib/Int.hpp"
#include "Lib/Metaiterators.hpp"
#include "Shell/Options.hpp"
#include "Shell/Shuffling.hpp"
#include "LPO.hpp"
#include "KBO.hpp"
#include "TermOrderingDiagram.hpp"
#include "Problem.hpp"
#include "Signature.hpp"
#include "Kernel/NumTraits.hpp"
#include "Kernel/QKbo.hpp"
#include "Kernel/ALASCA/Ordering.hpp"
#include "Shell/Shuffling.hpp"
#include "NumTraits.hpp"
#include "Ordering.hpp"
#define NONINTERPRETED_PRECEDENCE_BOOST 0x1000
#define NONINTERPRETED_LEVEL_BOOST 0x1000
#define COLORED_LEVEL_BOOST 0x10000
using namespace std;
using namespace Lib;
using namespace Kernel;
OrderingSP Ordering::s_globalOrdering;
bool Ordering::trySetGlobalOrdering(OrderingSP ordering)
{
if(s_globalOrdering) {
return false;
}
s_globalOrdering = ordering;
return true;
}
bool Ordering::unsetGlobalOrdering()
{
if(s_globalOrdering) {
s_globalOrdering = OrderingSP();
return true;
} else {
return false;
}
}
Ordering* Ordering::tryGetGlobalOrdering()
{
if(s_globalOrdering) {
return s_globalOrdering.ptr();
}
else {
return 0;
}
}
struct AllIncomparableOrdering : Ordering {
AllIncomparableOrdering() {
WARN("using term ordering that makes all terms incomparable. This is meant for debugging purposes only, as it is potentially VERY slow. please be sure that you really want to do this.")
}
Result compare(Literal* l1,Literal* l2) const override { return Result::INCOMPARABLE; }
Result compare(TermList t1,TermList t2) const override { return Result::INCOMPARABLE; }
void show(std::ostream& out) const override { out << "everything incomparable" << std::endl; }
};
#define TIME_TRACING_ORD 0
#if TIME_TRACING_ORD
# define NEW_ORD(Ord, ...) \
new TimeTraceOrdering<Ord>(#Ord " (literal)", #Ord "(term)", Ord(__VA_ARGS__))
#else
# define NEW_ORD(Ord, ...) \
new Ord(__VA_ARGS__)
#endif
Ordering* Ordering::create(Problem& prb, const Options& opt)
{
Ordering* out;
switch (opt.termOrdering()) {
case Options::TermOrdering::KBO:
out = new KBO(prb, opt);
break;
case Options::TermOrdering::QKBO:
out = NEW_ORD(QKbo, prb, opt);
break;
case Options::TermOrdering::LAKBO:
out = NEW_ORD(Kernel::LiteralOrdering<Kernel::LAKBO>, prb, opt);
break;
case Options::TermOrdering::LPO:
out = new LPO(prb, opt);
break;
case Options::TermOrdering::ALL_INCOMPARABLE:
out = new AllIncomparableOrdering();
break;
default:
ASSERTION_VIOLATION;
}
if (opt.showSimplOrdering()) {
out->show(std::cout);
}
return out;
}
Ordering::Result Ordering::fromComparison(Comparison c)
{
switch(c) {
case Lib::GREATER:
return GREATER;
case Lib::EQUAL:
return EQUAL;
case Lib::LESS:
return LESS;
default:
ASSERTION_VIOLATION;
}
}
Comparison Ordering::intoComparison(Ordering::Result r)
{
switch(r) {
case Ordering::Result::GREATER: return Lib::GREATER;
case Ordering::Result::EQUAL: return Lib::EQUAL;
case Ordering::Result::LESS: return Lib::LESS;
default:
ASSERTION_VIOLATION;
}
}
const char* Ordering::resultToString(Result r)
{
switch(r) {
case GREATER:
return "GREATER";
case LESS:
return "LESS";
case EQUAL:
return "EQUAL";
case INCOMPARABLE:
return "INCOMPARABLE";
default:
ASSERTION_VIOLATION;
return 0;
}
}
void Ordering::removeNonMaximal(LiteralList*& lits) const
{
LiteralList** ptr1 = &lits;
while (*ptr1) {
LiteralList** ptr2 = &(*ptr1)->tailReference();
while (*ptr2 && *ptr1) {
Ordering::Result res = compare((*ptr1)->head(), (*ptr2)->head());
if (res == Ordering::GREATER || res == Ordering::EQUAL) {
LiteralList::pop(*ptr2);
continue;
} else if (res == Ordering::LESS) {
LiteralList::pop(*ptr1);
goto topLevelContinue;
}
ptr2 = &(*ptr2)->tailReference();
}
ptr1 = &(*ptr1)->tailReference();
topLevelContinue: ;
}
}
Ordering::Result Ordering::getEqualityArgumentOrder(Literal* eq) const
{
ASS(eq->isEquality());
if(tryGetGlobalOrdering()!=this) {
return compare(*eq->nthArgument(0), *eq->nthArgument(1));
}
Result res;
ArgumentOrderVals precomputed = static_cast<ArgumentOrderVals>(eq->getArgumentOrderValue());
if(precomputed!=AO_UNKNOWN) {
res = static_cast<Result>(precomputed);
ASS_EQ(res, compare(*eq->nthArgument(0), *eq->nthArgument(1)));
}
else {
res = compare(*eq->nthArgument(0), *eq->nthArgument(1));
eq->setArgumentOrderValue(static_cast<ArgumentOrderVals>(res));
}
return res;
}
TermOrderingDiagramUP Ordering::createTermOrderingDiagram(bool ground) const
{
return std::make_unique<TermOrderingDiagram>(*this, ground);
}
Ordering::Result PrecedenceOrdering::compare(Literal* l1, Literal* l2) const
{
ASS(l1->shared());
ASS(l2->shared());
if (l1 == l2) {
return EQUAL;
}
unsigned p1 = l1->functor();
unsigned p2 = l2->functor();
if( (l1->isNegative() ^ l2->isNegative()) && (p1==p2) &&
l1->weight()==l2->weight() && l1->numVarOccs()==l2->numVarOccs() && l1==env.sharing->tryGetOpposite(l2)) {
return l1->isNegative() ? LESS : GREATER;
}
if (p1 != p2) {
Comparison levComp=Int::compare(predicateLevel(p1),predicateLevel(p2));
if(levComp!=Lib::EQUAL) {
return fromComparison(levComp);
}
}
if(l1->isEquality()) {
ASS(l2->isEquality())
return compareEqualities(l1, l2);
}
if(_reverseLCM && (l1->isNegative() || l2->isNegative()) ) {
if(l1->isNegative() && l2->isNegative()) {
return reverse(comparePredicates(l1, l2));
}
else {
return l1->isNegative() ? LESS : GREATER;
}
}
return comparePredicates(l1, l2);
}
int PrecedenceOrdering::predicateLevel (unsigned pred) const
{
int basic=pred >= _predicates ? 1 : _predicateLevels[pred];
if(NONINTERPRETED_LEVEL_BOOST && !env.signature->getPredicate(pred)->interpreted()) {
ASS(!Signature::isEqualityPredicate(pred)); basic+=NONINTERPRETED_LEVEL_BOOST;
}
if(env.signature->predicateColored(pred)) {
ASS_NEQ(pred,0); return COLORED_LEVEL_BOOST*basic;
} else {
return basic;
}
}
int PrecedenceOrdering::predicatePrecedence (unsigned pred) const
{
int res=pred >= _predicates ? (int)pred : _predicatePrecedences[pred];
if(NONINTERPRETED_PRECEDENCE_BOOST) {
ASS_EQ(NONINTERPRETED_PRECEDENCE_BOOST & 1, 0);
bool intp = env.signature->getPredicate(pred)->interpreted();
res *= 2;
return intp ? res+1 : res+NONINTERPRETED_PRECEDENCE_BOOST;
}
return res;
}
Ordering::Result PrecedenceOrdering::comparePredicatePrecedences(unsigned p1, unsigned p2) const
{
static bool reverse = env.options->introducedSymbolPrecedence() == Shell::Options::IntroducedSymbolPrecedence::BOTTOM;
return fromComparison(Int::compare(
p1 >= _predicates ? (int)(reverse ? -p1 : p1) : _predicatePrecedences[p1],
p2 >= _predicates ? (int)(reverse ? -p2 : p2) : _predicatePrecedences[p2] ));
}
Ordering::Result PrecedenceOrdering::compareFunctionPrecedences(unsigned fun1, unsigned fun2) const
{
if (fun1 == fun2)
return EQUAL;
if (_qkboPrecedence) {
if (fun1 == IntTraits::oneF()) { return LESS; }
if (fun2 == IntTraits::oneF()) { return GREATER; }
if (fun1 == RatTraits::oneF()) { return LESS; }
if (fun2 == RatTraits::oneF()) { return GREATER; }
if (fun1 == RealTraits::oneF()) { return LESS; }
if (fun2 == RealTraits::oneF()) { return GREATER; }
} else {
if (theory->isInterpretedFunction(fun1, IntTraits::minusI)) { return GREATER; }
if (theory->isInterpretedFunction(fun2, IntTraits::minusI)) { return LESS; }
if (theory->isInterpretedFunction(fun1, RatTraits::minusI)) { return GREATER; }
if (theory->isInterpretedFunction(fun2, RatTraits::minusI)) { return LESS; }
if (theory->isInterpretedFunction(fun1, RealTraits::minusI)) { return GREATER; }
if (theory->isInterpretedFunction(fun2, RealTraits::minusI)) { return LESS; }
}
if (env.signature->isFoolConstantSymbol(false,fun1)) {
return LESS;
}
if (env.signature->isFoolConstantSymbol(false,fun2)) {
return GREATER;
}
if (env.signature->isFoolConstantSymbol(true,fun1)) {
return LESS;
}
if (env.signature->isFoolConstantSymbol(true,fun2)) {
return GREATER;
}
Signature::Symbol* s1=env.signature->getFunction(fun1);
Signature::Symbol* s2=env.signature->getFunction(fun2);
if(s1->termAlgebraCons() && !s2->termAlgebraCons()) {
return LESS;
}
if(!s1->termAlgebraCons() && s2->termAlgebraCons()) {
return GREATER;
}
if(!s1->interpreted()) {
if(s2->interpreted()) {
return GREATER;
}
static bool reverse = env.options->introducedSymbolPrecedence() == Shell::Options::IntroducedSymbolPrecedence::BOTTOM;
return fromComparison(Int::compare(
fun1 >= _functions ? (int)(reverse ? -fun1 : fun1) : _functionPrecedences[fun1],
fun2 >= _functions ? (int)(reverse ? -fun2 : fun2) : _functionPrecedences[fun2] ));
}
if(!s2->interpreted()) {
return LESS;
}
if(s1->arity()) {
if(!s2->arity()) {
return GREATER;
}
return fromComparison(Int::compare(fun1, fun2));
}
if(s2->arity()) {
return LESS;
}
if (!s1->interpretedNumber() || !s2->interpretedNumber()) {
return fromComparison(Int::compare(fun1, fun2));
}
Comparison cmpRes;
if(s1->integerConstant() && s2->integerConstant()) {
cmpRes = IntegerConstantType::comparePrecedence(s1->integerValue(), s2->integerValue());
}
else if(s1->rationalConstant() && s2->rationalConstant()) {
cmpRes = RationalConstantType::comparePrecedence(s1->rationalValue(), s2->rationalValue());
}
else if(s1->realConstant() && s2->realConstant()) {
cmpRes = RealConstantType::comparePrecedence(s1->realValue(), s2->realValue());
}
else if(s1->integerConstant()) {
ASS_REP(s2->rationalConstant() || s2->realConstant(), s2->name());
cmpRes = Lib::LESS;
}
else if(s2->integerConstant()) {
ASS_REP(s1->rationalConstant() || s1->realConstant(), s1->name());
cmpRes = Lib::GREATER;
}
else if(s1->rationalConstant()) {
ASS_REP(s2->realConstant(), s2->name());
cmpRes = Lib::LESS;
}
else if(s2->rationalConstant()) {
ASS_REP(s1->realConstant(), s1->name());
cmpRes = Lib::GREATER;
}
else {
ASSERTION_VIOLATION;
cmpRes = Int::compare(fun1, fun2);
}
return fromComparison(cmpRes);
}
Ordering::Result PrecedenceOrdering::compareTypeConPrecedences(unsigned tyc1, unsigned tyc2) const
{
auto size = _typeConPrecedences.size();
if (tyc1 == tyc2)
return EQUAL;
static bool reverse = env.options->introducedSymbolPrecedence() == Shell::Options::IntroducedSymbolPrecedence::BOTTOM;
return fromComparison(Int::compare(
tyc1 >= size ? (int)(reverse ? -tyc1 : tyc1) : _typeConPrecedences[tyc1],
tyc2 >= size ? (int)(reverse ? -tyc2 : tyc2) : _typeConPrecedences[tyc2] ));
}
Ordering::Result PrecedenceOrdering::comparePrecedences(const Term* t1, const Term* t2) const
{
if (t1->isSort() && t2->isSort()) {
return compareTypeConPrecedences(t1->functor(), t2->functor());
}
if (t1->isSort()) {
return LESS;
}
if (t2->isSort()) {
return GREATER;
}
return compareFunctionPrecedences(t1->functor(), t2->functor());
}
struct SymbolComparator {
SymbolType _symType;
bool _noTiebreak;
SymbolComparator(SymbolType symType, bool noTiebreak) : _symType(symType), _noTiebreak(noTiebreak) {}
Signature::Symbol* getSymbol(unsigned s) {
if(_symType == SymbolType::FUNC){
return env.signature->getFunction(s);
} else if (_symType == SymbolType::PRED){
return env.signature->getPredicate(s);
} else {
return env.signature->getTypeCon(s);
}
}
};
template<typename InnerComparator>
struct BoostWrapper : public SymbolComparator
{
BoostWrapper(SymbolType symType, bool noTiebreak) : SymbolComparator(symType,noTiebreak) {}
Comparison compare(unsigned s1, unsigned s2)
{
static Options::SymbolPrecedenceBoost boost = env.options->symbolPrecedenceBoost();
Comparison res = EQUAL;
auto sym1 = getSymbol(s1);
auto sym2 = getSymbol(s2);
bool u1 = sym1->inUnit();
bool u2 = sym2->inUnit();
bool g1 = sym1->inGoal();
bool g2 = sym2->inGoal();
bool i1 = sym1->introduced();
bool i2 = sym2->introduced();
switch(boost){
case Options::SymbolPrecedenceBoost::NONE:
break;
case Options::SymbolPrecedenceBoost::GOAL:
if(g1 && !g2){ res = GREATER; }
else if(!g1 && g2){ res = LESS; }
break;
case Options::SymbolPrecedenceBoost::UNITS:
if(u1 && !u2){ res = GREATER; }
else if(!u1 && u2){ res = LESS; }
break;
case Options::SymbolPrecedenceBoost::GOAL_THEN_UNITS:
if(g1 && !g2){ res = GREATER; }
else if(!g1 && g2){ res = LESS; }
else if(u1 && !u2){ res = GREATER; }
else if(!u1 && u2){ res = LESS; }
break;
case Options::SymbolPrecedenceBoost::NON_INTRO:
if (i1 && !i2) { res = LESS; }
else if (!i1 && i2) { res = GREATER; }
break;
case Options::SymbolPrecedenceBoost::INTRO:
if (!i1 && i2) { res = LESS; }
else if (i1 && !i2) { res = GREATER; }
break;
}
if(res==EQUAL){
res = InnerComparator(_symType,_noTiebreak).compare(s1,s2);
}
return res;
}
};
struct OccurenceTiebreak {
OccurenceTiebreak(SymbolType, bool noTiebreak) : _noTiebreak(noTiebreak) {}
Comparison compare(unsigned s1, unsigned s2) { return _noTiebreak ? Comparison::EQUAL : Int::compare(s1,s2); }
private:
bool _noTiebreak;
};
template<bool revert = false, typename InnerComparator = OccurenceTiebreak>
struct FreqComparator : public SymbolComparator
{
FreqComparator(SymbolType symType, bool noTiebreak) : SymbolComparator(symType,noTiebreak) {}
Comparison compare(unsigned s1, unsigned s2)
{
unsigned c1 = getSymbol(s1)->usageCnt();
unsigned c2 = getSymbol(s2)->usageCnt();
Comparison res = revert ? Int::compare(c1,c2) : Int::compare(c2,c1);
if(res==EQUAL){
res = InnerComparator(_symType,_noTiebreak).compare(s1,s2);
}
return res;
}
};
template<bool revert = false, typename InnerComparator = OccurenceTiebreak>
struct ArityComparator : public SymbolComparator
{
ArityComparator(SymbolType symType, bool noTiebreak) : SymbolComparator(symType,noTiebreak) {}
Comparison compare(unsigned u1, unsigned u2)
{
Comparison res= Int::compare(getSymbol(u1)->arity(),getSymbol(u2)->arity());
if (revert) {
res = Lib::revert(res);
}
if(res==EQUAL) {
res = InnerComparator(_symType,_noTiebreak).compare(u1,u2);
}
return res;
}
};
template<int spc, bool revert = false, typename InnerComparator = OccurenceTiebreak>
struct SpecAriFirstComparator : public SymbolComparator
{
SpecAriFirstComparator(SymbolType symType, bool noTiebreak) : SymbolComparator(symType,noTiebreak) {}
Comparison compare(unsigned s1, unsigned s2)
{
unsigned a1 = getSymbol(s1)->arity();
unsigned a2 = getSymbol(s2)->arity();
if (a1 == spc && a2 != spc) {
return revert ? LESS : GREATER;
} else if (a1 != spc && a2 == spc) {
return revert ? GREATER : LESS;
}
return InnerComparator(_symType,_noTiebreak).compare(s1,s2);
}
};
template<bool revert = false, typename InnerComparator = OccurenceTiebreak>
using UnaryFirstComparator = SpecAriFirstComparator<1,revert,InnerComparator>;
template<bool revert = false, typename InnerComparator = OccurenceTiebreak>
using ConstFirstComparator = SpecAriFirstComparator<0,revert,InnerComparator>;
static void loadPermutationFromString(DArray<unsigned>& p, const std::string& str) {
std::stringstream ss(str.c_str());
unsigned i = 0;
unsigned val;
while (ss >> val)
{
if (i >= p.size()) {
break;
}
if (val >= p.size()) {
break;
}
p[i++] = val;
if (ss.peek() == ',')
ss.ignore();
}
}
bool isPermutation(const DArray<int>& xs) {
DArray<int> cnts(xs.size());
cnts.init(xs.size(), 0);
for (unsigned i = 0; i < xs.size(); i++) {
cnts[xs[i]] += 1;
}
for (unsigned i = 0; i < xs.size(); i++) {
if (cnts[xs[i]] != 1) {
return false;
}
}
return true;
}
PrecedenceOrdering::PrecedenceOrdering(const DArray<int>& funcPrec,
const DArray<int>& typeConPrec,
const DArray<int>& predPrec,
const DArray<int>& predLevels,
bool reverseLCM,
bool qkboPrecedence)
: _predicates(predPrec.size()),
_functions(funcPrec.size()),
_predicateLevels(predLevels),
_predicatePrecedences(predPrec),
_functionPrecedences(funcPrec),
_typeConPrecedences(typeConPrec),
_reverseLCM(reverseLCM),
_qkboPrecedence(qkboPrecedence)
{
ASS_EQ(env.signature->predicates(), _predicates);
ASS_EQ(env.signature->functions(), _functions);
ASS(isPermutation(_functionPrecedences))
ASS(isPermutation(_predicatePrecedences))
checkLevelAssumptions(predLevels);
}
PrecedenceOrdering::PrecedenceOrdering(Problem& prb, const Options& opt, const DArray<int>& predPrec, bool qkboPrecedence)
: PrecedenceOrdering(
funcPrecFromOpts(prb,opt),
typeConPrecFromOpts(prb,opt),
predPrec,
predLevelsFromOptsAndPrec(prb,opt,predPrec),
opt.literalComparisonMode()==Shell::Options::LiteralComparisonMode::REVERSE,
qkboPrecedence
)
{
}
PrecedenceOrdering::PrecedenceOrdering(Problem& prb, const Options& opt, bool qkboPrecedence)
: PrecedenceOrdering(prb,opt,
[&]() {
prb.getProperty();
return predPrecFromOpts(prb, opt);
}(),
qkboPrecedence)
{
ASS_G(_predicates, 0);
}
static void sortAuxBySymbolPrecedence(DArray<unsigned>& aux, const Options& opt, SymbolType symType) {
bool noTiebreak = opt.shuffleInput();
if (noTiebreak) {
Shuffling::shuffleArray(aux,aux.size());
if (opt.symbolPrecedence() == Shell::Options::SymbolPrecedence::SCRAMBLE) {
return;
}
}
switch(opt.symbolPrecedence()) {
case Shell::Options::SymbolPrecedence::ARITY:
aux.sort(BoostWrapper<ArityComparator<>>(symType,noTiebreak));
break;
case Shell::Options::SymbolPrecedence::REVERSE_ARITY:
aux.sort(BoostWrapper<ArityComparator<true >>(symType,noTiebreak));
break;
case Shell::Options::SymbolPrecedence::UNARY_FIRST:
aux.sort(BoostWrapper<UnaryFirstComparator<false,ArityComparator<false,FreqComparator<>>>>(symType,noTiebreak));
break;
case Shell::Options::SymbolPrecedence::CONST_MAX:
aux.sort(BoostWrapper<ConstFirstComparator<false,ArityComparator<>>>(symType,noTiebreak));
break;
case Shell::Options::SymbolPrecedence::CONST_MIN:
aux.sort(BoostWrapper<ConstFirstComparator<true ,ArityComparator<true >>>(symType,noTiebreak));
break;
case Shell::Options::SymbolPrecedence::FREQUENCY:
case Shell::Options::SymbolPrecedence::WEIGHTED_FREQUENCY:
aux.sort(BoostWrapper<FreqComparator<>>(symType,noTiebreak));
break;
case Shell::Options::SymbolPrecedence::REVERSE_FREQUENCY:
case Shell::Options::SymbolPrecedence::REVERSE_WEIGHTED_FREQUENCY:
aux.sort(BoostWrapper<FreqComparator<true >>(symType,noTiebreak));
break;
case Shell::Options::SymbolPrecedence::UNARY_FREQ:
aux.sort(BoostWrapper<UnaryFirstComparator<false,FreqComparator<>>>(symType,noTiebreak));
break;
case Shell::Options::SymbolPrecedence::CONST_FREQ:
aux.sort(BoostWrapper<ConstFirstComparator<true ,FreqComparator<>>>(symType,noTiebreak));
break;
case Shell::Options::SymbolPrecedence::OCCURRENCE:
break;
case Shell::Options::SymbolPrecedence::SCRAMBLE:
Shuffling::shuffleArray(aux,aux.size());
break;
}
}
DArray<int> PrecedenceOrdering::typeConPrecFromOpts(Problem& prb, const Options& opt) {
unsigned nTypeCons = env.signature->typeCons();
DArray<unsigned> aux(nTypeCons);
if(nTypeCons) {
aux.initFromIterator(getRangeIterator(0u, nTypeCons), nTypeCons);
if (!opt.typeConPrecedence().empty()) {
std::string precedence;
ifstream precedence_file (opt.typeConPrecedence().c_str());
if (precedence_file.is_open() && getline(precedence_file, precedence)) {
loadPermutationFromString(aux,precedence);
precedence_file.close();
}
} else {
sortAuxBySymbolPrecedence(aux,opt,SymbolType::TYPE_CON);
}
}
DArray<int> typeConPrecedences(nTypeCons);
for(unsigned i=0;i<nTypeCons;i++) {
typeConPrecedences[aux[i]]=i;
}
return typeConPrecedences;
}
DArray<int> PrecedenceOrdering::funcPrecFromOpts(Problem& prb, const Options& opt) {
unsigned nFunctions = env.signature->functions();
DArray<unsigned> aux(nFunctions);
if(nFunctions) {
aux.initFromIterator(getRangeIterator(0u, nFunctions), nFunctions);
if (!opt.functionPrecedence().empty()) {
std::string precedence;
ifstream precedence_file (opt.functionPrecedence().c_str());
if (precedence_file.is_open() && getline(precedence_file, precedence)) {
loadPermutationFromString(aux,precedence);
precedence_file.close();
}
} else {
sortAuxBySymbolPrecedence(aux,opt,SymbolType::FUNC);
}
}
DArray<int> functionPrecedences(nFunctions);
for(unsigned i=0;i<nFunctions;i++) {
functionPrecedences[aux[i]]=i;
}
return functionPrecedences;
}
DArray<int> PrecedenceOrdering::predPrecFromOpts(Problem& prb, const Options& opt) {
unsigned nPredicates = env.signature->predicates();
DArray<unsigned> aux(nPredicates);
aux.initFromIterator(getRangeIterator(0u, nPredicates), nPredicates);
if (!opt.predicatePrecedence().empty()) {
std::string precedence;
ifstream precedence_file (opt.predicatePrecedence().c_str());
if (precedence_file.is_open() && getline(precedence_file, precedence)) {
loadPermutationFromString(aux,precedence);
precedence_file.close();
}
} else {
sortAuxBySymbolPrecedence(aux,opt,SymbolType::PRED);
}
DArray<int> predicatePrecedences(nPredicates);
for(unsigned i=0;i<nPredicates;i++) {
predicatePrecedences[aux[i]]=i;
}
return predicatePrecedences;
}
DArray<int> PrecedenceOrdering::predLevelsFromOptsAndPrec(Problem& prb, const Options& opt, const DArray<int>& predicatePrecedences) {
unsigned nPredicates = env.signature->predicates();
DArray<int> predicateLevels(nPredicates);
switch(opt.literalComparisonMode()) {
case Shell::Options::LiteralComparisonMode::STANDARD:
predicateLevels.init(nPredicates, PredLevels::MIN_USER_DEF);
break;
case Shell::Options::LiteralComparisonMode::PREDICATE:
case Shell::Options::LiteralComparisonMode::REVERSE:
for(unsigned i=1;i<nPredicates;i++) {
predicateLevels[i] = predicatePrecedences[i] + PredLevels::MIN_USER_DEF;
}
break;
}
predicateLevels[0] = PredLevels::EQ;
if (env.predicateSineLevels) {
unsigned bound = env.maxSineLevel; bool reverse = (opt.sineToPredLevels() == Options::PredicateSineLevels::ON);
for(unsigned i=1;i<nPredicates;i++) { unsigned level;
if (!env.predicateSineLevels->find(i,level)) {
level = bound;
}
predicateLevels[i] = (reverse ? (bound - level) : level) + PredLevels::MIN_USER_DEF;
}
}
for(unsigned i=1;i<nPredicates;i++) {
Signature::Symbol* predSym = env.signature->getPredicate(i);
if(predSym->label()) {
predicateLevels[i]=-1;
}
else if(predSym->equalityProxy()) {
predicateLevels[i] = nPredicates + PredLevels::MIN_USER_DEF+ 1;
}
}
checkLevelAssumptions(predicateLevels);
return predicateLevels;
}
void PrecedenceOrdering::checkLevelAssumptions(DArray<int> const& levels)
{
#if VDEBUG
for (unsigned i = 0; i < levels.size(); i++) {
if (theory->isInterpretedPredicate(i)) {
auto itp = theory->interpretPredicate(i);
if (itp == Kernel::Theory::EQUAL) {
ASS_EQ(levels[i], PredLevels::EQ);
} else if (theory->isInequality(itp)) {
} else {
ASS(levels[i] >= PredLevels::MIN_USER_DEF || levels[i] < 0)
}
}
}
#endif }
void PrecedenceOrdering::show(std::ostream& out) const
{
auto _show = [&](const char* precKind, unsigned cntFunctors, auto getSymbol, auto compareFunctors)
{
out << "% " << precKind << " precedences, smallest symbols first (line format: `<name> <arity>`) " << std::endl;
out << "% ===== begin of " << precKind << " precedences ===== " << std::endl;
DArray<unsigned> functors;
functors.initFromIterator(getRangeIterator(0u, cntFunctors), cntFunctors);
functors.sort(closureComparator(compareFunctors));
for (unsigned i = 0; i < cntFunctors; i++) {
auto sym = getSymbol(functors[i]);
out << "% " << sym->name() << " " << sym->arity() << std::endl;
}
out << "% ===== end of " << precKind << " precedences ===== " << std::endl;
out << "%" << std::endl;
};
_show("type constructor",
env.signature->typeCons(),
[](unsigned f) { return env.signature->getTypeCon(f); },
[&](unsigned l, unsigned r){ return intoComparison(compareTypeConPrecedences(l,r)); });
_show("function",
env.signature->functions(),
[](unsigned f) { return env.signature->getFunction(f); },
[&](unsigned l, unsigned r){ return intoComparison(compareFunctionPrecedences(l,r)); }
);
_show("predicate",
env.signature->predicates(),
[](unsigned f) { return env.signature->getPredicate(f); },
[&](unsigned l, unsigned r) { return intoComparison(comparePredicatePrecedences(l,r)); });
{
out << "% Predicate levels (line format: `<name> <arity> <level>`)" << std::endl;
out << "% ===== begin of predicate levels ===== " << std::endl;
DArray<unsigned> functors;
functors.initFromIterator(getRangeIterator(0u,env.signature->predicates()),env.signature->predicates());
functors.sort(closureComparator([&](unsigned l, unsigned r) { return Int::compare(predicateLevel(l), predicateLevel(r)); }));
for (unsigned i = 0; i < functors.size(); i++) {
auto sym = env.signature->getPredicate(i);
out << "% " << sym->name() << " " << sym->arity() << " " << predicateLevel(i) << std::endl;
}
out << "% ===== end of predicate levels ===== " << std::endl;
}
out << "%" << std::endl;
showConcrete(out);
}
DArray<int> PrecedenceOrdering::testLevels()
{
DArray<int> levels(env.signature->predicates());
for (unsigned i = 0; i < levels.size(); i++) {
if (theory->isInterpretedPredicate(i)) {
auto itp = theory->interpretPredicate(i);
if (itp == Kernel::Theory::EQUAL) {
levels[i] = PredLevels::EQ;
} else if (theory->isInequality(itp)) {
levels[i] = PredLevels::INEQ;
} else {
levels[i] = PredLevels::MIN_USER_DEF;
}
}
}
return levels;
}