#include "Lib/Environment.hpp"
#include "Kernel/Clause.hpp"
#include "Kernel/FormulaUnit.hpp"
#include "Kernel/Inference.hpp"
#include "Kernel/Signature.hpp"
#include "SymElOutput.hpp"
namespace Saturation
{
using namespace std;
using namespace Lib;
using namespace Kernel;
SymElOutput::SymElOutput()
: _symElNextClauseNumber(0)
{
}
void SymElOutput::init(SaturationAlgorithm* sa)
{
_sa=sa;
}
void SymElOutput::onAllProcessed()
{
_symElRewrites.reset();
_symElColors.reset();
}
void SymElOutput::onInputClause(Clause* c)
{
checkForPreprocessorSymbolElimination(c);
}
void SymElOutput::onNonRedundantClause(Clause* c)
{
if(c->color()==COLOR_TRANSPARENT && !c->skip()) {
Clause* tgt=c;
Clause* src;
bool notFound=false;
do {
src=tgt;
if(!_symElRewrites.find(src, tgt)) {
ASS_EQ(src, c); notFound=true;
break;
}
} while(tgt);
if(!notFound) {
outputSymbolElimination(_symElColors.get(src), c);
}
}
}
void SymElOutput::onParenthood(Clause* cl, Clause* parent)
{
Color pcol=parent->color();
if(pcol!=COLOR_TRANSPARENT && cl->color()==COLOR_TRANSPARENT) {
onSymbolElimination(parent->color(), cl);
}
if(pcol==COLOR_TRANSPARENT && _symElRewrites.find(parent)) {
_symElRewrites.insert(cl, parent);
}
}
void SymElOutput::onSymbolElimination(Color eliminated,
Clause* c, bool nonRedundant)
{
ASS_EQ(c->color(),COLOR_TRANSPARENT);
if(!c->skip() && c->noSplits()) {
if(!_symElColors.insert(c,eliminated)) {
return;
}
if(nonRedundant) {
outputSymbolElimination(eliminated, c);
}
else {
_symElRewrites.insert(c,0);
}
}
}
void SymElOutput::outputSymbolElimination(Color eliminated, Clause* c)
{
ASS_EQ(c->color(),COLOR_TRANSPARENT);
ASS(!c->skip());
std::cout<<"%";
if(eliminated==COLOR_LEFT) {
std::cout<<"Left";
} else {
ASS_EQ(eliminated, COLOR_RIGHT);
std::cout<<"Right";
}
std::cout<<" symbol elimination"<<endl;
std::string cname = "inv"+Int::toString(_symElNextClauseNumber);
while(env.signature->isPredicateName(cname, 0)) {
_symElNextClauseNumber++;
cname = "inv"+Int::toString(_symElNextClauseNumber);
}
_printer.printAsClaim(cname, c);
_symElNextClauseNumber++;
}
void SymElOutput::checkForPreprocessorSymbolElimination(Clause* cl)
{
if(!env.colorUsed || cl->color()!=COLOR_TRANSPARENT || cl->skip()) {
return;
}
Color inputColor=COLOR_TRANSPARENT;
static DHMap<Unit*, Color> inputFormulaColors;
static Stack<Unit*> units;
units.reset();
units.push(cl);
while(units.isNonEmpty()) {
Unit* u=units.pop();
Inference::Iterator iit=u->inference().iterator();
if(!u->inference().hasNext(iit)) {
Color uCol;
if(u->isClause()) {
uCol=static_cast<Clause*>(u)->color();
} else if(!inputFormulaColors.find(u,uCol)){
uCol=static_cast<FormulaUnit*>(u)->getColor();
inputFormulaColors.insert(u,uCol);
}
if(uCol!=COLOR_TRANSPARENT) {
#if VDEBUG
inputColor=static_cast<Color>(inputColor|uCol);
ASS_NEQ(inputColor, COLOR_INVALID);
#else
inputColor=uCol;
break;
#endif
}
} else {
while(u->inference().hasNext(iit)) {
Unit* premUnit=u->inference().next(iit);
units.push(premUnit);
}
}
}
if(inputColor!=COLOR_TRANSPARENT) {
onSymbolElimination(inputColor, cl);
}
}
}