#ifndef __SATInference__
#define __SATInference__
#include "Forwards.hpp"
#include "Lib/List.hpp"
#include "SATClause.hpp"
namespace Kernel {
using namespace SAT;
struct NeedsMinimization {
NeedsMinimization(InferenceRule rule, UnitList* premises, SATClauseList* satPremises, const SATLiteralStack& usedAssumptions) :
_rule(rule), _premises(premises), _satPremises(satPremises), _usedAssumptions(usedAssumptions) {}
NeedsMinimization(InferenceRule rule, UnitList* premises, SATClauseList* satPremises) :
_rule(rule), _premises(premises), _satPremises(satPremises) {}
InferenceRule _rule;
UnitList* _premises;
SATClauseList* _satPremises;
SATLiteralStack _usedAssumptions;
};
}
namespace SAT {
using namespace Kernel;
class FOConversionInference;
class PropInference;
class SATInference
{
public:
enum InfType {
PROP_INF,
FO_CONVERSION
};
virtual ~SATInference() {}
virtual InfType getType() const = 0;
FOConversionInference *foConversion();
PropInference *propInf();
template<typename Receiver>
static void visitFOConversions(SATClause* cl, Receiver receive);
template <typename Filter>
static void collectFilteredFOPremises(SATClause* cl, Stack<Unit*>& acc, Filter f);
static UnitList *getFOPremises(SATClause *cl);
};
class PropInference : public SATInference
{
public:
USE_ALLOCATOR(PropInference);
PropInference(SATClauseList* premises) : _premises(premises) {}
PropInference(SATClause* prem) : _premises(0)
{
SATClauseList::push(prem, _premises);
}
PropInference(SATClause* prem1, SATClause* prem2) : _premises(0)
{
SATClauseList::push(prem1, _premises);
SATClauseList::push(prem2, _premises);
}
~PropInference() override
{
SATClauseList::destroy(_premises);
}
InfType getType() const override { return PROP_INF; }
SATClauseList* getPremises() const { return const_cast<SATClauseList*>(_premises); }
void setPremises(SATClauseList* prems) { _premises = prems; }
private:
SATClauseList* _premises;
};
class FOConversionInference : public SATInference
{
public:
USE_ALLOCATOR(FOConversionInference);
FOConversionInference(Unit* origin);
FOConversionInference(Clause* cl);
~FOConversionInference() override;
InfType getType() const override { return FO_CONVERSION; }
Unit* getOrigin() const { return _origin; }
private:
Unit* _origin;
};
inline FOConversionInference *SATInference::foConversion() {
ASS_EQ(getType(), FO_CONVERSION)
return static_cast<FOConversionInference *>(this);
}
inline PropInference *SATInference::propInf() {
ASS_EQ(getType(), PROP_INF)
return static_cast<PropInference *>(this);
}
template<typename Receiver>
void SATInference::visitFOConversions(SATClause* cl, Receiver receive)
{
static Stack<SATClause*> toDo;
static DHSet<SATClause*> seen;
toDo.reset();
seen.reset();
toDo.push(cl);
while (toDo.isNonEmpty()) {
SATClause* cur = toDo.pop();
if (!seen.insert(cur))
continue;
SATInference* sinf = cur->inference();
ASS(sinf);
switch(sinf->getType()) {
case SATInference::FO_CONVERSION:
receive(cur);
break;
case SATInference::PROP_INF:
{
PropInference* pinf = static_cast<PropInference*>(sinf);
toDo.loadFromIterator(SATClauseList::Iterator(pinf->getPremises()));
break;
}
}
}
}
template <typename Filter>
void SATInference::collectFilteredFOPremises(SATClause* cl, Stack<Unit*>& acc, Filter f) {
visitFOConversions(cl, [&](SATClause *cl) {
if(!f(cl))
return;
acc.push(cl->inference()->foConversion()->getOrigin());
});
}
inline UnitList *SATInference::getFOPremises(SATClause *cl) {
UnitList *result = nullptr;
SATInference::visitFOConversions(cl, [&result](SATClause *cl) {
UnitList::push(cl->inference()->foConversion()->getOrigin(), result);
});
return result;
}
}
#endif