Require that FMF model basis terms are variables (#3031)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Sat, 1 Jun 2019 07:39:16 +0000 (09:39 +0200)
committerAndres Noetzli <andres.noetzli@gmail.com>
Sat, 1 Jun 2019 07:39:16 +0000 (00:39 -0700)
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.

src/theory/quantifiers/first_order_model.cpp
src/theory/quantifiers/term_database.cpp
src/theory/quantifiers/term_database.h

index 5428d9f1abc1db55d24bc2d49c458f3c94889d01..8d29cb8e12dfde4b5b1695ac295f53096753e9ec 100644 (file)
@@ -328,7 +328,11 @@ Node FirstOrderModel::getModelBasisTerm(TypeNode tn)
       }
       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;
index c4b10eb6f286ece6b684b417e6126cd556ca5bd7..989609a766e0c59a11a1ff88a2625685499fd1e6 100644 (file)
@@ -113,19 +113,26 @@ Node TermDb::getTypeGroundTerm(TypeNode tn, unsigned i) const
   }
 }
 
-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)
index cd5c27f0d2b7552d1eabb4eb816ec8fc28635c65..d58d336733075754e78084e18f30afd1d64a0d6c 100644 (file)
@@ -108,10 +108,11 @@ class TermDb : public QuantifiersUtil {
   */
   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