#ifndef __AnswerLiteralManager__
#define __AnswerLiteralManager__
#include <vector>
#include "Forwards.hpp"
#include "Lib/DArray.hpp"
#include "Lib/DHMap.hpp"
#include "Lib/Environment.hpp"
#include "Lib/List.hpp"
#include "Kernel/Formula.hpp"
#include "Kernel/FormulaUnit.hpp"
#include "Kernel/TermTransformer.hpp"
#include "Inferences/InferenceEngine.hpp"
namespace Inferences {
class AnswerLiteralResolver
: public ImmediateSimplificationEngine
{
public:
Clause* simplify(Clause* cl) override;
};
}
namespace Shell {
using namespace Lib;
using namespace Kernel;
using namespace Indexing;
class AnswerLiteralManager
{
public:
friend class Inferences::AnswerLiteralResolver;
static AnswerLiteralManager* getInstance();
void tryOutputAnswer(Clause* refutation, std::ostream& out);
virtual ~AnswerLiteralManager() {}
virtual bool tryGetAnswer(Clause* refutation, Stack<Clause*>& answer);
void addAnswerLiterals(Problem& prb);
bool addAnswerLiterals(UnitList*& units);
virtual void onNewClause(Clause* cl) {}
virtual Clause* recordAnswerAndReduce(Clause* cl) { return nullptr; };
virtual Literal* makeITEAnswerLiteral(Literal* condition, Literal* thenLit, Literal* elseLit) { return nullptr; };
void recordSkolemsOrigin(unsigned skSymb, unsigned var, Unit* unit) {
ALWAYS(_skolemsOrigin.insert(skSymb,std::make_pair(var,unit)));
}
protected:
static TermList possiblyEvaluateAnswerTerm(TermList);
virtual void recordSkolemBinding(Term* skT,unsigned var,std::string vName) = 0;
virtual bool closeFreeVariablesForPrinting() { return false; };
virtual void optionalAnswerPrefix(std::ostream& out) {};
virtual std::string postprocessAnswerString(std::string answer) { return answer; };
Clause* getRefutation(Clause* answer);
Literal* getAnswerLiteral(VList* vars,SList* srts,Formula* f);
private:
Unit* tryAddingAnswerLiteral(Unit* unit);
Clause* getResolverClause(unsigned pred);
DHMap<unsigned, std::pair<Unit*,Literal*>> _originUnitsAndInjectedLiterals;
DHMap<unsigned, Clause*> _resolverClauses;
DHMap<unsigned,std::pair<unsigned,Unit*>> _skolemsOrigin;
};
class PlainALManager : public AnswerLiteralManager
{
protected:
void recordSkolemBinding(Term*,unsigned,std::string) override;
bool closeFreeVariablesForPrinting() override { return true; };
void optionalAnswerPrefix(std::ostream& out) override;
std::string postprocessAnswerString(std::string answer) override;
private:
Stack<std::pair<Term*, std::string>> _skolemNames;
};
typedef std::pair<unsigned, Term*> Binding;
typedef List<Binding> BindingList;
struct SkolemTracker { Binding binding;
unsigned constructorId = 0; bool recursiveCall = false; unsigned indexInConstructor = 0; unsigned recFnId = 0;
SkolemTracker() {}
SkolemTracker(Binding b, unsigned c, bool rc, unsigned i, unsigned rf = 0) : binding(b), constructorId(c), recursiveCall(rc), indexInConstructor(i), recFnId(rf) {}
std::string toString() const {
std::string s;
s += "SkolemTracker(";
s += "var=X" + Int::toString(binding.first);
s += ", skolem=";
s += (binding.second ? binding.second->toString() : "");
s += ", cnstrID=";
s += Int::toString(constructorId);
s += ", recursiveCall=";
s += recursiveCall ? "true" : "false";
s += ", idxInCons=";
s += Int::toString(indexInConstructor);
s += ", recFnId=";
s += Int::toString(recFnId) + ")";
return s;
}
};
class SynthesisALManager : public AnswerLiteralManager
{
private:
typedef DHMap<unsigned , DHMap<unsigned , SkolemTracker>> RecursionMappings;
public:
bool tryGetAnswer(Clause* refutation, Stack<Clause*>& answer) override;
void onNewClause(Clause* cl) override;
Clause* recordAnswerAndReduce(Clause* cl) override;
Literal* makeITEAnswerLiteral(Literal* condition, Literal* thenLit, Literal* elseLit) override;
void registerSkolemSymbols(Term* recTerm, const Substitution& subst, const std::vector<Term*>& functionHeadsByConstruction, std::vector<SkolemTracker>& incompleteTrackers, const VList* us);
bool isRecTerm(const Term* t) const;
bool hasRecTerm(Literal* lit);
const SkolemTracker* getSkolemTracker(unsigned skolemFunctor) const;
void outputRecursiveFunctions() { _skolemReplacement.outputRecursiveFunctions(); }
unsigned numInputSkolems() { return _skolemReplacement.numInputSkolems(); }
void printRecursionMappings();
void printSkolemTrackers();
static void pushEqualityConstraints(LiteralStack* ls, Literal* thenLit, Literal* elseLit);
bool isFunctionComputable(unsigned functor) const;
bool isPredicateComputable(unsigned functor) const;
bool addDeclaredSymbolAnnotatedAsUncomputable(std::pair<unsigned, bool> p) { return _annotatedUncomputable.insert(p); }
bool addIntroducedComputableSymbol(std::pair<unsigned, bool> p) { return _introducedComputable.insert(p); }
bool isComputableOrVar(const Term* t) const;
bool isComputableOrVar(const Literal* l) const;
bool isComputable(const Term* t) const {
ASS(t);
return t->ground() && isComputableOrVar(t);
}
bool isComputable(const Literal* l) const {
ASS(l);
return l->ground() && isComputableOrVar(l);
}
bool isComputable(const Clause* c) const;
protected:
void recordSkolemBinding(Term*,unsigned,std::string) override;
private:
class ConjectureSkolemReplacement : public BottomUpTermTransformer {
public:
ConjectureSkolemReplacement() {}
struct Function {
Function() = default;
Function(unsigned recFunctor, ConjectureSkolemReplacement* replacement);
void addCases(Term* t);
std::string toString() const {
std::string s;
std::string fname = env.signature->getFunction(_functor)->name();
ASS(_cases.size() == _caseHeads->size());
for (unsigned i = 0; i < _cases.size(); ++i) {
s += fname + "(" + (*_caseHeads)[i]->toString();
s += ") = " + _cases[i].toString() + "\n";
}
return s;
}
unsigned _functor;
DArray<TermList> _cases;
std::vector<Term*>* _caseHeads;
DHMap<unsigned, DHMap<Term*, TermList>> _skolemToTermListForCase;
DHMap<Term*, TermList> _skolemToTermList;
};
void bindSkolemToTermList(Term* t, TermList&& tl);
TermList transformTermList(TermList tl, TermList sort);
void addCondPair(unsigned fn, unsigned pred) { _condFnToPred.insert(fn, pred); }
void associateRecMappings(RecursionMappings* m, DHMap<unsigned, std::vector<Term*>>* f) { _recursionMappings = m; _functionHeads = f;}
unsigned numInputSkolems() { return _numInputSkolems; }
void outputRecursiveFunctions();
DHMap<unsigned, std::vector<Term*>>* _functionHeads;
const RecursionMappings* _recursionMappings;
protected:
TermList transformSubterm(TermList trm) override;
private:
unsigned _numInputSkolems = 0;
DHMap<Term*, TermList> _skolemToTermList;
DHMap<unsigned, unsigned> _condFnToPred;
DHMap<unsigned, Function*> _functions;
class SimpleSkolemReplacement : public TermTransformer {
public:
SimpleSkolemReplacement(DHMap<Term*, TermList>* m) : _skolemToTermList(m) {}
void setMap(DHMap<Term*, TermList>* m) { _skolemToTermList = m; }
protected:
TermList transformSubterm(TermList trm) override {
if (trm.isTerm()) {
TermList* res = _skolemToTermList->findPtr(trm.term());
if (res) {
return *res;
}
}
return trm;
}
private:
DHMap<Term*, TermList>* _skolemToTermList;
};
};
bool computableOrVarHelper(const Term* t, DHMap<unsigned, unsigned>* recAncestors) const;
void getNeededUnits(Clause* refutation, ClauseStack& premiseClauses, Stack<Unit*>& conjectures, DHSet<Unit*>& allProofUnits);
Formula* getConditionFromClause(Clause* cl);
Term* translateToSynthesisConditionTerm(Literal* l);
static Term* createRegularITE(Term* condition, TermList thenBranch, TermList elseBranch, TermList branchSort);
static unsigned getITEFunctionSymbol(TermList sort) {
std::string name = "$ite_" + sort.toString();
bool added = false;
unsigned fn = env.signature->addFunction(name, 3, added);
if (added) {
Signature::Symbol* sym = env.signature->getFunction(fn);
sym->setType(OperatorType::getFunctionType({AtomicSort::defaultSort(), sort, sort}, sort));
}
return fn;
}
ConjectureSkolemReplacement _skolemReplacement;
List<std::pair<unsigned,std::pair<Clause*, Literal*>>>* _answerPairs = nullptr;
Literal* _lastAnsLit = nullptr;
RecursionMappings _recursionMappings;
DHMap<unsigned, SkolemTracker*> _skolemTrackers;
DHMap<unsigned, std::vector<Term*>> _functionHeads;
DHSet<std::pair<unsigned, bool>> _annotatedUncomputable;
DHSet<std::pair<unsigned, bool>> _introducedComputable;
};
}
#endif