#include "EqFactoring.hpp"
#include "Debug/TimeProfiling.hpp"
#define DEBUG(...)
namespace Inferences {
namespace ALASCA {
void EqFactoring::attach(SaturationAlgorithm* salg)
{ }
void EqFactoring::detach()
{ }
Option<Clause*> EqFactoring::applyRule(SelectedEquality const& l1, SelectedEquality const& l2)
{
TIME_TRACE("alasca equality factoring application")
DEBUG("============")
DEBUG("l1: ", l1)
DEBUG("l2: ", l2)
auto unifySorts = [](auto s1, auto s2) -> Option<TermList> {
static RobSubstitution subst;
if (!subst.unify(s1, 0, s2, 0)) {
return Option<TermList>();
} else {
ASS_EQ(subst.apply(s1,0), subst.apply(s2,0))
return Option<TermList>(subst.apply(s1, 0));
}
};
auto nothing = [&]() { return Option<Clause*>(); };
auto s1 = l1.biggerSide();
auto s2 = l2.biggerSide();
auto t1 = l1.smallerSide();
auto t2 = l2.smallerSide();
ASS (l1.positive() && l2.positive())
ASS(!l1.isFracNum() || !l1.biggerSide().isVar())
ASS(!l2.isFracNum() || !l2.biggerSide().isVar())
#define check_side_condition(cond, cond_code) \
if (!(cond_code)) { \
DEBUG("side condition not fulfilled: ", cond) \
return nothing(); \
} \
auto srt_ = unifySorts(
SortHelper::getEqualityArgumentSort(l1.literal()),
SortHelper::getEqualityArgumentSort(l2.literal())
);
check_side_condition(
"s1 and s2 are of unifyable sorts",
srt_.isSome())
auto& srt = srt_.unwrap();
auto uwa = _shared->unify(s1, s2);
check_side_condition(
"uwa(s1,s2) = ⟨σ,Cnst⟩",
uwa.isSome())
auto sigma = [&](auto t) { return uwa->subs().apply(t, 0); };
auto cnst = uwa->computeConstraintLiterals();
Stack<Literal*> concl(l1.clause()->size() + cnst->size());
auto L2σ = sigma(l2.literal());
check_side_condition(
"(s2 ≈ t2)σ /< (s1 ≈ t1 \\/ C)σ",
l2.contextLiterals()
.all([&](auto L) {
auto Lσ = sigma(L);
concl.push(Lσ);
return _shared->notLess(L2σ, Lσ);
}))
auto s1σ = sigma(s1);
auto s2σ = sigma(s2);
auto t1σ = sigma(t1);
auto t2σ = sigma(t2);
check_side_condition( "s1σ /⪯ t1σ", _shared->notLeq(s1σ.untyped(), t1σ))
check_side_condition( "s2σ /⪯ t2σ", _shared->notLeq(s2σ.untyped(), t1σ))
auto res = Literal::createEquality(false, t1σ, t2σ, srt);
concl.push(res);
concl.loadFromIterator(cnst->iterFifo());
Inference inf(GeneratingInference1(Kernel::InferenceRule::ALASCA_EQ_FACTORING, l1.clause()));
auto out = Clause::fromStack(concl, inf);
DEBUG("out: ", *out);
return Option<Clause*>(out);
}
ClauseIterator EqFactoring::generateClauses(Clause* premise)
{
TIME_TRACE("alasca equality factoring generate")
DEBUG("in: ", *premise)
auto selected = Lib::make_shared(
_shared->selectedEqualities(premise,
SelectionCriterion::NOT_LESS,
SelectionCriterion::NOT_LEQ,
false)
.filter([](auto& s) { return s.positive(); })
.template collect<Stack>());
auto rest = Lib::make_shared(
_shared->selectedEqualities(premise,
SelectionCriterion::ANY,
SelectionCriterion::NOT_LEQ,
false)
.filter([](auto& s) { return s.positive(); })
.template collect<Stack>());
return pvi(range(0, selected->size())
.flatMap([=](auto i) {
return range(0, rest->size())
.filter([=](auto j) { return (*selected)[i].litIdx() != (*rest)[j].litIdx(); })
.flatMap([=](auto j) {
auto& max = (*selected)[i];
auto& other = (*rest)[j];
return ifElseIter(
max.literal() == other.literal() && other.litIdx() < max.litIdx(),
[&]() { return arrayIter(Stack<Clause*>{}); },
[&]() { return concatIters(applyRule(other, max).intoIter()); });
});
}));
}
} }