Fixes #8147.
// If this function is running, the user gave --check-model (or equivalent),
// and if verbose(1) is on, the user gave --verbose (or equivalent).
- // check-model is not guaranteed to succeed if approximate values were used.
- // Thus, we intentionally abort here.
- if (m->hasApproximations())
- {
- throw RecoverableModalException(
- "Cannot run check-model on a model with approximate values.");
- }
Node sepHeap, sepNeq;
if (m->getHeapModel(sepHeap, sepNeq))
{
const std::set<Node>& termSet)
{
Trace("nl-ext") << "TranscendentalSolver::postProcessModel" << std::endl;
- std::unordered_set<Node> trReps;
+ // map from equivalence classes to a transcendental function application,
+ // if it exists.
+ std::unordered_map<Node, Node> trReps;
for (const Node& n : termSet)
{
if (isTranscendentalKind(n.getKind()))
{
Node r = d_astate.getRepresentative(n);
- trReps.insert(r);
+ trReps[r] = n;
}
}
if (trReps.empty())
Trace("nl-ext") << "...no transcendental functions" << std::endl;
return;
}
- std::vector<Node> rmFromModel;
+ std::unordered_map<Node, Node>::iterator it;
for (auto& am : arithModel)
{
+ // skip integer variables
+ if (am.first.getType().isInteger())
+ {
+ continue;
+ }
Node r = d_astate.getRepresentative(am.first);
- if (trReps.find(r) != trReps.end())
+ it = trReps.find(r);
+ // if it is in the same equivalence class as a trancendental function
+ // application, we replace its value in the model with that application
+ if (it != trReps.end())
{
- Trace("nl-ext") << "...erase value for " << am.first
- << ", since approximate" << std::endl;
- rmFromModel.push_back(am.first);
+ Trace("nl-ext") << "...abstract value for " << am.first << " to "
+ << it->second << std::endl;
+ am.second = it->second;
}
else
{
Trace("nl-ext") << "...keep model value for " << am.first << std::endl;
}
}
- for (const Node& n : rmFromModel)
- {
- arithModel.erase(n);
- }
}
} // namespace transcendental
void checkTranscendentalTangentPlanes();
/**
- * Post-process model. This ensures that the domain of arithModel does not
- * contain terms that are equal to any transcendental function applications,
+ * Post-process model. This ensures that for all terms t in the domain of
+ * arithModel, if t is in the same equivalence class as a transcendental
+ * function application, then arithModel[t] maps to one such application.
+ *
+ * This is to ensure that the linear model is ignored for such terms,
* as their values cannot be properly represented in the model.
+ *
+ * It is important to map such terms t to a transcendental function
+ * application, or otherwise they would be unconstrained, leading to
+ * spurious models.
*/
void postProcessModel(std::map<Node, Node>& arithModel,
const std::set<Node>& termSet);
regress0/nl/nta/exp-n0.5-ub.smt2
regress0/nl/nta/exp-neg2-unsat-unsound.smt2
regress0/nl/nta/exp1-ub.smt2
+ regress0/nl/nta/issue8147-unc-model.smt2
regress0/nl/nta/real-pi.smt2
regress0/nl/nta/sin-sym.smt2
regress0/nl/nta/sqrt-simple.smt2
--- /dev/null
+(set-logic ALL)
+(set-info :status sat)
+(declare-const x Bool)
+(declare-fun a () Real)
+(declare-fun r () Real)
+(declare-fun v () Real)
+(assert (and (xor (= a 1.0) x) (= 1 (- v (exp (* r v))))))
+(check-sat)