#include "Forwards.hpp"
#include "Lib/Environment.hpp"
#include "Lib/Int.hpp"
#include "Lib/List.hpp"
#include "SAT/SATClause.hpp"
#include "Shell/Statistics.hpp"
#include "Inference.hpp"
#include "Clause.hpp"
#include "Formula.hpp"
#include "FormulaUnit.hpp"
#include "Unit.hpp"
using namespace std;
using namespace Kernel;
unsigned Unit::_lastNumber = 0;
unsigned Unit::_firstNonPreprocessingNumber = 0;
unsigned Unit::_lastParsingNumber = 0;
void Unit::onPreprocessingEnd()
{
ASS(!_firstNonPreprocessingNumber);
_firstNonPreprocessingNumber=_lastNumber+1;
}
Unit::Unit(Kind kind, Inference inf)
: _number(++_lastNumber),
_kind(kind),
_inheritedColor(COLOR_INVALID),
_inference(std::move(inf))
{
env.statistics->reportUnit(this,Statistics::TOTAL_CNT);
}
void Unit::doUnitTracing() {
#if VAMPIRE_CLAUSE_TRACING
if (env.options->traceBackward() && unsigned(env.options->traceBackward()) == number()) {
traverseParentsPost(
[&](unsigned depth, Unit* unit) {
std::cout << "backward trace " << number() << ": " << Output::repeat("| ", depth) << unit->toString() << std::endl;
});
}
static int traceFwd = env.options->traceForward();
if (traceFwd != -1) {
bool doTrace = false;
auto infit = inference().iterator();
while (inference().hasNext(infit)) {
if (inference().next(infit)->number() == unsigned(traceFwd)) {
doTrace = true;
break;
}
}
if (doTrace) {
std::cout << "forward trace " << traceFwd << ": " << toString() << std::endl;
}
}
#endif }
void Unit::incRefCnt()
{
if(isClause()) {
static_cast<Clause*>(this)->incRefCnt();
}
}
void Unit::decRefCnt()
{
if(isClause()) {
static_cast<Clause*>(this)->decRefCnt();
}
}
Clause* Unit::asClause() {
ASS(isClause());
return static_cast<Clause*>(this);
}
Color Unit::getColor()
{
if(isClause()) {
return static_cast<Clause*>(this)->color();
}
else {
return static_cast<FormulaUnit*>(this)->getColor();
}
}
unsigned Unit::getWeight()
{
if(isClause()) {
return static_cast<Clause*>(this)->weight();
}
else {
return static_cast<FormulaUnit*>(this)->weight();
}
}
void Unit::destroy()
{
if(isClause()) {
static_cast<Clause*>(this)->destroy();
}
else {
static_cast<FormulaUnit*>(this)->destroy();
}
}
std::string Unit::toString() const
{
if(isClause()) {
return static_cast<const Clause*>(this)->toString();
}
else {
return static_cast<const FormulaUnit*>(this)->toString();
}
}
unsigned Unit::varCnt()
{
if(isClause()) {
return static_cast<Clause*>(this)->varCnt();
}
else {
return static_cast<FormulaUnit*>(this)->varCnt();
}
}
Formula* Unit::getFormula()
{
if(isClause()) {
return Formula::fromClause(static_cast<Clause*>(this)); }
else {
return Formula::quantify(static_cast<FormulaUnit*>(this)->formula());
}
}
std::string Unit::inferenceAsString() const
{
const Inference& inf = inference();
std::string result = (std::string)"[" + inf.name();
SAT::SATClause *sat = inf.satPremise();
if(sat)
return result + " s" + Int::toString(inf.satPremise()->number) + "]";
bool first = true;
auto it = inf.iterator();
while (inf.hasNext(it)) {
Unit* parent = inf.next(it);
result += first ? ' ' : ',';
first = false;
result += Int::toString(parent->number());
}
if(env.options->proofExtra() == Options::ProofExtra::FULL) {
auto *extra = env.proofExtra.find(this);
if(extra) {
if(!first)
result += ',';
result += extra->toString();
}
}
return result + ']';
}
void Unit::assertValid()
{
if(isClause()) {
ASS_ALLOC_TYPE(this,"Clause");
}
else {
ASS_ALLOC_TYPE(this,"FormulaUnit");
}
}
UnitIterator Unit::getParents() const
{
UnitList* res = 0;
Inference::Iterator iit = _inference.iterator();
while(_inference.hasNext(iit)) {
Unit* premUnit = _inference.next(iit);
UnitList::push(premUnit, res);
}
res = UnitList::reverse(res); return pvi(UnitList::DestructiveIterator(res));
}
bool Unit::minimizeAncestorsAndUpdateSelectedStats()
{
Stack<std::pair<Unit*,bool>> todo;
DHSet<Unit*> done;
bool seenInputInference = false;
todo.push(make_pair(this,false));
while(!todo.isEmpty()) {
Unit* current;
bool collecting;
std::tie(current,collecting) = todo.pop();
if (collecting) {
Inference& inf = current->inference();
seenInputInference |= (inf.rule() == InferenceRule::INPUT);
Inference::Iterator iit = inf.iterator();
if (inf.hasNext(iit)) {
UnitInputType uit = UnitInputType::AXIOM; bool isPureTheoryDescendant = true; while(inf.hasNext(iit)) {
Unit* premUnit = inf.next(iit);
uit = getInputType(uit,premUnit->inputType());
isPureTheoryDescendant &= premUnit->isPureTheoryDescendant();
}
current->setInputType(uit);
inf.setPureTheoryDescendant(isPureTheoryDescendant);
} else if (inf.rule() == InferenceRule::AVATAR_DEFINITION) {
current->setInputType(UnitInputType::AXIOM); } else {
ASS_EQ(inf.isPureTheoryDescendant(),inf.isTheoryAxiom());
}
inf.updateStatistics(); env.statistics->reportUnit(current,Statistics::INPROOF_CNT);
} else {
if (!done.insert(current)) {
continue;
}
todo.push(make_pair(current,true)); Inference& inf = current->inference();
inf.minimizePremises(); Inference::Iterator iit = inf.iterator();
while(inf.hasNext(iit)) {
Unit* premUnit = inf.next(iit);
todo.push(make_pair(premUnit,false));
}
}
}
return seenInputInference;
}
std::ostream& Kernel::operator<<(std::ostream& out, const Unit& u)
{
return out << u.toString();
}