#ifndef __Splitter__
#define __Splitter__
#include "Forwards.hpp"
#include "Lib/Allocator.hpp"
#include "Lib/ArrayMap.hpp"
#include "Lib/DHMap.hpp"
#include "Lib/Hash.hpp"
#include "Lib/Stack.hpp"
#include "Lib/ScopedPtr.hpp"
#include "Shell/Options.hpp"
#include "Kernel/RCClauseStack.hpp"
#include "Indexing/ClauseVariantIndex.hpp"
#include "SAT/SAT2FO.hpp"
#include "SAT/SATLiteral.hpp"
#include "SAT/SATSolver.hpp"
#include "SAT/ProofProducingSATSolver.hpp"
#include "DP/ShortConflictMetaDP.hpp"
#include "Lib/Allocator.hpp"
namespace Saturation {
using namespace Lib;
using namespace Kernel;
using namespace Shell;
using namespace SAT;
using namespace DP;
using namespace Indexing;
typedef Stack<SplitLevel> SplitLevelStack;
struct SATClauseExtra : public InferenceExtra {
SATClause *clause;
SATClauseExtra(SATClause *clause) : clause(clause) {}
void output(std::ostream &out) const override;
};
struct SplitDefinitionExtra : public InferenceExtra {
Clause *component;
SplitDefinitionExtra(Clause *component) : component(component) {
component->incRefCnt();
}
void output(std::ostream &out) const override;
};
class Splitter;
class SplittingBranchSelector {
public:
SplittingBranchSelector(Splitter& parent) : _parent(parent) {}
void init();
void updateVarCnt();
void considerPolarityAdvice(SATLiteral lit);
void trySetTrue(SATLiteral lit) {
_solver.suggestPolarity(lit.var(),lit.positive());
}
void addSatClauseToSolver(SATClause* cl);
void recomputeModel(SplitLevelStack& addedComps, SplitLevelStack& removedComps);
private:
friend class Splitter;
SAT::Status processDPConflicts();
void handleSatRefutation();
void updateSelection(unsigned satVar, VarAssignment asgn,
SplitLevelStack& addedComps, SplitLevelStack& removedComps);
Options::SplittingLiteralPolarityAdvice _literalPolarityAdvice;
Splitter& _parent;
ProofProducingSATSolver _solver;
ScopedPtr<ShortConflictMetaDP> _dp;
ArraySet _selected;
};
class Splitter {
private:
struct ReductionRecord
{
ReductionRecord(Clause* clause) : clause(clause),
timestamp(clause->getReductionTimestamp()) {}
Clause* clause;
unsigned timestamp;
};
struct SplitRecord
{
SplitRecord(Clause* comp)
: component(comp), active(false)
{
component->incRefCnt();
}
~SplitRecord();
void addReduced(Clause* cl);
Clause* component;
RCClauseStack children;
Stack<ReductionRecord> reduced;
Stack<PartialRedundancyEntry*> partialRedundancyEntries;
bool active;
bool sticky = false;
USE_ALLOCATOR(SplitRecord);
};
public:
Splitter();
~Splitter();
const Options& getOptions() const;
Ordering& getOrdering() const;
void init(SaturationAlgorithm* sa);
bool doSplitting(Clause* cl);
void onClauseReduction(Clause* cl, ClauseIterator premises, Clause* replacement);
void addPartialRedundancyEntry(SplitSet* splits, PartialRedundancyEntry* e);
void onNewClause(Clause* cl);
void onAllProcessed();
bool handleEmptyClause(Clause* cl);
SplitLevel getNameFromLiteral(SATLiteral lit) const;
Unit* getDefinitionFromName(SplitLevel compName) const;
static std::string splitsToString(SplitSet* splits);
static SATLiteral getLiteralFromName(SplitLevel compName);
static std::string getFormulaStringFromName(SplitLevel compName, bool negated = false);
static std::string getFormulaStringFromLiteral(SATLiteral l);
bool isUsedName(SplitLevel name) const {
ASS_L(name,_db.size());
return (_db[name] != 0);
}
bool isSticky(SplitLevel name) const {
ASS_L(name,_db.size());
return _db[name]->sticky;
}
Clause* getComponentClause(SplitLevel name) const;
SplitLevel splitLevelCnt() const { return _db.size(); }
unsigned maxSatVar() const { return _sat2fo.maxSATVar(); }
SAT2FO& satNaming() { return _sat2fo; }
UnitList* preprendCurrentlyAssumedComponentClauses(UnitList* clauses);
static bool getComponents(Clause* cl, Stack<LiteralStack>& acc, bool shuffle = false);
Clause* reintroduceAvatarAssertions(Clause* cl);
private:
friend class SplittingBranchSelector;
SplitLevel getNameFromLiteralUnsafe(SATLiteral lit) const;
bool shouldAddClauseForNonSplittable(Clause* cl, unsigned& compName, Clause*& compCl);
bool handleNonSplittable(Clause* cl);
bool tryGetExistingComponentName(unsigned size, Literal* const * lits, SplitLevel& comp, Clause*& compCl);
void addComponents(const SplitLevelStack& toAdd);
void removeComponents(const SplitLevelStack& toRemove);
void collectDependenceLits(SplitSet* splits, SATLiteralStack& acc) const;
SplitLevel addNonGroundComponent(unsigned size, Literal* const * lits, Clause* orig, Clause*& compCl);
SplitLevel addGroundComponent(Literal* lit, Clause* orig, Clause*& compCl);
Clause* buildAndInsertComponentClause(SplitLevel name, unsigned size, Literal* const * lits, Clause* orig=0);
SplitLevel tryGetComponentNameOrAddNew(const LiteralStack& comp, Clause* orig, Clause*& compCl);
SplitLevel tryGetComponentNameOrAddNew(unsigned size, Literal* const * lits, Clause* orig, Clause*& compCl);
void addSatClauseToSolver(SATClause* cl);
SplitSet* getNewClauseSplitSet(Clause* cl);
void assignClauseSplitSet(Clause* cl, SplitSet* splits);
bool allSplitLevelsActive(SplitSet* s);
void conjectureSingleton(Literal* theLit, Clause* orig);
bool _showSplitting;
Options::SplittingAddComplementary _complBehavior;
Options::SplittingNonsplittableComponents _nonsplComps;
Options::SplittingDeleteDeactivated _deleteDeactivated;
bool _congruenceClosure;
bool _shuffleComponents;
#if VZ3
bool hasSMTSolver;
#endif
SplittingBranchSelector _branchSelector;
ScopedPtr<ClauseVariantIndex> _componentIdx;
SAT2FO _sat2fo;
Stack<SplitRecord*> _db;
DHMap<SplitLevel,Unit*> _defs;
bool _clausesAdded;
unsigned _stopSplittingAtTime; #if VAMPIRE_PERF_EXISTS
unsigned _stopSplittingAtInst; #endif
bool _cleaveNonsplittables;
SaturationAlgorithm* _sa;
Set<SATClause *, DerefPtrHash<DefaultHash>> _already_added;
public:
static std::string splPrefix;
SplitLevel splitLevelBound() { return _db.size(); }
bool splitLevelActive(SplitLevel lev) {
ASS_REP(lev<_db.size(), lev);
return (_db[lev]!=0 && _db[lev]->active);
}
};
}
#endif