#include <algorithm>
#include <ostream>
#include "Lib/Allocator.hpp"
#include "Lib/Environment.hpp"
#include "Shell/Statistics.hpp"
#include "SATInference.hpp"
#include "SATClause.hpp"
namespace SAT {
using namespace Lib;
using namespace Shell;
unsigned SATClause::_lastNumber = 0;
void* SATClause::operator new(size_t sz,unsigned lits)
{
size_t size=sz+lits*sizeof(SATLiteral);
if (lits > 0)
size-=sizeof(SATLiteral);
return ALLOC_KNOWN(size,"SATClause");
}
void SATClause::operator delete(void *ptr, size_t sz) {
SATClause *self = static_cast<SATClause *>(ptr);
size_t size = sz + self->_length * sizeof(SATLiteral);
if(self->_length > 0)
size -= sizeof(SATLiteral);
DEALLOC_KNOWN(ptr, size, "SATClause");
}
SATClause::SATClause(unsigned length)
: number(++_lastNumber), _length(length), _nonDestroyable(0), _inference(0)
{
env.statistics->satClauses++;
if(length==1) {
env.statistics->unitSatClauses++;
}
else if(length==2) {
env.statistics->binarySatClauses++;
}
for (size_t i = 1; i < _length; i++)
::new (&_literals[i]) SATLiteral();
}
void SATClause::destroy()
{
if(_nonDestroyable) {
return;
}
if(_inference) {
delete _inference;
}
size_t size=sizeof(SATClause)+_length*sizeof(SATLiteral);
if (_length > 0) size-=sizeof(SATLiteral);
for (size_t i = 1; i < _length; i++)
_literals[i].~SATLiteral();
this->~SATClause();
DEALLOC_KNOWN(this, size,"SATClause");
}
void SATClause::setInference(SATInference* val)
{
ASS(!_inference);
_inference = val;
if(_inference->getType()==SATInference::PROP_INF) {
SATClauseList* premises = static_cast<PropInference*>(val)->getPremises();
SATClauseList::Iterator pit(premises);
while(pit.hasNext()) {
SATClause* prem = pit.next();
prem->_nonDestroyable = 1;
}
}
}
void SATClause::sort()
{
std::sort(_literals, _literals + length());
}
SATClause* SATClause::removeDuplicateLiterals(SATClause* cl)
{
unsigned clen=cl->length();
cl->sort();
unsigned duplicate=0;
for(unsigned i=1;i<clen;i++) {
if((*cl)[i-1].var()==(*cl)[i].var()) {
if((*cl)[i-1].positive()==(*cl)[i].positive()) {
std::swap((*cl)[duplicate], (*cl)[i-1]);
duplicate++;
} else {
cl->destroy();
return 0;
}
}
}
if(duplicate) {
unsigned newLen=clen-duplicate;
SATClause* cl2=new(newLen) SATClause(newLen);
for(unsigned i=0;i<newLen;i++) {
(*cl2)[i]=(*cl)[duplicate+i];
}
cl2->sort();
if(cl->inference()) {
SATInference* cl2Inf = new PropInference(cl);
cl2->setInference(cl2Inf);
}
else {
cl->destroy();
}
cl=cl2;
}
return cl;
}
SATClause* SATClause::fromStack(SATLiteralStack& stack)
{
unsigned clen = stack.size();
SATClause* rcl=new(clen) SATClause(clen);
SATLiteralStack::BottomFirstIterator it(stack);
unsigned i=0;
while(it.hasNext()) {
(*rcl)[i]=it.next();
i++;
}
ASS_EQ(i, clen);
return rcl;
}
std::ostream &operator<<(std::ostream &out, const SATClause &cl)
{
out << "s" << cl.number << ". ";
if (cl.length() == 0)
out << "#";
else {
out << cl[0];
for(unsigned i = 1; i < cl.length(); i++)
out << " | " << cl[i];
}
SATInference *inference = cl.inference();
if(!inference)
return out;
bool first = true;
out << " [";
switch(inference->getType()) {
case SATInference::PROP_INF: {
out << "rat ";
PropInference *deduction = static_cast<PropInference *>(inference);
for(SATClause *premise : iterTraits(deduction->getPremises()->iter())) {
if(!first)
out << ",";
first = false;
out << "s" << premise->number;
}
break;
}
case SAT::SATInference::FO_CONVERSION: {
FOConversionInference *deduction = static_cast<FOConversionInference *>(inference);
out << "sat_conversion " << deduction->getOrigin()->number();
break;
}
}
return out << "]";
}
};