#include "Lib/ScopedLet.hpp"
#include "Kernel/Unit.hpp"
#include "Kernel/Clause.hpp"
#include "Kernel/Problem.hpp"
#include "GoalGuessing.hpp"
#include "AnswerLiteralManager.hpp"
#include "CNF.hpp"
#include "NewCNF.hpp"
#include "DistinctGroupExpansion.hpp"
#include "EqResWithDeletion.hpp"
#include "EqualityProxy.hpp"
#include "EqualityProxyMono.hpp"
#include "Flattening.hpp"
#include "FunctionDefinition.hpp"
#include "GeneralSplitting.hpp"
#include "FunctionDefinitionHandler.hpp"
#include "InequalitySplitting.hpp"
#include "InterpretedNormalizer.hpp"
#include "Kernel/ALASCA/Preprocessor.hpp"
#include "Naming.hpp"
#include "Normalisation.hpp"
#include "Shuffling.hpp"
#include "NNF.hpp"
#include "Options.hpp"
#include "PredicateDefinition.hpp"
#include "Preprocess.hpp"
#include "Rectify.hpp"
#include "Skolem.hpp"
#include "SimplifyFalseTrue.hpp"
#include "SineUtils.hpp"
#include "Statistics.hpp"
#include "FOOLElimination.hpp"
#include "TheoryAxioms.hpp"
#include "TheoryFlattening.hpp"
#include "TweeGoalTransformation.hpp"
#include "BlockedClauseElimination.hpp"
#include "UIHelper.hpp"
#include "Lib/List.hpp"
using namespace std;
using namespace Shell;
void Preprocess::preprocess(Problem& prb)
{
env.options->resolveAwayAutoValues0();
if (env.options->showPreprocessing()) {
std::cout << "preprocessing started" << std::endl;
UnitList::Iterator uit(prb.units());
while(uit.hasNext()) {
Unit* u = uit.next();
std::cout << "[PP] input: " << u->toString() << std::endl;
}
}
if (_options.questionAnswering()!=Options::QuestionAnsweringMode::OFF) {
env.statistics->phase=ExecutionPhase::ANSWER_LITERAL;
if (env.options->showPreprocessing())
std::cout << "answer literal addition" << std::endl;
AnswerLiteralManager::getInstance()->addAnswerLiterals(prb);
}
prb.getProperty();
if (env.signature->hasDefPreds() &&
!FunctionDefinitionHandler::isHandlerEnabled(_options)) {
prb.getFunctionDefinitionHandler().initAndPreprocessEarly(prb);
}
if (_options.normalize()) { env.statistics->phase=ExecutionPhase::NORMALIZATION;
if (env.options->showPreprocessing())
std::cout << "normalization" << std::endl;
Normalisation().normalise(prb);
}
if (_options.shuffleInput()) {
TIME_TRACE(TimeTrace::SHUFFLING);
env.statistics->phase=ExecutionPhase::SHUFFLING;
if (env.options->showPreprocessing())
std::cout << "shuffling1" << std::endl;
Shuffling::shuffle(prb);
}
if(_options.guessTheGoal() != Options::GoalGuess::OFF){
prb.invalidateProperty();
prb.getProperty();
GoalGuessing().apply(prb);
}
if (prb.hasInterpretedOperations() || env.signature->hasTermAlgebras()){
if (_options.theoryAxioms() != Options::TheoryAxiomLevel::OFF || !_options.alasca()) { InterpretedNormalizer().apply(prb);
}
if(_options.theoryAxioms() != Options::TheoryAxiomLevel::OFF){
env.statistics->phase=ExecutionPhase::INCLUDING_THEORY_AXIOMS;
if (env.options->showPreprocessing())
std::cout << "adding theory axioms" << std::endl;
TheoryAxioms(prb).apply();
}
}
if (_options.alascaIntegerConversion()) {
if (env.options->showPreprocessing())
std::cout << "eliminating euclidean quotient and remainder" << std::endl;
QuotientEPreproc().proc(prb);
}
if (prb.hasFOOL() || prb.isHigherOrder()) {
if (!_options.newCNF() || prb.isHigherOrder()) {
if (env.options->showPreprocessing())
std::cout << "FOOL elimination" << std::endl;
FOOLElimination().apply(prb);
}
}
(void)prb.getProperty();
if(env.signature->hasDistinctGroups()){
if(env.options->showPreprocessing())
std::cout << "distinct group expansion" << std::endl;
DistinctGroupExpansion(_options.distinctGroupExpansionLimit()).apply(prb);
}
if (_options.sineToAge() || _options.useSineLevelSplitQueues() || (_options.sineToPredLevels() != Options::PredicateSineLevels::OFF)) {
env.statistics->phase=ExecutionPhase::SINE_SELECTION;
if (_options.sineToPredLevels() != Options::PredicateSineLevels::OFF) {
env.predicateSineLevels = new DHMap<unsigned,unsigned>();
}
SineSelector(false,_options.sineToAgeTolerance(),0,
_options.sineToAgeGeneralityThreshold(),true).perform(prb);
}
if (_options.sineSelection()!=Options::SineSelection::OFF) {
env.statistics->phase=ExecutionPhase::SINE_SELECTION;
if (env.options->showPreprocessing())
std::cout << "sine selection" << std::endl;
SineSelector(_options).perform(prb);
}
if (!_clausify && !_stillSimplify) {
return;
}
if (prb.mayHaveFormulas()) {
if (env.options->showPreprocessing())
std::cout << "preprocess1 (rectify, simplify false true, flatten)" << std::endl;
preprocess1(prb);
}
if (_options.shuffleInput()) {
TIME_TRACE(TimeTrace::SHUFFLING);
env.statistics->phase=ExecutionPhase::SHUFFLING;
if (env.options->showPreprocessing())
std::cout << "shuffling2" << std::endl;
Shuffling::shuffle(prb);
}
if (!_clausify) {
return;
}
if (_options.unusedPredicateDefinitionRemoval()) {
env.statistics->phase=ExecutionPhase::UNUSED_PREDICATE_DEFINITION_REMOVAL;
if (env.options->showPreprocessing())
std::cout << "unused predicate definition removal" << std::endl;
PredicateDefinition pdRemover;
pdRemover.removeUnusedDefinitionsAndPurePredicates(prb);
}
if (prb.mayHaveFormulas()) {
if (env.options->showPreprocessing())
std::cout << "preprocess 2 (ennf,flatten)" << std::endl;
preprocess2(prb);
}
if (_options.shuffleInput()) {
TIME_TRACE(TimeTrace::SHUFFLING);
env.statistics->phase=ExecutionPhase::SHUFFLING;
if (env.options->showPreprocessing())
std::cout << "shuffling3" << std::endl;
Shuffling::shuffle(prb);
}
if (prb.mayHaveFormulas() && _options.newCNF() && !prb.isHigherOrder()) {
if (env.options->showPreprocessing())
std::cout << "newCnf" << std::endl;
newCnf(prb);
} else {
if (prb.mayHaveFormulas() && _options.newCNF()) { ASS(prb.isHigherOrder());
if (outputAllowed()) {
addCommentSignForSZS(std::cout);
std::cout << "WARNING: Not using 'newcnf' as currently not compatible with higher-order inputs." << endl;
}
}
if (prb.mayHaveFormulas() && _options.naming()) {
if (env.options->showPreprocessing())
std::cout << "naming" << std::endl;
naming(prb);
}
if (prb.mayHaveFormulas()) {
if (env.options->showPreprocessing())
std::cout << "preprocess3 (nnf, flatten, skolemize)" << std::endl;
preprocess3(prb);
}
if (prb.mayHaveFormulas()) {
if (env.options->showPreprocessing())
std::cout << "clausify" << std::endl;
clausify(prb);
}
}
prb.getProperty();
if (prb.hasFOOL()) {
TheoryAxioms(prb).applyFOOL();
}
if (prb.mayHaveFunctionDefinitions()) {
env.statistics->phase=ExecutionPhase::FUNCTION_DEFINITION_ELIMINATION;
if (env.options->showPreprocessing())
std::cout << "function definition elimination" << std::endl;
if (_options.functionDefinitionElimination() == Options::FunctionDefinitionElimination::ALL) {
FunctionDefinition fd;
fd.removeAllDefinitions(prb,env.getMainProblem()->isHigherOrder());
}
else if (_options.functionDefinitionElimination() == Options::FunctionDefinitionElimination::UNUSED) {
FunctionDefinition::removeUnusedDefinitions(prb,env.getMainProblem()->isHigherOrder());
}
}
if (prb.mayHaveEquality() && _options.inequalitySplitting() != 0) {
if (env.options->showPreprocessing())
std::cout << "inequality splitting" << std::endl;
env.statistics->phase=ExecutionPhase::INEQUALITY_SPLITTING;
InequalitySplitting is(_options);
is.perform(prb);
}
if (_options.equalityResolutionWithDeletion() && prb.mayHaveInequalityResolvableWithDeletion() ) {
env.statistics->phase=ExecutionPhase::EQUALITY_RESOLUTION_WITH_DELETION;
if (env.options->showPreprocessing())
std::cout << "equality resolution with deletion" << std::endl;
EqResWithDeletion resolver;
resolver.apply(prb);
}
if (env.signature->hasDefPreds() &&
FunctionDefinitionHandler::isHandlerEnabled(_options)) {
prb.getFunctionDefinitionHandler().initAndPreprocessLate(prb,_options);
}
if (_options.generalSplitting()) {
if (prb.isHigherOrder() || prb.hasPolymorphicSym()) { if (outputAllowed()) {
addCommentSignForSZS(std::cout);
std::cout << "WARNING: Not using GeneralSplitting currently not compatible with polymorphic/higher-order inputs." << endl;
}
} else {
env.statistics->phase=ExecutionPhase::GENERAL_SPLITTING;
if (env.options->showPreprocessing())
std::cout << "general splitting" << std::endl;
GeneralSplitting gs;
gs.apply(prb);
}
}
if(env.options->tweeGoalTransformation() != Options::TweeGoalTransformation::OFF) {
env.statistics->phase = ExecutionPhase::TWEE;
if(env.options->showPreprocessing())
std::cout << "twee goal transformation" << std::endl;
TweeGoalTransformation twee;
twee.apply(prb,(env.options->tweeGoalTransformation() == Options::TweeGoalTransformation::GROUND));
}
if (!prb.isHigherOrder() && _options.equalityProxy()!=Options::EqualityProxy::OFF && prb.mayHaveEquality()) {
env.statistics->phase=ExecutionPhase::EQUALITY_PROXY;
if (env.options->showPreprocessing())
std::cout << "equality proxy" << std::endl;
prb.getProperty();
if(_options.useMonoEqualityProxy() && !prb.hasPolymorphicSym()){
EqualityProxyMono proxy(_options.equalityProxy());
proxy.apply(prb);
} else {
EqualityProxy proxy(_options.equalityProxy());
proxy.apply(prb);
}
}
if(_options.theoryFlattening()) {
if (prb.hasPolymorphicSym()) { if (outputAllowed()) {
addCommentSignForSZS(std::cout);
std::cout << "WARNING: Not using TheoryFlattening currently not compatible with polymorphic inputs." << endl;
}
} else {
if(env.options->showPreprocessing())
std::cout << "theory flattening" << std::endl;
TheoryFlattening tf;
tf.apply(prb);
}
}
if (env.options->alascaIntegerConversion()) {
if (env.options->showPreprocessing())
std::cout << "performing integer conversion" << std::endl;
AlascaPreprocessor alasca(InequalityNormalizer::global());
alasca.integerConversion(prb);
}
if (_options.blockedClauseElimination()) {
env.statistics->phase=ExecutionPhase::BLOCKED_CLAUSE_ELIMINATION;
if(env.options->showPreprocessing())
std::cout << "blocked clause elimination" << std::endl;
BlockedClauseElimination bce(_options.saturationAlgorithm() == Options::SaturationAlgorithm::FINITE_MODEL_BUILDING);
bce.apply(prb);
}
if (_options.shuffleInput()) {
TIME_TRACE(TimeTrace::SHUFFLING);
env.statistics->phase=ExecutionPhase::SHUFFLING;
if (env.options->showPreprocessing())
std::cout << "shuffling4" << std::endl;
Shuffling::shuffle(prb);
}
if (_options.randomPolarities()) {
TIME_TRACE(TimeTrace::SHUFFLING);
env.statistics->phase=ExecutionPhase::SHUFFLING;
if (env.options->showPreprocessing())
std::cout << "flipping polarities" << std::endl;
Shuffling::polarityFlip(prb);
}
if (env.options->showPreprocessing()) {
UnitList::Iterator uit(prb.units());
while(uit.hasNext()) {
Unit* u = uit.next();
std::cout << "[PP] final: " << u->toString() << std::endl;
}
}
if (_options.printClausifierPremises()) {
UIHelper::outputAllPremises(cerr, prb.units());
}
if (env.options->showPreprocessing()) {
std::cout << "preprocessing finished" << std::endl;
}
}
void Preprocess::preprocess1 (Problem& prb)
{
ScopedLet<ExecutionPhase> epLet(env.statistics->phase, ExecutionPhase::PREPROCESS_1);
bool formulasSimplified = false;
UnitList*& units = prb.units();
UnitList::DelIterator us(units);
while (us.hasNext()) {
Unit* u = us.next();
if (u->isClause()) {
continue;
}
FormulaUnit* fu = static_cast<FormulaUnit*>(u);
fu = Rectify::rectify(fu);
FormulaUnit* rectFu = fu;
if (!_options.newCNF() || prb.isHigherOrder()) {
fu = SimplifyFalseTrue::simplify(fu);
}
if (fu!=rectFu) {
formulasSimplified = true;
}
fu = Flattening::flatten(fu);
if (fu != u) {
us.replace(fu);
}
}
if (formulasSimplified) {
prb.invalidateByRemoval();
}
}
void Preprocess::preprocess2(Problem& prb)
{
env.statistics->phase=ExecutionPhase::PREPROCESS_2;
UnitList::DelIterator us(prb.units());
while (us.hasNext()) {
Unit* u = us.next();
if (u->isClause()) {
continue;
}
FormulaUnit* fu = static_cast<FormulaUnit*>(u);
FormulaUnit* fu0 = fu;
fu = NNF::ennf(fu);
fu = Flattening::flatten(fu);
if (fu != fu0) {
us.replace(fu);
}
}
}
void Preprocess::naming(Problem& prb)
{
ASS(_options.naming());
env.statistics->phase=ExecutionPhase::NAMING;
UnitList::DelIterator us(prb.units());
Naming naming(_options.naming(),false, prb.isHigherOrder()); while (us.hasNext()) {
Unit* u = us.next();
if (u->isClause()) {
continue;
}
UnitList* defs;
FormulaUnit* fu = static_cast<FormulaUnit*>(u);
FormulaUnit* v = naming.apply(fu,defs);
if (v != fu) {
ASS(defs);
us.insert(defs);
us.replace(v);
}
}
prb.invalidateProperty();
}
void Preprocess::newCnf(Problem& prb)
{
env.statistics->phase=ExecutionPhase::NEW_CNF;
Unit* emptyClause = 0;
bool modified = false;
UnitList::DelIterator us(prb.units());
NewCNF cnf(env.options->naming());
Stack<Clause*> clauses(32);
while (us.hasNext()) {
Unit* u = us.next();
if (env.options->showPreprocessing()) {
std::cout << "[PP] clausify: " << u->toString() << std::endl;
}
if (u->isClause()) {
if (static_cast<Clause*>(u)->isEmpty()) {
emptyClause = u;
break;
}
continue;
}
modified = true;
FormulaUnit* fu = static_cast<FormulaUnit*>(u);
cnf.clausify(fu,clauses);
while (! clauses.isEmpty()) {
Clause* cl = clauses.pop();
if (cl->isEmpty()) {
emptyClause = cl;
goto fin;
}
us.insert(cl);
}
us.del();
}
fin:
if (emptyClause) {
UnitList::destroy(prb.units());
prb.units() = 0;
UnitList::push(emptyClause, prb.units());
}
if (modified) {
prb.invalidateProperty();
}
prb.reportFormulasEliminated();
}
Unit* Preprocess::preprocess3 (Unit* u, bool appify )
{
if (u->isClause()) {
return u;
}
FormulaUnit* fu = static_cast<FormulaUnit*>(u);
fu = NNF::nnf(fu);
fu = Flattening::flatten(fu);
fu = Skolem::skolemise(fu, appify);
return fu;
}
void Preprocess::preprocess3 (Problem& prb)
{
bool modified = false;
env.statistics->phase=ExecutionPhase::PREPROCESS_3;
UnitList::DelIterator us(prb.units());
while (us.hasNext()) {
Unit* u = us.next();
Unit* v = preprocess3(u, prb.isHigherOrder());
if (u!=v) {
us.replace(v);
modified = true;
}
}
if (modified) {
prb.invalidateProperty();
}
}
void Preprocess::clausify(Problem& prb)
{
env.statistics->phase=ExecutionPhase::CLAUSIFICATION;
Unit* emptyClause = 0;
bool modified = false;
UnitList::DelIterator us(prb.units());
CNF cnf;
Stack<Clause*> clauses(32);
while (us.hasNext()) {
Unit* u = us.next();
if (env.options->showPreprocessing()) {
std::cout << "[PP] clausify: " << u->toString() << std::endl;
}
if (u->isClause()) {
if (static_cast<Clause*>(u)->isEmpty()) {
emptyClause = u;
break;
}
continue;
}
modified = true;
cnf.clausify(u,clauses);
while (! clauses.isEmpty()) {
Unit* u = clauses.pop();
if (static_cast<Clause*>(u)->isEmpty()) {
emptyClause = u;
goto fin;
}
us.insert(u);
}
us.del();
}
fin:
if (emptyClause) {
UnitList::destroy(prb.units());
prb.units() = 0;
UnitList::push(emptyClause, prb.units());
}
if (modified) {
prb.invalidateProperty();
}
prb.reportFormulasEliminated();
}