#include <algorithm>
#include "Term.hpp"
#include "Clause.hpp"
#include "ELiteralSelector.hpp"
using namespace std;
using namespace Lib;
using namespace Kernel;
LiteralList* ELiteralSelector::getMaximalsInOrder(Clause* c, unsigned eligible)
{
LiteralList* res = LiteralList::empty();
for(int li=((int)eligible)-1; li>=0; li--) {
LiteralList::push((*c)[li],res);
}
_ord.removeNonMaximal(res);
return res;
}
unsigned ELiteralSelector::lit_standard_diff(Literal* lit)
{
if (lit->isEquality()) {
unsigned w0 = lit->nthArgument(0)->weight();
unsigned w1 = lit->nthArgument(1)->weight();
return max(w0,w1)-min(w0,w1);
} else {
return lit->weight() - 1;
}
}
unsigned ELiteralSelector::lit_sel_diff_weight(Literal* lit)
{
return 100*lit_standard_diff(lit)+lit->weight();
}
void ELiteralSelector::doSelection(Clause* c, unsigned eligible)
{
Literal* singleSel = nullptr;
LiteralList* sel = LiteralList::empty();
switch (_value) {
case SelectNegativeLiterals: {
for(int li=((int)eligible)-1; li>=0; li--) {
Literal* lit=(*c)[li];
if(isNegativeForSelection(lit)) {
LiteralList::push(lit,sel);
}
}
break;
}
case SelectPureVarNegLiterals: {
for(int li=((int)eligible)-1; li>=0; li--) {
Literal* lit=(*c)[li];
if(isNegativeForSelection(lit) && lit->isTwoVarEquality()) {
singleSel = lit;
break;
}
}
break;
}
case SelectSmallestNegLit: {
for(int li=((int)eligible)-1; li>=0; li--) {
Literal* lit=(*c)[li];
if(isNegativeForSelection(lit)) {
if (!singleSel || singleSel->weight() > lit->weight()) {
singleSel = lit;
}
}
}
break;
}
case SelectDiffNegLit: {
unsigned bestVal = 0;
for(int li=((int)eligible)-1; li>=0; li--) {
Literal* lit=(*c)[li];
if(isNegativeForSelection(lit)) {
unsigned val = lit_sel_diff_weight(lit);
if (!singleSel || val > bestVal) {
singleSel = lit;
bestVal = val;
}
}
}
break;
}
case SelectGroundNegLit: {
unsigned bestVal = 0;
for(int li=((int)eligible)-1; li>=0; li--) {
Literal* lit=(*c)[li];
if(isNegativeForSelection(lit) && lit->ground()) {
unsigned val = lit_sel_diff_weight(lit);
if (!singleSel || val > bestVal) {
singleSel = lit;
bestVal = val;
}
}
}
break;
}
case SelectOptimalLit: {
unsigned bestVal = 0;
bool bestGround = false;
for(int li=((int)eligible)-1; li>=0; li--) {
Literal* lit=(*c)[li];
if(isNegativeForSelection(lit) && (!bestGround || lit->ground())) {
unsigned val = lit_sel_diff_weight(lit);
if (!singleSel || (!bestGround && lit->ground()) || val > bestVal) {
singleSel = lit;
bestVal = val;
bestGround = lit->ground();
}
}
}
break;
}
default:
ASSERTION_VIOLATION;
}
if(singleSel) {
LiteralList::destroy(sel);
sel = LiteralList::empty();
LiteralList::push(singleSel,sel);
} else if (!sel) {
sel = getMaximalsInOrder(c,eligible);
}
unsigned selCnt=0;
for(unsigned li=0; sel; li++) {
ASS(li<eligible);
if((*c)[li]==sel->head()) {
if(li!=selCnt) {
swap((*c)[li], (*c)[selCnt]);
}
selCnt++;
LiteralList::pop(sel);
}
}
ASS(selCnt>0);
c->setSelected(selCnt);
ensureSomeColoredSelected(c, eligible);
}