#include "Lib/DHMultiset.hpp"
#include "Lib/Environment.hpp"
#include "Lib/Metaiterators.hpp"
#include "Debug/TimeProfiling.hpp"
#include "Lib/VirtualIterator.hpp"
#include "Kernel/Clause.hpp"
#include "Kernel/ColorHelper.hpp"
#include "Kernel/EqHelper.hpp"
#include "Kernel/Inference.hpp"
#include "Kernel/Ordering.hpp"
#include "Kernel/Term.hpp"
#include "Indexing/Index.hpp"
#include "Indexing/TermIndex.hpp"
#include "Debug/TimeProfiling.hpp"
#include "Saturation/SaturationAlgorithm.hpp"
#include "Shell/Options.hpp"
#include "Shell/Statistics.hpp"
#include "BackwardDemodulation.hpp"
namespace Inferences {
using namespace std;
using namespace Lib;
using namespace Kernel;
using namespace Indexing;
using namespace Saturation;
void BackwardDemodulation::attach(SaturationAlgorithm* salg)
{
BackwardSimplificationEngine::attach(salg);
_index = salg->getSimplifyingIndex<DemodulationSubtermIndex>();
_helper = DemodulationHelper(getOptions(), &_salg->getOrdering());
}
void BackwardDemodulation::detach()
{
_index = nullptr;
BackwardSimplificationEngine::detach();
}
struct BackwardDemodulation::RemovedIsNonzeroFn
{
bool operator() (BwSimplificationRecord arg)
{
return arg.toRemove!=0;
}
};
struct BackwardDemodulation::RewritableClausesFn
{
RewritableClausesFn(DemodulationSubtermIndex* index) : _index(index) {}
VirtualIterator<pair<TypedTermList,QueryRes<ResultSubstitutionSP, TermLiteralClause>> > operator() (TypedTermList lhs)
{
return pvi( pushPairIntoRightIterator(lhs, _index->getInstances(lhs, true)) );
}
private:
DemodulationSubtermIndex* _index;
};
namespace {
struct Applicator : SubstApplicator {
Applicator(ResultSubstitution* subst) : subst(subst) {}
TermList operator()(unsigned v) const override {
return subst->applyToBoundQuery(TermList(v,false));
}
ResultSubstitution* subst;
};
}
struct BackwardDemodulation::ResultFn
{
typedef DHMultiset<Clause*> ClauseSet;
ResultFn(Clause* cl, BackwardDemodulation& parent, const DemodulationHelper& helper)
: _cl(cl), _helper(helper), _ordering(parent._salg->getOrdering())
{
ASS_EQ(_cl->length(),1);
_eqLit=(*_cl)[0];
_removed=SmartPtr<ClauseSet>(new ClauseSet());
}
BwSimplificationRecord operator() (pair<TermList,QueryRes<ResultSubstitutionSP, TermLiteralClause>> arg)
{
auto qr=arg.second;
if( !ColorHelper::compatible(_cl->color(), qr.data->clause->color()) ) {
return BwSimplificationRecord(0);
}
if(_cl==qr.data->clause || _removed->find(qr.data->clause)) {
return BwSimplificationRecord(0);
}
TermList lhs=arg.first;
TermList rhs=EqHelper::getOtherEqualitySide(_eqLit, lhs);
auto subs = qr.unifier;
ASS(subs->isIdentityOnResultWhenQueryBound());
Applicator appl(subs.ptr());
TermList lhsS=qr.data->term;
if (_ordering.compareUnidirectional(AppliedTerm(lhsS), AppliedTerm(rhs,&appl,true))!=Ordering::GREATER) {
return BwSimplificationRecord(0);
}
TermList rhsS=subs->applyToBoundQuery(rhs);
if (_helper.redundancyCheckNeededForPremise(qr.data->clause,qr.data->literal,lhsS) &&
!_helper.isPremiseRedundant(qr.data->clause,qr.data->literal,lhsS,rhsS,lhs,&appl))
{
return BwSimplificationRecord(0);
}
Literal* resLit=EqHelper::replace(qr.data->literal,lhsS,rhsS);
if(EqHelper::isEqTautology(resLit)) {
env.statistics->backwardDemodulationsToEqTaut++;
_removed->insert(qr.data->clause);
return BwSimplificationRecord(qr.data->clause);
}
unsigned cLen=qr.data->clause->length();
RStack<Literal*> resLits;
resLits->push(resLit);
for(unsigned i=0;i<cLen;i++) {
Literal* curr=(*qr.data->clause)[i];
if(curr!=qr.data->literal) {
resLits->push(curr);
}
}
_removed->insert(qr.data->clause);
Clause *replacement = Clause::fromStack(
*resLits,
SimplifyingInference2(InferenceRule::BACKWARD_DEMODULATION, qr.data->clause, _cl)
);
if(env.options->proofExtra() == Options::ProofExtra::FULL)
env.proofExtra.insert(replacement, new BackwardDemodulationExtra(lhs, lhsS));
return BwSimplificationRecord(qr.data->clause, replacement);
}
private:
Literal* _eqLit;
Clause* _cl;
SmartPtr<ClauseSet> _removed;
const DemodulationHelper& _helper;
Ordering& _ordering;
};
void BackwardDemodulation::perform(Clause* cl,
BwSimplificationRecordIterator& simplifications)
{
TIME_TRACE("backward demodulation");
if(cl->length()!=1 || !(*cl)[0]->isEquality() || !(*cl)[0]->isPositive() ) {
simplifications=BwSimplificationRecordIterator::getEmpty();
return;
}
Literal* lit=(*cl)[0];
BwSimplificationRecordIterator replacementIterator=
pvi( getFilteredIterator(
getMappingIterator(
getMapAndFlattenIterator(
EqHelper::getDemodulationLHSIterator(lit,
_salg->getOptions().backwardDemodulation() == Options::Demodulation::PREORDERED,
_salg->getOrdering()).first,
RewritableClausesFn(_index.get())),
ResultFn(cl, *this, _helper)),
RemovedIsNonzeroFn()) );
simplifications=getPersistentIterator(std::move(replacementIterator));
}
}