#include "Lib/Environment.hpp"
#include "Kernel/Clause.hpp"
#include "Kernel/Inference.hpp"
#include "Kernel/Signature.hpp"
#include "DistinctEqualitySimplifier.hpp"
namespace Inferences
{
Clause* DistinctEqualitySimplifier::simplify(Clause* cl)
{
if(!canSimplify(cl)) {
return cl;
}
static LiteralStack lits;
static Stack<Unit*> prems;
prems.reset();
lits.reset();
unsigned clen = cl->length();
for(unsigned i=0; i<clen; i++) {
Literal* lit = (*cl)[i];
unsigned grp;
if(!lit->isEquality() || !mustBeDistinct(*lit->nthArgument(0),*lit->nthArgument(1), grp)) {
lits.push(lit);
continue;
}
if(lit->isNegative()) {
return 0;
}
Unit* prem = env.signature->getDistinctGroupPremise(grp);
if(prem) {
prems.push(prem);
}
}
ASS_L(lits.size(), clen);
prems.push(cl);
UnitList* premLst = 0;
UnitList::pushFromIterator(Stack<Unit*>::Iterator(prems), premLst);
ASS(premLst);
Clause* res = Clause::fromStack(lits,
SimplifyingInferenceMany(InferenceRule::DISTINCT_EQUALITY_REMOVAL, premLst));
return res;
}
bool DistinctEqualitySimplifier::mustBeDistinct(TermList t1, TermList t2)
{
unsigned aux;
return mustBeDistinct(t1, t2, aux);
}
bool DistinctEqualitySimplifier::mustBeDistinct(TermList t1, TermList t2, unsigned& grp)
{
if(!t1.isTerm() || t1.term()->arity()!=0 || !t2.isTerm() || t2.term()->arity()!=0 || t1.term() == t2.term()) {
return false;
}
unsigned fn1 = t1.term()->functor();
unsigned fn2 = t2.term()->functor();
const List<unsigned>* dlst1 = env.signature->getFunction(fn1)->distinctGroups();
if(!dlst1) {
return false;
}
const List<unsigned>* dlst2 = env.signature->getFunction(fn2)->distinctGroups();
if(!dlst2) {
return false;
}
List<unsigned>::Iterator dl1it(dlst1);
while(dl1it.hasNext()) {
unsigned candGrp = dl1it.next(); if(List<unsigned>::member(candGrp, dlst2)) {
grp = candGrp;
return true;
}
}
return false;
}
bool DistinctEqualitySimplifier::canSimplify(Clause* cl)
{
unsigned clen = cl->length();
for(unsigned i=0; i<clen; i++) {
Literal* lit = (*cl)[i];
if(lit->isEquality() && mustBeDistinct(*lit->nthArgument(0),*lit->nthArgument(1))) {
return true;
}
}
return false;
}
}