This PR fixes an issue during variable elimination using equalities in the nonlinear arithmetic solver. We need to make sure that we don't apply the substitutions within terms that are not native arithmetic terms. While we already did that whenever we actually used the resulting term, we did not when we just checked for a possible loop.
Although we always invalidate the substitution cache, the apply method also poisons the actual substitution map. By protecting the calls to apply where we don't actually store the result as well, we avoid this type of "poisoning".
Fixes #8161.
if (d_substitutions->hasSubstitution(l)) continue;
if (expr::hasSubterm(r, l)) continue;
d_substitutions->invalidateCache();
- if (expr::hasSubterm(d_substitutions->apply(r), l)) continue;
+ if (expr::hasSubterm(d_substitutions->apply(r, nullptr, nullptr, &stc), l)) continue;
Trace("nl-eqs") << "Found substitution " << l << " -> " << r
<< std::endl
<< " from " << o << " / " << orig << std::endl;
regress0/nl/issue6547-ran-model.smt2
regress0/nl/issue6619-ran-model.smt2
regress0/nl/issue8135-icp-candidates.smt2
+ regress0/nl/issue8161-var-elim.smt2
regress0/nl/lazard-spurious-root.smt2
regress0/nl/magnitude-wrong-1020-m.smt2
regress0/nl/mult-po.smt2
--- /dev/null
+; EXPECT: sat
+(set-logic QF_NRA)
+(declare-fun r5 () Real)
+(declare-fun r7 () Real)
+(declare-fun r26 () Real)
+(assert (or (= 3 r5) (= r7 0)))
+(assert (and (< r26 0.0) (< r7 r26)))
+(assert (or (> r5 1) (= 0.0 (/ (- r26 (/ r5 0.0)) r7))))
+(check-sat)