Fix quantifiers dynamic split module for parametric datatypes (#7085)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Mon, 30 Aug 2021 19:10:27 +0000 (14:10 -0500)
committerGitHub <noreply@github.com>
Mon, 30 Aug 2021 19:10:27 +0000 (14:10 -0500)
Fixes #6838.

src/theory/datatypes/theory_datatypes_utils.cpp
src/theory/datatypes/theory_datatypes_utils.h
src/theory/quantifiers/quant_split.cpp
test/regress/CMakeLists.txt
test/regress/regress0/quantifiers/issue6838-qpdt.smt2 [new file with mode: 0644]

index 582f11c72ee790958d2254ffd2fd19d5c47a7af4..3b36ad2f294f227a4c8b8e2703819c4aa81fe0f5 100644 (file)
@@ -28,12 +28,11 @@ namespace datatypes {
 namespace utils {
 
 /** get instantiate cons */
-Node getInstCons(Node n, const DType& dt, int index)
+Node getInstCons(Node n, const DType& dt, size_t index)
 {
-  Assert(index >= 0 && index < (int)dt.getNumConstructors());
+  Assert(index dt.getNumConstructors());
   std::vector<Node> children;
   NodeManager* nm = NodeManager::currentNM();
-  children.push_back(dt[index].getConstructor());
   TypeNode tn = n.getType();
   for (unsigned i = 0, nargs = dt[index].getNumArgs(); i < nargs; i++)
   {
@@ -41,30 +40,37 @@ Node getInstCons(Node n, const DType& dt, int index)
         APPLY_SELECTOR_TOTAL, dt[index].getSelectorInternal(tn, i), n);
     children.push_back(nc);
   }
-  Node n_ic = nm->mkNode(APPLY_CONSTRUCTOR, children);
+  Node n_ic = mkApplyCons(tn, dt, index, children);
+  Assert(n_ic.getType() == tn);
+  Assert(static_cast<size_t>(isInstCons(n, n_ic, dt)) == index);
+  return n_ic;
+}
+
+Node mkApplyCons(TypeNode tn,
+                 const DType& dt,
+                 size_t index,
+                 const std::vector<Node>& children)
+{
+  Assert(tn.isDatatype());
+  Assert(index < dt.getNumConstructors());
+  Assert(dt[index].getNumArgs() == children.size());
+  NodeManager* nm = NodeManager::currentNM();
+  std::vector<Node> cchildren;
+  cchildren.push_back(dt[index].getConstructor());
+  cchildren.insert(cchildren.end(), children.begin(), children.end());
   if (dt.isParametric())
   {
     // add type ascription for ambiguous constructor types
-    if (!n_ic.getType().isComparableTo(tn))
-    {
-      Debug("datatypes-parametric")
-          << "DtInstantiate: ambiguous type for " << n_ic << ", ascribe to "
-          << n.getType() << std::endl;
-      Debug("datatypes-parametric")
-          << "Constructor is " << dt[index] << std::endl;
-      TypeNode tspec = dt[index].getSpecializedConstructorType(n.getType());
-      Debug("datatypes-parametric")
-          << "Type specification is " << tspec << std::endl;
-      children[0] = nm->mkNode(APPLY_TYPE_ASCRIPTION,
-                               nm->mkConst(AscriptionType(tspec)),
-                               children[0]);
-      n_ic = nm->mkNode(APPLY_CONSTRUCTOR, children);
-      Assert(n_ic.getType() == tn);
-    }
+    Debug("datatypes-parametric")
+        << "Constructor is " << dt[index] << std::endl;
+    TypeNode tspec = dt[index].getSpecializedConstructorType(tn);
+    Debug("datatypes-parametric")
+        << "Type specification is " << tspec << std::endl;
+    cchildren[0] = nm->mkNode(APPLY_TYPE_ASCRIPTION,
+                              nm->mkConst(AscriptionType(tspec)),
+                              cchildren[0]);
   }
-  Assert(isInstCons(n, n_ic, dt) == index);
-  // n_ic = Rewriter::rewrite( n_ic );
-  return n_ic;
+  return nm->mkNode(APPLY_CONSTRUCTOR, cchildren);
 }
 
 int isInstCons(Node t, Node n, const DType& dt)
index 705e867b9eb0c171f18e8fa69ddf1e1bc64fc64a..1a6e6619ba633bfdf4ec7c1a560f76004f3bdaab 100644 (file)
@@ -34,7 +34,17 @@ namespace utils {
  * This returns the term C( sel^{C,1}( n ), ..., sel^{C,m}( n ) ),
  * where C is the index^{th} constructor of datatype dt.
  */
-Node getInstCons(Node n, const DType& dt, int index);
+Node getInstCons(Node n, const DType& dt, size_t index);
+/**
+ * Apply constructor, taking into account whether the datatype is parametric.
+ *
+ * Return the index^th constructor of dt applied to children, where tn is the
+ * datatype type for dt, instantiated if dt is parametric.
+ */
+Node mkApplyCons(TypeNode tn,
+                 const DType& dt,
+                 size_t index,
+                 const std::vector<Node>& children);
 /** is instantiation cons
  *
  * If this method returns a value >=0, then that value, call it index,
index cc2525b782e8fcd0a300d32d262cb2747c2f3cf7..941b94d234cf451e409ca8b2f7083c2b33fb654b 100644 (file)
 
 #include "expr/dtype.h"
 #include "expr/dtype_cons.h"
-#include "theory/quantifiers/term_database.h"
-#include "theory/quantifiers/first_order_model.h"
 #include "options/quantifiers_options.h"
+#include "theory/datatypes/theory_datatypes_utils.h"
+#include "theory/quantifiers/first_order_model.h"
+#include "theory/quantifiers/term_database.h"
 
 using namespace cvc5::kind;
 
@@ -164,17 +165,18 @@ void QuantDSplit::check(Theory::Effort e, QEffort quant_e)
       for (unsigned j = 0, ncons = dt.getNumConstructors(); j < ncons; j++)
       {
         std::vector<Node> vars;
+        TypeNode dtjtn = dt[j].getSpecializedConstructorType(tn);
+        Assert(dtjtn.getNumChildren() == dt[j].getNumArgs() + 1);
         for (unsigned k = 0, nargs = dt[j].getNumArgs(); k < nargs; k++)
         {
-          TypeNode tns = dt[j][k].getRangeType();
+          TypeNode tns = dtjtn[k];
           Node v = nm->mkBoundVar(tns);
           vars.push_back(v);
         }
         std::vector<Node> bvs_cmb;
         bvs_cmb.insert(bvs_cmb.end(), bvs.begin(), bvs.end());
         bvs_cmb.insert(bvs_cmb.end(), vars.begin(), vars.end());
-        vars.insert(vars.begin(), dt[j].getConstructor());
-        Node c = nm->mkNode(kind::APPLY_CONSTRUCTOR, vars);
+        Node c = datatypes::utils::mkApplyCons(tn, dt, j, vars);
         TNode ct = c;
         Node body = q[1].substitute(svar, ct);
         if (!bvs_cmb.empty())
index ec6d04c1db3090ebade4689a64decdc67185afc5..dca8860fdff1f392965270af80a0251ea05a6c87 100644 (file)
@@ -911,6 +911,7 @@ set(regress_0_tests
   regress0/quantifiers/issue5645-dt-cm-spurious.smt2
   regress0/quantifiers/issue5693-prenex.smt2
   regress0/quantifiers/issue6603-dt-bool-cegqi.smt2
+  regress0/quantifiers/issue6838-qpdt.smt2
   regress0/quantifiers/issue6996-trivial-elim.smt2
   regress0/quantifiers/issue6999-deq-elim.smt2
   regress0/quantifiers/lra-triv-gn.smt2
diff --git a/test/regress/regress0/quantifiers/issue6838-qpdt.smt2 b/test/regress/regress0/quantifiers/issue6838-qpdt.smt2
new file mode 100644 (file)
index 0000000..8aad3c7
--- /dev/null
@@ -0,0 +1,5 @@
+(set-logic ALL)
+(set-info :status unsat)
+(declare-datatype Box (par (A) ((box (unbox A)))))
+(assert (forall ((xy (Box Bool))) (unbox xy)))
+(check-sat)