#if VZ3
#define DPRINT 0
#include "Lib/Environment.hpp"
#include "Lib/Metaiterators.hpp"
#include "Lib/VirtualIterator.hpp"
#include "Kernel/Clause.hpp"
#include "Kernel/Inference.hpp"
#include "Kernel/Signature.hpp"
#include "Kernel/Term.hpp"
#include "Kernel/Substitution.hpp"
#include "Kernel/TermIterators.hpp"
#include "Kernel/SubstHelper.hpp"
#include "Kernel/OperatorType.hpp"
#include "Kernel/Theory.hpp"
#include "Kernel/FormulaVarIterator.hpp"
#include "Saturation/SaturationAlgorithm.hpp"
#include "Saturation/Splitter.hpp"
#include "Shell/Options.hpp"
#include "Shell/UIHelper.hpp"
#include "SAT/SATLiteral.hpp"
#include "SAT/SAT2FO.hpp"
#include "SAT/Z3Interfacing.hpp"
#include "TheoryInstAndSimp.hpp"
#include "Kernel/NumTraits.hpp"
#include "Kernel/TermIterators.hpp"
#define DEBUG(...)
namespace Inferences
{
using namespace std;
using namespace Lib;
using namespace Kernel;
using namespace Shell;
using namespace Saturation;
using namespace SAT;
using SortId = SAT::Z3Interfacing::SortId;
TheoryInstAndSimp::TheoryInstAndSimp(Options& opts) : TheoryInstAndSimp(
opts.theoryInstAndSimp(),
opts.thiTautologyDeletion(),
opts.showZ3(),
opts.thiGeneralise(),
opts.exportThiProblem(),
opts.problemExportSyntax()
) {}
Options::TheoryInstSimp manageDeprecations(Options::TheoryInstSimp mode)
{
switch (mode) {
case Options::TheoryInstSimp::FULL:
case Options::TheoryInstSimp::NEW:
if(outputAllowed()) {
std::cout << "WARNING: the modes full & new are deprecated for theory instantiation. using all instead." << std::endl;
}
return Options::TheoryInstSimp::ALL;
default:
return mode;
}
}
TheoryInstAndSimp::TheoryInstAndSimp(Options::TheoryInstSimp mode, bool thiTautologyDeletion, bool showZ3, bool generalisation, std::string const& exportSmtlib, Options::ProblemExportSyntax problemExportSyntax)
: _splitter(0)
, _mode(manageDeprecations(mode))
, _thiTautologyDeletion(thiTautologyDeletion)
, _naming()
, _solver(new Z3Interfacing(_naming, showZ3, generalisation, exportSmtlib, problemExportSyntax))
, _generalisation(generalisation)
, _instantiationConstants ("$inst")
, _generalizationConstants("$inst$gen")
{ }
void TheoryInstAndSimp::attach(SaturationAlgorithm* salg)
{
SimplifyingGeneratingInference::attach(salg);
_splitter = salg->getSplitter();
}
bool TheoryInstAndSimp::calcIsSupportedSort(SortId sort)
{
if( sort == IntTraits::sort()
|| sort == RatTraits::sort()
|| sort == RealTraits::sort() ){
return true;
} else if (env.signature->isTermAlgebraSort(sort)) {
return TermAlgebra::subSorts(sort).iter()
.all([&](auto s){ return env.signature->isTermAlgebraSort(s) || calcIsSupportedSort(s); });
} else {
return false;
}
}
bool TheoryInstAndSimp::isSupportedSort(SortId sort)
{ return _supportedSorts.getOrInit(sort, [&](){ return calcIsSupportedSort(sort); }); }
bool TheoryInstAndSimp::isSupportedLiteral(Literal* lit) {
if (lit->isEquality()) {
return isSupportedSort(SortHelper::getEqualityArgumentSort(lit));
}
if (! theory->isInterpretedPredicate(lit->functor())){
return false;
}
for (unsigned i=0; i<lit->numTermArguments(); i++) {
TermList sort = SortHelper::getTermArgSort(lit,i);
if (! isSupportedSort(sort))
return false;
}
switch(theory->interpretPredicate(lit->functor())){
case Theory::INT_IS_RAT:
case Theory::INT_IS_REAL:
case Theory::RAT_IS_RAT:
case Theory::RAT_IS_REAL:
case Theory::REAL_IS_RAT:
case Theory::REAL_IS_REAL:
return false;
default:;
}
return true;
}
bool TheoryInstAndSimp::isSupportedFunction(Term* trm) {
auto sym = env.signature->getFunction(trm->functor());
return !(theory->isInterpretedConstant(trm)
|| (theory->isInterpretedFunction(trm) && isSupportedFunction(theory->interpretFunction(trm)) )
|| (sym->termAlgebraCons() && isSupportedSort(SortHelper::getResultSort(trm)))
|| (sym->termAlgebraDest() && isSupportedSort(SortHelper::getTermArgSort(trm, 0)))
);
}
bool TheoryInstAndSimp::isSupportedFunction(Theory::Interpretation itp) {
switch (itp) {
case Theory::ARRAY_BOOL_SELECT:
case Theory::ARRAY_SELECT:
case Theory::ARRAY_STORE:
case Theory::INT_SUCCESSOR:
case Theory::INT_TO_INT:
case Theory::RAT_TO_RAT:
case Theory::REAL_TO_RAT:
case Theory::REAL_TO_REAL:
return false;
default: return true;
}
}
bool TheoryInstAndSimp::isPure(Literal* lit) {
if (lit->isSpecial()) {
#if DPRINT
cout << "special lit " << lit -> toString() << endl;
#endif
return false;
}
if (! isSupportedLiteral(lit) ) {
return false;
}
NonVariableNonTypeIterator nvi(lit);
while( nvi.hasNext() ) {
Term* term = nvi.next();
if (isSupportedFunction(term)){
return false;
}
if (! isSupportedSort(SortHelper::getResultSort(term))){
return false;
}
for (unsigned i=0; i<term->numTermArguments(); i++) {
TermList sort = SortHelper::getTermArgSort(term,i);
if (! isSupportedSort(sort))
return false;
}
}
#if DPRINT
cout << "found pure literal: " << lit->toString() << endl;
#endif
return true;
}
bool TheoryInstAndSimp::isXeqTerm(TermList left, TermList right) {
bool r = left.isVar() &&
right.isTerm() &&
!VList::member(left.var(), freeVariables(right.term()));
return r;
}
unsigned TheoryInstAndSimp::varOfXeqTerm(const Literal* lit,bool flip) {
ASS(lit->isEquality());
ASS(! lit->isPositive());
if (lit->isEquality()) {
TermList left = lit->termArg(0);
TermList right = lit->termArg(1);
if (isXeqTerm(left,right)){ return left.var();}
if (isXeqTerm(right,left)){ return right.var();}
ASS(lit->isTwoVarEquality());
if(flip){
return left.var();
}else{
return right.var();
}
}
ASSERTION_VIOLATION ;
return -1; }
bool TheoryInstAndSimp::literalContainsVar(const Literal* lit, unsigned v) {
SubtermIterator it(lit);
while (it.hasNext()) {
const TermList t = it.next();
if ((t.isVar()) && (t.var() == v)){
return true;
}
}
return false;
}
Stack<Literal*> TheoryInstAndSimp::selectTrivialLiterals(Clause* cl)
{
#if DPRINT
cout << "selecting trivial literals in " << cl->toString() << endl ;
#endif
auto it = cl->iterLits();
Stack<Literal*> triv_candidates;
Stack<Literal*> nontriv_pure;
Stack<Literal*> impure;
while( it.hasNext() ) {
Literal* c = it.next();
if (isPure(c)) {
if (c->isNegative()
&& c->isEquality()) {
#if DPRINT
cout << "checking " << c->toString() << endl;
#endif
TermList left = c->termArg(0);
TermList right = c->termArg(1);
if (TheoryInstAndSimp::isXeqTerm(left, right) ||
TheoryInstAndSimp::isXeqTerm(right, left) ) {
triv_candidates.push(c);
} else {
if( left.isVar()
&& right.isVar()) {
if (left.var() != right.var()) {
triv_candidates.push(c);
} else {
nontriv_pure.push(c);
}
} else { nontriv_pure.push(c);
}
}
} else {
#if DPRINT
cout << "non trivial pure found " << c->toString() << endl;
#endif
nontriv_pure.push(c);
}
} else { impure.push(c);
}
}
#if DPRINT
cout << "Found " << triv_candidates.length() << " trivial candidates." << endl;
cout << "Found " << nontriv_pure.length() << " nontrivial pure literals." << endl;
cout << "Found " << impure.length() << " impure literals." << endl;
#endif
Stack<Literal*> nt_pure_tocheck(nontriv_pure);
Stack<Literal*> nt_new;
while( ! (nt_pure_tocheck.isEmpty() || triv_candidates.isEmpty()) ) {
Stack<Literal*>::Iterator cand_it(triv_candidates);
while(cand_it.hasNext() ) {
Literal* cand = cand_it.next();
Stack<Literal*>::Iterator tocheck_it(nt_pure_tocheck);
while (tocheck_it.hasNext()) {
Literal* checklit = tocheck_it.next();
if (literalContainsVar(checklit, varOfXeqTerm(cand))) {
nt_new.push(cand);
}
if(cand->isTwoVarEquality() && literalContainsVar(checklit,varOfXeqTerm(cand,true))){
nt_new.push(cand);
}
} } Stack<Literal*>::Iterator nt_new_it(nt_new);
while(nt_new_it.hasNext()) {
triv_candidates.remove(nt_new_it.next());
}
nt_pure_tocheck = nt_new;
}
#if DPRINT
cout << "Found " << triv_candidates.length() << " trivial literals." << endl;
#endif
return triv_candidates;
}
Stack<Literal*> TheoryInstAndSimp::selectTheoryLiterals(Clause* cl) {
#if DPRINT
cout << "selectTheoryLiterals in " << cl->toString() << endl;
#endif
ASS_NEQ(_mode, Shell::Options::TheoryInstSimp::OFF);
Stack<Literal*> trivial_lits = selectTrivialLiterals(cl);
Stack<Literal*> out;
for (auto lit : cl->iterLits()) {
if (isPure(lit) && !trivial_lits.find(lit))
out.push(lit);
}
return out;
}
void TheoryInstAndSimp::filterUninterpretedPartialFunctionDeep(Stack<Literal*>& theoryLits, Stack<Literal*>& filteredLits) {
#if DPRINT
cout << "div zero filtering checking!" << endl;
#endif
Stack<Literal*>::BottomFirstIterator it(theoryLits);
while(it.hasNext()) {
Literal* lit = it.next();
#if DPRINT
cout << "div zero filtering checking: " << lit->toString() << endl;
#endif
bool keep_lit = true;
SubtermIterator sit(lit);
while(sit.hasNext() && keep_lit){
auto ts = sit.next();
if(ts.isTerm()){
Term* t = ts.term();
if( theory->isPartiallyInterpretedFunction(t)
&& theory->partiallyDefinedFunctionUndefinedForArgs(t)
){
keep_lit = false;
#if DPRINT
cout << "division by zero removed: " << lit->toString() << endl;
#endif
}
}
}
if (keep_lit) {
filteredLits.push(lit);
}
}
}
void TheoryInstAndSimp::ConstantCache::reset()
{ for (auto& x : iterTraits(_inner.iter())) x.value().reset(); }
Term* TheoryInstAndSimp::ConstantCache::freshConstant(SortId sort)
{
auto& cache = _inner.getOrInit(sort, [](){
DEBUG("new constant cache for sort ", _inner.size());
return SortedConstantCache();
});
return cache.freshConstant(_prefix, sort);
}
void TheoryInstAndSimp::ConstantCache::SortedConstantCache::reset()
{ _used = 0; }
Term* TheoryInstAndSimp::ConstantCache::SortedConstantCache::freshConstant(const char* prefix, SortId sort)
{
if (_constants.size() == _used) {
unsigned sym = env.signature->addFreshFunction(0, prefix);
env.signature->getFunction(sym)
->setType(OperatorType::getConstantsType(sort));
DEBUG("new constant for sort ", sort, ": ", *env.signature->getFunction(sym));
_constants.push(Term::createConstant(sym));
}
return _constants[_used++];
}
class TheoryInstAndSimp::GeneralisationTree {
TermList _introduced;
unsigned _functor;
Stack<GeneralisationTree> _args;
public:
GeneralisationTree(Term* name, TermList toAbstract, ConstantCache& cache)
: _introduced(TermList(name))
, _functor(toAbstract.term()->functor())
, _args(toAbstract.term()->numTermArguments())
{
for (unsigned i = 0; i < toAbstract.term()->numTermArguments(); i++) {
auto arg = toAbstract.term()->termArg(i);
auto sort = SortHelper::getResultSort(arg.term());
_args.push(GeneralisationTree(cache.freshConstant(sort), arg, cache));
}
}
template<class F>
void foreachDef(F f)
{
Stack<TermList> args(_args.size());
for (auto& a : _args) {
args.push(a._introduced);
a.foreachDef(f);
}
auto definition = TermList(Term::create(_functor, args.size(), args.begin()));
f(*this, Literal::createEquality(true, _introduced, definition, SortHelper::getResultSort(_introduced.term())));
}
TermList buildGeneralTerm(Set<TermList> const& usedDefs, unsigned& freshVar)
{
if (usedDefs.contains(_introduced)) {
Stack<TermList> args(_args.size());
for (auto& a : _args) {
args.push(a.buildGeneralTerm(usedDefs, freshVar));
}
return TermList(Term::create(_functor, args.size(), args.begin()));
} else {
return TermList::var(freshVar++);
}
}
TermList constant() { return _introduced; }
};
Option<Substitution> TheoryInstAndSimp::instantiateGeneralised(
SkolemizedLiterals skolem, unsigned freshVar)
{
auto negatedClause = [](Stack<SATLiteral> lits) -> SATClause*
{
for (auto& lit : lits) {
lit = lit.opposite();
}
return SATClause::fromStack(lits);
};
return _solver->scoped([&]() {
_solver->addClause(negatedClause(skolem.lits));
Stack<SATLiteral> theoryLits;
_generalizationConstants.reset();
Map<SATLiteral, TermList> definitionLiterals;
Stack<GeneralisationTree> gens;
for (auto v : skolem.vars) {
ASS(v < freshVar);
auto sk = skolem.subst.apply(v);
auto val = _solver->evaluateInModel(sk.term());
if (!val) {
return Option<Substitution>();
}
auto gen = GeneralisationTree(sk.term(), TermList(val), _generalizationConstants);
gens.push(gen);
gen.foreachDef([&](GeneralisationTree gen, Literal* l){
auto named = _naming.toSAT(l);
theoryLits.push(named);
definitionLiterals.insert(named, gen.constant());
});
}
DEBUG_CODE(auto res =) _solver->solveUnderAssumptionsLimited(theoryLits, 0);
ASS_EQ(res, Status::UNSATISFIABLE)
Set<TermList> usedDefs;
for (auto& x : _solver->failedAssumptions()) {
definitionLiterals
.tryGet(x)
.andThen([&](TermList t)
{ usedDefs.insert(t); });
}
for (unsigned i = 0; i < skolem.vars.size(); i++) {
skolem.subst.rebind(skolem.vars[i], gens[i].buildGeneralTerm(usedDefs, freshVar));
}
return Option<Substitution>(std::move(skolem.subst));
});
};
Option<Substitution> TheoryInstAndSimp::instantiateWithModel(SkolemizedLiterals skolem)
{
for (auto var : skolem.vars) {
auto ev = _solver->evaluateInModel(skolem.subst.apply(var).term());
if (ev) {
skolem.subst.rebind(var, ev);
} else {
return Option<Substitution>();
}
}
return Option<Substitution>(std::move(skolem.subst));
};
template<class IterLits> TheoryInstAndSimp::SkolemizedLiterals TheoryInstAndSimp::skolemize(IterLits lits)
{
Substitution subst;
Stack<SATLiteral> skolemized;
Stack<unsigned> vars;
_instantiationConstants.reset();
for (auto lit : lits) {
DHMap<unsigned, SortId> srtMap;
SortHelper::collectVariableSorts(lit,srtMap);
TermVarIterator vit(lit);
while(vit.hasNext()){
unsigned var = vit.next();
auto sort = srtMap.get(var);
TermList fc;
if(!subst.findBinding(var,fc)){
Term* fc = _instantiationConstants.freshConstant(sort);
ASS_EQ(SortHelper::getResultSort(fc), sort);
subst.bindUnbound(var,fc);
vars.push(var);
}
}
lit = SubstHelper::apply(lit,subst);
skolemized.push(_naming.toSAT(lit));
}
return SkolemizedLiterals {
.lits = std::move(skolemized),
.vars = std::move(vars),
.subst = std::move(subst),
};
}
VirtualIterator<Solution> TheoryInstAndSimp::getSolutions(Stack<Literal*> const& theoryLiterals, Stack<Literal*> const& guards, unsigned freshVar) {
auto skolemized = skolemize(concatIters(
theoryLiterals.iterFifo(),
guards.iterFifo()
));
DEBUG("skolemized: ", iterTraits(skolemized.lits.iterFifo()).map([&](SATLiteral l){ return _naming.toFO(l)->toString(); }).collect<Stack>())
Status status = _solver->solveUnderAssumptionsLimited(skolemized.lits, 0);
if(status == Status::UNSATISFIABLE) {
DEBUG("unsat")
return pvi(getSingletonIterator(Solution::unsat()));
} else if(status == Status::SATISFIABLE) {
DEBUG("found model: ", _solver->getModel())
auto subst = _generalisation ? instantiateGeneralised(skolemized, freshVar)
: instantiateWithModel(skolemized);
if (subst.isSome()) {
return pvi(getSingletonIterator(Solution(std::move(subst).unwrap())));
} else {
DEBUG("could not build a substitution from model.")
}
} else {
DEBUG("no solution.")
}
return VirtualIterator<Solution>::getEmpty();
}
Clause* instantiate(Clause* original, Substitution& subst, Stack<Literal*> const& theoryLits, Splitter* splitter)
{
RStack<Literal*> instLits;
RStack<Literal*> resLits;
for (Literal* lit : original->iterLits()) {
ASS_REP(SortHelper::areSortsValid(lit), *lit);
Literal* lit_inst = SubstHelper::apply(lit,subst);
SubtermIterator iter(lit_inst);
while (iter.hasNext()) {
DEBUG_CODE(auto t =) iter.next();
ASS_REP(t.isVar() || SortHelper::areSortsValid(t.term()), t);
}
ASS_REP(SortHelper::areSortsValid(lit_inst), *lit_inst);
instLits->push(lit_inst);
if(!theoryLits.find(lit)){
resLits->push(lit_inst);
}
}
Clause* inst = Clause::fromStack(*instLits, GeneratingInference1(InferenceRule::INSTANTIATION,original));
if(splitter){
splitter->onNewClause(inst);
}
return Clause::fromStack(*resLits, SimplifyingInference1(InferenceRule::INTERPRETED_SIMPLIFICATION,inst));
}
struct InstanceFn
{
Clause* operator()(Solution sol, Clause* original,
Stack<Literal*> const& theoryLits,
Stack<Literal*> const& invertedLits,
Stack<Literal*> const& guards,
Splitter* splitter,
TheoryInstAndSimp* parent,
bool& redundant
)
{
if(!sol.sat) {
if(guards.isEmpty()){
redundant = true;
} else {
auto skolem = parent->skolemize(iterTraits(invertedLits.iterFifo() ));
auto status = parent->_solver->solveUnderAssumptionsLimited(skolem.lits, 0);
redundant = status == Status::UNSATISFIABLE;
}
DEBUG("tautology")
return nullptr;
}
return instantiate(original, sol.subst, theoryLits, splitter);
}
};
Stack<Literal*> computeGuards(Stack<Literal*> const& lits)
{
auto findConstructor = [](TermAlgebra* ta, unsigned destructor, bool predicate) -> TermAlgebraConstructor*
{
for (auto ctor : ta->iterCons()) {
for (unsigned i = 0; i < ctor->arity(); i++) {
auto p = ctor->argSort(i) == AtomicSort::boolSort();
auto d = ctor->destructorFunctor(i);
if(destructor == d && predicate == p)
return ctor;
}
}
ASSERTION_VIOLATION
};
auto destructorGuard = [&findConstructor](Term* destr, SortId sort, bool predicate) -> Literal*
{
auto ctor = findConstructor(env.signature->getTermAlgebraOfSort(sort), destr->functor(), predicate);
auto discr = ctor->discriminator();
TermStack args;
for (unsigned i = 0; i < destr->numTypeArguments(); i++) {
args.push(destr->typeArg(i));
}
args.push(destr->termArg(0));
return Literal::create(discr, args.size(), true, args.begin());
};
Stack<Literal*> out;
for (auto lit : lits) {
auto predSym = env.signature->getPredicate(lit->functor());
if (predSym->termAlgebraDest()) {
out.push(destructorGuard(lit, predSym->predType()->arg(0), true));
}
SubtermIterator it(lit);
for (auto t = it.next(); it.hasNext(); t = it.next()) {
ASS_REP(t.isVar() || !t.term()->isLiteral(), t);
if (t.isTerm()) {
auto term = t.term();
auto sym = env.signature->getFunction(t.term()->functor());
auto fun = term->functor();
if (theory->isInterpretedNumber(term)) {
} else if (theory->isInterpretedFunction(fun) || theory->isInterpretedConstant(fun)) {
switch (theory->interpretFunction(fun)) {
case Theory::REAL_QUOTIENT:
case Theory::REAL_REMAINDER_E:
case Theory::REAL_QUOTIENT_F:
case Theory::REAL_QUOTIENT_T:
case Theory::REAL_REMAINDER_T:
case Theory::REAL_REMAINDER_F:
out.push(Literal::createEquality(false, RealTraits::zero(), term->termArg(1), RealTraits::sort()));
break;
case Theory::RAT_QUOTIENT:
case Theory::RAT_QUOTIENT_T:
case Theory::RAT_REMAINDER_T:
case Theory::RAT_QUOTIENT_F:
case Theory::RAT_REMAINDER_F:
case Theory::RAT_REMAINDER_E:
out.push(Literal::createEquality(false, RatTraits::zero(), term->termArg(1), RatTraits::sort()));
break;
case Theory::INT_QUOTIENT_F:
case Theory::INT_REMAINDER_F:
case Theory::INT_QUOTIENT_E:
case Theory::INT_QUOTIENT_T:
case Theory::INT_REMAINDER_T:
case Theory::INT_REMAINDER_E:
out.push(Literal::createEquality(false, IntTraits::zero(), term->termArg(1), IntTraits::sort()));
break;
default:;
}
} else if (sym->termAlgebraDest()) {
out.push(destructorGuard(term, sym->fnType()->arg(0), false));
}
}
}
}
return out;
}
Stack<Literal*> filterLiterals(Stack<Literal*> lits, Options::TheoryInstSimp mode)
{
auto isStrong = [](Literal* lit) -> bool
{ return ( lit->isEquality() && lit->isNegative())
|| (!lit->isEquality() && theory->isInterpretedPredicate(lit->functor())); };
auto freeVars = [](Literal* lit)
{ return iterTraits(VList::Iterator(freeVariables(lit))); };
switch(mode) {
case Options::TheoryInstSimp::ALL:
return lits;
case Options::TheoryInstSimp::STRONG:
return iterTraits(lits.iterFifo())
.filter(isStrong)
.collect<Stack>();
case Options::TheoryInstSimp::NEG_EQ:
return iterTraits(lits.iterFifo())
.filter([](Literal* lit)
{ return lit->isEquality() && lit->isNegative(); } )
.collect<Stack>();
case Options::TheoryInstSimp::OVERLAP:
{
Set<unsigned> strongVars;
for (auto l : lits) {
if (isStrong(l)) {
for (auto v : freeVars(l)) {
strongVars.insert(v);
}
}
}
return iterTraits(lits.iterFifo())
.filter([&](Literal* lit)
{ return freeVars(lit)
.any([&](unsigned var)
{ return strongVars.contains(var); }); })
.collect<Stack>();
}
case Options::TheoryInstSimp::FULL:
case Options::TheoryInstSimp::NEW:
case Options::TheoryInstSimp::OFF:
ASSERTION_VIOLATION
}
ASSERTION_VIOLATION
}
unsigned getFreshVar(Clause& clause)
{
unsigned freshVar = 0;
for (unsigned i = 0; i < clause.size(); i++) {
VariableIterator iter(clause[i]);
while(iter.hasNext()) {
auto var = iter.next();
if (freshVar <= var.var()) {
freshVar = var.var() + 1;
}
}
}
return freshVar;
}
SimplifyingGeneratingInference::ClauseGenerationResult TheoryInstAndSimp::generateSimplify(Clause* premise)
{
auto empty = ClauseGenerationResult {
.clauses = ClauseIterator::getEmpty(),
.premiseRedundant = false,
};
if(premise->isPureTheoryDescendant()){
return empty;
}
Stack<Literal*> selectedLiterals = selectTheoryLiterals(premise);
selectedLiterals = filterLiterals(std::move(selectedLiterals), _mode);
if(selectedLiterals.isEmpty()){
return empty;
}
#if VTIME_PROFILING
static const char* THEORY_INST_SIMP = "theory instantiation";
#endif
auto guards = computeGuards(selectedLiterals);
DEBUG("input: ", *premise);
DEBUG("selected literals: ", iterTraits(selectedLiterals.iterFifo())
.map([](Literal* l) -> std::string { return l->toString(); })
.collect<Stack>())
DEBUG("guards: ", iterTraits(guards.iterFifo())
.map([](Literal* l) -> std::string { return l->toString(); })
.collect<Stack>())
TIME_TRACE(THEORY_INST_SIMP);
auto invertedLiterals = iterTraits(selectedLiterals.iterFifo())
.map(Literal::complementaryLiteral)
.collect<Stack>();
bool premiseRedundant = false;
auto it1 = iterTraits(getSolutions(invertedLiterals, guards, getFreshVar(*premise)))
.map([&](Solution s) {
DEBUG("found solution: ", s);
return InstanceFn{}(s, premise, selectedLiterals, invertedLiterals, guards, _splitter, this, premiseRedundant);
})
.filter([](Clause* cl) { return cl != nullptr; });
auto it2 = TIME_TRACE_ITER(THEORY_INST_SIMP, std::move(it1));
auto clauses = getPersistentIterator(std::move(it2));
if (premiseRedundant && _thiTautologyDeletion) {
return ClauseGenerationResult {
.clauses = ClauseIterator::getEmpty(),
.premiseRedundant = true,
};
} else {
return ClauseGenerationResult {
.clauses = std::move(clauses),
.premiseRedundant = false,
};
}
}
bool TheoryInstAndSimp::isTheoryLemma(Clause* cl, bool& couldNotCheck) {
static TheoryInstAndSimp checker(
Options::TheoryInstSimp::ALL,
true,
false,
false,
"", Options::ProblemExportSyntax::SMTLIB);
if (!forAll(cl->iterLits(),[](auto l){ return checker.isPure(l); })) {
couldNotCheck = true;
return true;
}
auto invertedLiterals = iterTraits(cl->iterLits())
.map(Literal::complementaryLiteral)
.collect<Stack>();
static Stack<Literal*> empty;
auto solutions = checker.getSolutions(invertedLiterals,empty,0);
ASS_REP(solutions.hasNext(),cl->toString())
return !solutions.next().sat;
}
}
std::ostream& operator<<(std::ostream& out, Inferences::Solution const& self)
{ return out << "Solution(" << (self.sat ? "sat" : "unsat") << ", " << self.subst << ")"; }
#endif