#include "Lib/Environment.hpp"
#include "Kernel/Clause.hpp"
#include "Kernel/FormulaUnit.hpp"
#include "Kernel/Problem.hpp"
#include "Kernel/Term.hpp"
#include "Kernel/SubformulaIterator.hpp"
#include "Kernel/Unit.hpp"
#include "Normalisation.hpp"
using namespace Kernel;
using namespace Shell;
Normalisation::Normalisation ()
: _counter(*env.signature)
{
}
void Normalisation::normalise(Problem& prb)
{
UnitList* units = prb.units();
units = normalise(units);
prb.units() = units;
}
UnitList* Normalisation::normalise (UnitList* units)
{
if (UnitList::isEmpty(units)) {
return units;
}
_counter.count(units,1);
unsigned length = UnitList::length(units);
std::vector<Unit *> srt;
UnitList::Iterator us(units);
while (us.hasNext()) {
Unit* unit = us.next();
normalise(unit);
srt.push_back(unit);
}
sort(
srt.begin(), srt.end(),
[this](Unit *u1, Unit *u2) -> bool { return lessThan(u1, u2); }
);
UnitList* result = UnitList::empty();
for (int k = length-1;k >= 0;k--) {
result = new UnitList(srt[k],result);
}
UnitList::destroy(units);
return result;
}
void Normalisation::normalise (Unit* unit)
{
if (! unit->isClause()) {
return;
}
Clause& clause = *static_cast<Clause*>(unit);
int length = clause.length();
if (length <= 1) {
return;
}
std::vector<Literal *> srt;
for (int i = 0;i < length;i++) {
srt.push_back(clause[i]);
}
sort(
srt.begin(), srt.end(),
[this](Literal *l, Literal *k) -> bool { return lessThan(l, k); }
);
for (int i=0;i < length;i++) {
clause[i] = srt[i];
}
clause.notifyLiteralReorder();
return;
}
bool Normalisation::lessThan (Unit* u1, Unit* u2)
{
switch (compare(static_cast<int>(u1->inputType()),static_cast<int>(u2->inputType()))) {
case LESS:
return false;
case EQUAL:
break;
case GREATER:
return true;
}
if (u1->isClause()) {
if (u2->isClause()) {
return lessThan(static_cast<Clause*>(u1),
static_cast<Clause*>(u2));
}
return true;
}
if (u2->isClause()) {
return false;
}
return lessThan(static_cast<FormulaUnit*>(u1)->formula(),
static_cast<FormulaUnit*>(u2)->formula());
}
bool Normalisation::lessThan(Clause* cl1, Clause* cl2)
{
if(cl1->length()!=cl2->length()) {
return cl1->length() < cl2->length();
}
unsigned clen=cl1->length();
for(unsigned i=0;i<clen;i++) {
Comparison cmp=compare( (*cl1)[i], (*cl2)[i] );
if(cmp!=EQUAL) {
return cmp==LESS;
}
}
return false;
}
bool Normalisation::lessThan (Formula* f1, Formula* f2)
{
return compare(f1,f2) == LESS;
}
bool Normalisation::lessThan (Literal* l1, Literal* l2)
{
return compare(l1,l2) == LESS;
}
Comparison Normalisation::compare (Formula* fm1, Formula* fm2)
{
SubformulaIterator sf1(fm1);
SubformulaIterator sf2(fm2);
while (sf1.hasNext()) {
if (! sf2.hasNext()) {
return GREATER;
}
Formula* f1 = sf1.next();
Formula* f2 = sf2.next();
Comparison comp = compare ((int)f1->connective(),
(int)f2->connective ());
if (comp != EQUAL) {
return comp;
}
switch (f1->connective()) {
case LITERAL:
comp = compare(f1->literal(),f2->literal());
if (comp != EQUAL) {
return comp;
}
break;
case BOOL_TERM: {
TermList ts1 = f1->getBooleanTerm();
TermList ts2 = f2->getBooleanTerm();
comp = compare(ts1, ts2);
if (comp != EQUAL) {
return comp;
}
}
break;
case FORALL:
case EXISTS:
comp = compare((int) VList::length(f1->vars()),
(int) VList::length(f2->vars()));
if (comp != EQUAL) {
return comp;
}
break;
default:
break;
}
}
return sf2.hasNext() ? LESS : EQUAL;
}
Comparison Normalisation::compare (Literal* l1, Literal* l2)
{
if (l1 == l2) {
return EQUAL;
}
if (!l1->shared() && l2->shared()) {
return GREATER;
}
if (l1->shared() && !l2->shared()) {
return LESS;
}
Comparison comp;
if (l1->shared() && l2->shared()) {
comp = compare((int)l1->weight(),(int)l2->weight());
if (comp != EQUAL) {
return comp;
}
}
if (l1->isPositive()) {
if (! l2->isPositive()) {
return GREATER;
}
}
else { if (l2->isPositive()) {
return LESS;
}
}
if (l1->isEquality()) {
if (! l2->isEquality()) {
return LESS;
}
}
else if (l2->isEquality()) {
return GREATER;
}
int p1 = l1->functor();
int p2 = l2->functor();
if (p1 != p2) {
comp = compare((int)l1->arity(),(int)l2->arity());
if (comp != EQUAL) {
return comp;
}
if (l1->shared() && l2->shared()) {
comp = compare((int)l1->numVarOccs(),(int)l2->numVarOccs());
if (comp != EQUAL) {
return comp;
}
}
comp = compare(_counter.getPred(p1).pocc(),
_counter.getPred(p2).pocc());
if (comp != EQUAL) {
return comp;
}
comp = compare(_counter.getPred(p1).nocc(),
_counter.getPred(p2).nocc());
if (comp != EQUAL) {
return comp;
}
comp = compare(_counter.getPred(p1).docc(),
_counter.getPred(p2).docc());
if (comp != EQUAL) {
return comp;
}
}
for(unsigned i = 0; i < l1->arity(); i++){
TermList* ts1 = l1->nthArgument(i);
TermList* ts2 = l2->nthArgument(i);
comp = compare(*ts1,*ts2);
if (comp != EQUAL) {
return comp;
}
}
return EQUAL;
}
Comparison Normalisation::compare(TermList ts1, TermList ts2)
{
if (ts1.isVar() && !ts2.isVar()) {
return LESS;
}
if (!ts1.isVar() && ts2.isVar()) {
return GREATER;
}
if(ts1.isVar() && ts2.isVar()){
return EQUAL;
}
Term* t1 = ts1.term();
Term* t2 = ts2.term();
return compare(t1,t2);
}
Comparison Normalisation::compare(Term* t1, Term* t2)
{
if (t1 == t2) {
return EQUAL;
}
Comparison comp;
if (!t1->isSpecial() && t2->isSpecial()) {
return GREATER;
}
if (t1->isSpecial() && !t2->isSpecial()) {
return LESS;
}
if(!t1->isSort() && t2->isSort()){
return GREATER;
}
if(t1->isSort() && !t2->isSort()){
return LESS;
}
if (t1->isSpecial() && t2->isSpecial()) {
comp = compare (unsigned(t1->specialFunctor()), unsigned(t2->specialFunctor()));
if (comp != EQUAL) {
return comp;
}
switch (t1->specialFunctor()) {
case SpecialFunctor::FORMULA:
return compare(t1->getSpecialData()->getFormula(), t2->getSpecialData()->getFormula());
case SpecialFunctor::ITE:
comp = compare(t1->getSpecialData()->getITECondition(), t2->getSpecialData()->getITECondition());
if (comp != EQUAL) {
return comp;
}
break;
case SpecialFunctor::LET: {
comp = compare(t1->getSpecialData()->getLetBinding(),
t2->getSpecialData()->getLetBinding());
if (comp != EQUAL) {
return comp;
}
break; }
case SpecialFunctor::LAMBDA: {
comp = compare((int) VList::length(t1->getSpecialData()->getLambdaVars()),
(int) VList::length(t2->getSpecialData()->getLambdaVars()));
if (comp != EQUAL) {
return comp;
}
TermList b1 = t1->getSpecialData()->getLambdaExp();
TermList b2 = t2->getSpecialData()->getLambdaExp();
comp = compare(b1, b2);
return comp;
}
case SpecialFunctor::MATCH: {
break; }
}
}
if (!t1->shared() && t2->shared()) {
return GREATER;
}
if (t1->shared() && !t2->shared()) {
return LESS;
}
if (t1->shared() && t2->shared()) {
comp = compare((int)t1->weight(),(int)t2->weight());
if (comp != EQUAL) {
return comp;
}
comp = compare((int)t1->numVarOccs(),(int)t2->numVarOccs());
if (comp != EQUAL) {
return comp;
}
}
int f1 = t1->functor();
int f2 = t2->functor();
if (f1 != f2) {
comp = compare((int)t1->arity(),(int)t2->arity());
if (comp != EQUAL) {
return comp;
}
int countf1 = t1->isSort() ? _counter.getTypeCon(f1).occ() : _counter.getFun(f1).occ();
int countf2 = t1->isSort() ? _counter.getTypeCon(f2).occ() : _counter.getFun(f2).occ();
comp = compare(countf1, countf2);
if (comp != EQUAL) {
return comp;
}
}
for(unsigned i = 0; i < t1->arity(); i++){
TermList* ts1 = t1->nthArgument(i);
TermList* ts2 = t2->nthArgument(i);
comp = compare(*ts1,*ts2);
if (comp != EQUAL) {
return comp;
}
}
return EQUAL;
}