The commit fixes an issue where FMF could theoretically chose interpreted function applications as "model basis terms". This triggered an incorrect model (caught by an AlwaysAssert) when the interpreted function later did not appear in a model and was chosen by FMF to be equal to a wrong value.
}
else
{
- mbt = d_qe->getTermDatabase()->getOrMakeTypeGroundTerm(tn);
+ // The model basis term cannot be an interpreted function, or else we
+ // may produce an inconsistent model by choosing an arbitrary
+ // equivalence class for it. Hence, we require that it be an existing or
+ // fresh variable.
+ mbt = d_qe->getTermDatabase()->getOrMakeTypeGroundTerm(tn, true);
}
}
ModelBasisAttribute mba;
}
}
-Node TermDb::getOrMakeTypeGroundTerm(TypeNode tn)
+Node TermDb::getOrMakeTypeGroundTerm(TypeNode tn, bool reqVar)
{
std::map<TypeNode, std::vector<Node> >::const_iterator it =
d_type_map.find(tn);
if (it != d_type_map.end())
{
Assert(!it->second.empty());
- return it->second[0];
- }
- else
- {
- return getOrMakeTypeFreshVariable(tn);
+ if (!reqVar)
+ {
+ return it->second[0];
+ }
+ for (const Node& v : it->second)
+ {
+ if (v.isVar())
+ {
+ return v;
+ }
+ }
}
+ return getOrMakeTypeFreshVariable(tn);
}
Node TermDb::getOrMakeTypeFreshVariable(TypeNode tn)
*/
Node getTypeGroundTerm(TypeNode tn, unsigned i) const;
/** get or make ground term
- * Returns the first ground term of type tn,
- * or makes one if none exist.
- */
- Node getOrMakeTypeGroundTerm(TypeNode tn);
+ *
+ * Returns the first ground term of type tn, or makes one if none exist. If
+ * reqVar is true, then the ground term must be a variable.
+ */
+ Node getOrMakeTypeGroundTerm(TypeNode tn, bool reqVar = false);
/** make fresh variable
* Returns a fresh variable of type tn.
* This will return only a single fresh