namespace NumeralMultiplicationGeneralizationImpl
{
template<class NumTraits>
using Numeral = typename NumTraits::ConstantType;
using NumeralMap = Map<Variable, FlatMeetLattice<AnyNumber<Numeral>>, StlHash>;
bool canDivideBy(IntegerConstantType i)
{ return i == IntegerConstantType(1) || i == IntegerConstantType(-1); }
bool canDivideBy(RationalConstantType i)
{ return i != RationalConstantType(0); }
bool canDivideBy(RealConstantType i)
{ return i != RealConstantType(0); }
struct Generalize
{
Variable var;
AnyNumber<Numeral> num;
bool doOrderingCheck;
template<class NumTraits>
Monom<NumTraits> operator()(Monom<NumTraits> monom, PolyNf* evaluatedArgs)
{
using Monom = Monom<NumTraits>;
auto newFactors = perfect(monom.factors->replaceTerms(evaluatedArgs));
for (auto f : monom.factors->iter()) {
if (f.tryVar() == Option<Variable>(var)) {
ASS_EQ(num.downcast<NumTraits>().unwrap(), monom.numeral)
return Monom(Numeral<NumTraits>(1), newFactors);
}
}
return Monom(monom.numeral, newFactors);
}
};
const auto isOne = [](auto x) { return decltype(x)(1) == x; };
SimplifyingGeneratingInference1::Result applyRule(Clause* cl, bool doOrderingCheck)
{
DEBUG("input clause: ", *cl);
NumeralMap numerals;
for (auto poly : iterPolynoms(cl)) {
poly.apply([&](auto& poly) {
for (auto monom : poly->iterSummands()) {
for (auto factor : monom.factors->iter()) {
auto var = factor.term.tryVar();
if (var.isSome()) {
auto numeral = FlatMeetLattice<AnyNumber<Numeral>>(AnyNumber<Numeral>(monom.numeral));
if (factor.power == 1 && canDivideBy(monom.numeral)) {
numerals.updateOrInit(var.unwrap(),
[&](auto n)
{ return n.meet(numeral); },
[&]() { return numeral; });
} else {
ASS_NEQ(factor.power, 0)
numerals.replaceOrInsert(var.unwrap(), FlatMeetLattice<AnyNumber<Numeral>>::bot());
}
}
}
}
});
}
Option<typename NumeralMap::Entry &> selected;
for (auto& e : iterTraits(numerals.iter()) ) {
FlatMeetLattice<AnyNumber<Numeral>> num = e.value();
if (!num.isBot() && !num.unwrap().apply(isOne)) {
if (selected.isNone() || e.key() < selected.unwrap().key()) {
selected = decltype(selected)(e);
}
}
}
if (selected.isNone()) {
DEBUG("not applicable")
return SimplifyingGeneratingInference1::Result::nop(cl);
} else {
auto& e = selected.unwrap();
DEBUG("selected generalization: (", e.key(), ", ", e.value(), ")");
Generalize gen { e.key(), e.value().unwrap(), doOrderingCheck };
return generalizeBottomUp(cl, EvaluateMonom<Generalize> {gen});
}
}
}