#include "TheoryFlattening.hpp"
#include "Lib/Environment.hpp"
#include "Kernel/Clause.hpp"
#include "Kernel/Inference.hpp"
#include "Kernel/Problem.hpp"
#include "Kernel/Signature.hpp"
#include "Kernel/SortHelper.hpp"
#include "Kernel/Term.hpp"
namespace Shell
{
using namespace std;
using namespace Lib;
using namespace Kernel;
TheoryFlattening::TheoryFlattening(bool rec, bool share) : _recursive(rec), _sharing(share) {
}
void TheoryFlattening::apply(Problem& prb)
{
if(apply(prb.units())) {
prb.invalidateProperty();
}
}
bool TheoryFlattening::apply(UnitList*& units)
{
bool modified = false;
UnitList* res=0;
UnitList::DelIterator uit(units);
while(uit.hasNext()) {
Clause* cl=static_cast<Clause*>(uit.next());
ASS(cl->isClause());
Clause* cln = apply(cl);
if(cl!=cln){
modified = true;
uit.del();
UnitList::push(cln, res);
}
}
ASS_EQ(modified, UnitList::isNonEmpty(res));
units=UnitList::concat(res, units);
return modified;
}
bool TheoryFlattening::apply(ClauseList*& clauses)
{
bool modified = false;
ClauseList* res=0;
ClauseList::DelIterator cit(clauses);
while(cit.hasNext()) {
Clause* cl=cit.next();
Clause* cln = apply(cl);
if(cl!=cln){
modified = true;
cit.del();
ClauseList::push(cln, res);
}
}
ASS_EQ(modified, ClauseList::isNonEmpty(res));
clauses=ClauseList::concat(res, clauses);
return modified;
}
Clause* TheoryFlattening::apply(Clause*& cl,Stack<Literal*>& target)
{
unsigned maxVar = 0;
VirtualIterator<unsigned> varIt = cl->getVariableIterator();
while (varIt.hasNext()) {
unsigned var = varIt.next();
if (var > maxVar) {
maxVar = var;
}
}
Stack<Literal*> result;
bool updated = false;
Stack<Literal*> lits;
for(int i= cl->length()-1; i>=0;i--){
Literal* lit = (*cl)[i];
if(target.isEmpty() || target.find(lit)){
lits.push(lit);
}
else{ result.push(lit); }
}
DHMap<Term*,unsigned> abstracted;
while(!lits.isEmpty()){
Literal* lit = lits.pop();
if(lit->arity()==0){
result.push(lit);
continue;
}
Stack<Literal*> newLits;
Literal* nlit = replaceTopTerms(lit,newLits,maxVar,abstracted);
if(nlit==lit){
ASS(newLits.isEmpty());
result.push(lit);
}
else{
updated=true;
if(_recursive){
lits.push(nlit);
lits.loadFromIterator(Stack<Literal*>::Iterator(newLits));
}
else{
result.push(nlit);
result.loadFromIterator(Stack<Literal*>::Iterator(newLits));
}
}
}
if(!updated){ return cl;}
Clause* rep = Clause::fromStack(result,SimplifyingInference1(InferenceRule::THEORY_FLATTENING,cl));
return rep;
}
Literal* TheoryFlattening::replaceTopTerms(Literal* lit, Stack<Literal*>& newLits,unsigned& maxVar,
DHMap<Term*,unsigned>& abstracted)
{
bool interpreted = theory->isInterpretedPredicate(lit->functor());
bool equalityWithNumber = false;
if(lit->isEquality()){
interpreted=false;
for(TermList* ts = lit->args(); ts->isNonEmpty(); ts = ts->next()){
if(ts->isTerm()
&& (
env.signature->getFunction(ts->term()->functor())->interpreted()
|| env.signature->getFunction(ts->term()->functor())->termAlgebraCons()
|| env.signature->getFunction(ts->term()->functor())->termAlgebraDest()
)
){
interpreted=true;
}
if(ts->isTerm() && theory->isInterpretedConstant(ts->term())){
equalityWithNumber = true;
}
}
}
bool updated = false;
Stack<TermList> args;
for(TermList* ts = lit->args(); ts->isNonEmpty(); ts = ts->next()){
if(ts->isVar() || ts->term()->isSort()){
args.push(*ts);
continue;
}
Term* t = ts->term();
if(
!equalityWithNumber &&
(interpreted !=
(env.signature->getFunction(t->functor())->interpreted()
|| env.signature->getFunction(ts->term()->functor())->termAlgebraCons()
|| env.signature->getFunction(ts->term()->functor())->termAlgebraDest()
)
)&&
!theory->isInterpretedConstant(t)
){
unsigned newVar;
bool create = false;
if(!(_sharing && abstracted.find(t,newVar))){
newVar = ++maxVar;
create=true;
}
args.push(TermList(newVar,false));
if(create){
TermList sort = SortHelper::getResultSort(t);
Literal* lit = Literal::createEquality(false,TermList(t),TermList(newVar,false),sort);
newLits.push(lit);
abstracted.insert(t,newVar);
}
updated=true;
}
else{
Term* tt = replaceTopTermsInTerm(t,newLits,maxVar,interpreted,abstracted);
if(tt!=t){ updated=true; }
args.push(TermList(tt));
}
}
if(!updated){ return lit;}
return Literal::create(lit,args.begin());
}
Term* TheoryFlattening::replaceTopTermsInTerm(Term* term, Stack<Literal*>& newLits,
unsigned& maxVar,bool interpreted,
DHMap<Term*,unsigned>& abstracted)
{
Stack<TermList> args;
bool updated=false;
for(TermList* ts = term->args(); ts->isNonEmpty(); ts = ts->next()){
if(ts->isVar() || ts->term()->isSort()){
args.push(*ts);
continue;
}
Term* t = ts->term();
bool interpretedStatus = env.signature->getFunction(t->functor())->interpreted();
if(!interpreted && interpretedStatus){
interpretedStatus = !theory->isInterpretedNumber(t);
}
if(interpretedStatus &&
theory->isPartiallyInterpretedFunction(t)
&& theory->partiallyDefinedFunctionUndefinedForArgs(t)){
interpretedStatus=false;
}
if(interpreted != interpretedStatus){
unsigned newVar;
bool create = false;
if(!(_sharing && abstracted.find(t,newVar))){
newVar = ++maxVar;
create=true;
}
args.push(TermList(newVar,false));
if(create){
TermList sort = SortHelper::getResultSort(t);
Literal* lit = Literal::createEquality(false,TermList(t),TermList(newVar,false),sort);
newLits.push(lit);
abstracted.insert(t,newVar);
}
updated=true;
}
else{
Term* tt = replaceTopTermsInTerm(t,newLits,maxVar,interpreted,abstracted);
if(tt!=t){ updated=true; }
args.push(TermList(tt));
}
}
if(!updated) return term;
else return Term::create(term->functor(),term->arity(),args.begin());
}
}