#include "Lib/DArray.hpp"
#include "Lib/Metaiterators.hpp"
#include "Lib/Stack.hpp"
#include "Indexing/LiteralIndex.hpp"
#include "Indexing/TermIndex.hpp"
#include "Saturation/SaturationAlgorithm.hpp"
#include "EqHelper.hpp"
#include "LiteralComparators.hpp"
#include "Matcher.hpp"
#include "Ordering.hpp"
#include "RobSubstitution.hpp"
#include "LookaheadLiteralSelector.hpp"
namespace Kernel
{
using namespace std;
using namespace Lib;
using namespace Indexing;
using namespace Saturation;
struct LookaheadLiteralSelector::GenIteratorIterator
{
using TermIndex = Indexing::TermIndex<TermLiteralClause>;
DECL_ELEMENT_TYPE(VirtualIterator<std::tuple<>>);
GenIteratorIterator(Literal* lit, LookaheadLiteralSelector& parent) : stage(0), lit(lit), prepared(false), _parent(parent) {}
bool hasNext()
{
if(prepared) {
return true;
}
SaturationAlgorithm* salg=SaturationAlgorithm::tryGetInstance();
if(!salg) {
static bool errAnnounced = false;
if(!errAnnounced) {
errAnnounced = true;
std::cout<<"Using LookaheadLiteralSelector without having an SaturationAlgorithm object\n";
}
prepared=false;
return false;
}
start:
switch(stage) {
case 0: {
auto gli = salg->tryGetGeneratingIndex<BinaryResolutionIndex>();
if(!gli) { stage++; goto start; }
nextIt=pvi( dropElementType(gli->getUnifications(lit,true,false)) );
break;
}
case 1: {
auto bsi = salg->tryGetGeneratingIndex<SuperpositionSubtermIndex>();
if(!bsi) { stage++; goto start; }
nextIt=pvi( getMapAndFlattenIterator(
EqHelper::getLHSIterator(lit, _parent._ord),
TermUnificationRetriever(bsi.get())) );
break;
}
case 2: {
auto fsi=salg->tryGetGeneratingIndex<SuperpositionLHSIndex>();
if(!fsi) { stage++; goto start; }
nextIt=pvi( getMapAndFlattenIterator(
EqHelper::getSubtermIterator(lit, _parent._ord), TermUnificationRetriever(fsi.get())) );
break;
}
case 3: {
bool haveEqRes=false;
if(lit->isNegative() && lit->isEquality()) {
RobSubstitution rs;
if(rs.unify(*lit->nthArgument(0), 0, *lit->nthArgument(1), 0)) {
haveEqRes=true;
nextIt=pvi( dropElementType(getSingletonIterator(0)) );
}
}
if(!haveEqRes) {
stage++;
goto start;
}
break;
}
default:
ASSERTION_VIOLATION;
case 4: {
prepared=false;
return false;
}
}
prepared=true;
return true;
}
VirtualIterator<std::tuple<>> next()
{
if(!prepared) {
ALWAYS(hasNext());
}
ASS(prepared);
prepared=false;
stage++;
return std::move(nextIt);
}
private:
struct TermUnificationRetriever
{
TermUnificationRetriever(TermIndex* index) : _index(index) {}
VirtualIterator<std::tuple<>> operator()(TypedTermList trm)
{
return pvi(dropElementType(_index->getUnifications(trm, false)));
}
private:
TermIndex* _index;
};
int stage;
Literal* lit;
bool prepared;
VirtualIterator<std::tuple<>> nextIt;
LookaheadLiteralSelector& _parent;
};
VirtualIterator<std::tuple<>> LookaheadLiteralSelector::getGeneraingInferenceIterator(Literal* lit)
{
return pvi( getFlattenedIterator(GenIteratorIterator(lit, *this)) );
}
Literal* LookaheadLiteralSelector::pickTheBest(Literal** lits, unsigned cnt)
{
ASS_G(cnt,1);
static DArray<VirtualIterator<std::tuple<>> > runifs; runifs.ensure(cnt);
for(unsigned i=0;i<cnt;i++) {
runifs[i]=getGeneraingInferenceIterator(lits[i]);
}
static Stack<Literal*> candidates;
candidates.reset();
do {
for(unsigned i=0;i<cnt;i++) {
if(runifs[i].hasNext()) {
runifs[i].next();
}
else {
candidates.push(lits[i]);
}
}
} while(candidates.isEmpty());
using namespace LiteralComparators;
typedef Composite<ColoredFirst,
Composite<NoPositiveEquality,
Composite<LeastTopLevelVariables,
Composite<LeastDistinctVariables, LexComparator> > > > LitComparator;
Literal* res=candidates.pop();
if(candidates.isNonEmpty()) {
LitComparator comp;
while(candidates.isNonEmpty()) {
Literal* lit=candidates.pop();
if(comp.compare(res, lit)==LESS) {
res=lit;
}
}
}
for(unsigned i=0;i<cnt;i++) {
runifs[i].~VirtualIterator(); }
return res;
}
void LookaheadLiteralSelector::removeVariants(LiteralStack& lits)
{
size_t cnt=lits.size();
for(size_t i=0;i<cnt-1;i++) {
for(size_t j=i+1;j<cnt;j++) {
if(MatchingUtils::isVariant(lits[i], lits[j], false)) {
cnt--;
swap(lits[j], lits[cnt]);
lits.pop();
}
}
}
}
void LookaheadLiteralSelector::doSelection(Clause* c, unsigned eligible)
{
if(_startupSelector){
_startupSelector->select(c,eligible);
_skipped++;
if(_skipped == _delay){
delete _startupSelector;
_startupSelector=0;
}
return;
}
LiteralList* maximals=0;
Literal* singleSel=0;
static LiteralStack selectable;
selectable.reset();
if(_completeSelection) {
for(int li=((int)eligible)-1; li>=0; li--) {
Literal* lit=(*c)[li];
if(isNegativeForSelection(lit)) {
selectable.push(lit);
}
}
for(int li=((int)eligible)-1; li>=0; li--) {
Literal* lit=(*c)[li];
LiteralList::push(lit,maximals);
}
_ord.removeNonMaximal(maximals);
ASS(maximals);
if(selectable.isEmpty()) {
goto selection_done;
}
removeVariants(selectable);
if(!maximals->tail() && isPositiveForSelection(maximals->head())) {
selectable.push(maximals->head());
}
}
else {
selectable.loadFromIterator(arrayIter(*c, eligible));
removeVariants(selectable);
}
if(selectable.size()==1) {
singleSel=selectable.pop();
goto selection_done;
}
ASS_G(selectable.size(),1);
singleSel=pickTheBest(selectable.begin(), selectable.size());
selection_done:
if(singleSel) {
LiteralList::destroy(maximals);
maximals=0;
LiteralList::push(singleSel,maximals);
}
unsigned selCnt=0;
for(unsigned li=0; maximals; li++) {
ASS_L(li,eligible);
if((*c)[li]==maximals->head()) {
if(li!=selCnt) {
swap((*c)[li], (*c)[selCnt]);
}
selCnt++;
LiteralList::pop(maximals);
}
}
ASS(selCnt>0);
c->setSelected(selCnt);
ensureSomeColoredSelected(c, eligible);
}
}