Fixes for higher-order (#1405)
authorAndrew Reynolds <andrew.j.reynolds@gmail.com>
Sat, 25 Nov 2017 20:12:00 +0000 (14:12 -0600)
committerGitHub <noreply@github.com>
Sat, 25 Nov 2017 20:12:00 +0000 (14:12 -0600)
src/theory/quantifiers/ho_trigger.cpp
src/theory/quantifiers/ho_trigger.h
src/theory/quantifiers/term_util.cpp
src/theory/quantifiers/trigger.cpp
test/regress/regress0/ho/Makefile.am

index 0386c0cf04104c10e66d27e17c61c6b99ad76657..6354047cfc00189453fc46196719ce7fb33256a1 100644 (file)
@@ -72,45 +72,87 @@ HigherOrderTrigger::HigherOrderTrigger(
 
 HigherOrderTrigger::~HigherOrderTrigger() {}
 void HigherOrderTrigger::collectHoVarApplyTerms(
-    Node q, TNode n, std::map<Node, std::vector<Node> >& apps)
+    Node q, Node& n, std::map<Node, std::vector<Node> >& apps)
 {
   std::vector<Node> ns;
   ns.push_back(n);
   collectHoVarApplyTerms(q, ns, apps);
+  Assert(ns.size() == 1);
+  n = ns[0];
 }
 
 void HigherOrderTrigger::collectHoVarApplyTerms(
     Node q, std::vector<Node>& ns, std::map<Node, std::vector<Node> >& apps)
 {
-  std::unordered_set<TNode, TNodeHashFunction> visited;
+  std::unordered_map<TNode, Node, TNodeHashFunction> visited;
+  std::unordered_map<TNode, Node, TNodeHashFunction>::iterator it;
   // whether the visited node is a child of a HO_APPLY chain
   std::unordered_map<TNode, bool, TNodeHashFunction> withinApply;
-  std::stack<TNode> visit;
+  std::vector<TNode> visit;
   TNode cur;
-  for (unsigned i = 0; i < ns.size(); i++)
+  for (unsigned i = 0, size = ns.size(); i < size; i++)
   {
-    visit.push(ns[i]);
+    visit.push_back(ns[i]);
     withinApply[ns[i]] = false;
     do
     {
-      cur = visit.top();
-      visit.pop();
+      cur = visit.back();
+      visit.pop_back();
 
-      if (visited.find(cur) == visited.end())
+      it = visited.find(cur);
+      if (it == visited.end())
       {
-        visited.insert(cur);
-        bool curWithinApply = withinApply[cur];
-        if (!curWithinApply)
+        // do not look in nested quantifiers
+        if (cur.getKind() == FORALL)
+        {
+          visited[cur] = cur;
+        }
+        else
+        {
+          bool curWithinApply = withinApply[cur];
+          visited[cur] = Node::null();
+          visit.push_back(cur);
+          for (unsigned j = 0, size = cur.getNumChildren(); j < size; j++)
+          {
+            withinApply[cur[j]] = curWithinApply && j == 0;
+            visit.push_back(cur[j]);
+          }
+        }
+      }
+      else if (it->second.isNull())
+      {
+        // carry the conversion
+        Node ret = cur;
+        bool childChanged = false;
+        std::vector<Node> children;
+        if (cur.getMetaKind() == kind::metakind::PARAMETERIZED)
+        {
+          children.push_back(cur.getOperator());
+        }
+        for (const Node& nc : cur)
+        {
+          it = visited.find(nc);
+          Assert(it != visited.end());
+          Assert(!it->second.isNull());
+          childChanged = childChanged || nc != it->second;
+          children.push_back(it->second);
+        }
+        if (childChanged)
+        {
+          ret = NodeManager::currentNM()->mkNode(cur.getKind(), children);
+        }
+        // now, convert and store the application
+        if (!withinApply[cur])
         {
           TNode op;
-          if (cur.getKind() == kind::APPLY_UF)
+          if (ret.getKind() == kind::APPLY_UF)
           {
             // could be a fully applied function variable
-            op = cur.getOperator();
+            op = ret.getOperator();
           }
-          else if (cur.getKind() == kind::HO_APPLY)
+          else if (ret.getKind() == kind::HO_APPLY)
           {
-            op = cur;
+            op = ret;
             while (op.getKind() == kind::HO_APPLY)
             {
               op = op[0];
@@ -120,42 +162,27 @@ void HigherOrderTrigger::collectHoVarApplyTerms(
           {
             if (op.getKind() == kind::INST_CONSTANT)
             {
-              Assert(quantifiers::TermUtil::getInstConstAttr(cur) == q);
+              Assert(quantifiers::TermUtil::getInstConstAttr(ret) == q);
               Trace("ho-quant-trigger-debug")
-                  << "Ho variable apply term : " << cur << " with head " << op
+                  << "Ho variable apply term : " << ret << " with head " << op
                   << std::endl;
-              Node app = cur;
-              if (app.getKind() == kind::APPLY_UF)
+              if (ret.getKind() == kind::APPLY_UF)
               {
+                Node prev = ret;
                 // for consistency, convert to HO_APPLY if fully applied
-                app = uf::TheoryUfRewriter::getHoApplyForApplyUf(app);
+                ret = uf::TheoryUfRewriter::getHoApplyForApplyUf(ret);
               }
-              apps[op].push_back(cur);
-            }
-            if (cur.getKind() == kind::HO_APPLY)
-            {
-              curWithinApply = true;
+              apps[op].push_back(ret);
             }
           }
         }
-        else
-        {
-          if (cur.getKind() != HO_APPLY)
-          {
-            curWithinApply = false;
-          }
-        }
-        // do not look in nested quantifiers
-        if (cur.getKind() != FORALL)
-        {
-          for (unsigned i = 0, size = cur.getNumChildren(); i < size; i++)
-          {
-            withinApply[cur[i]] = curWithinApply && i == 0;
-            visit.push(cur[i]);
-          }
-        }
+        visited[cur] = ret;
       }
     } while (!visit.empty());
+
+    // store the conversion
+    Assert(visited.find(ns[i]) != visited.end());
+    ns[i] = visited[ns[i]];
   }
 }
 
index 16d676353432c0e90a4a9fbae120af0e16df021c..e5112abcedcae427d30a12a0a2889dfa7ac20d59 100644 (file)
@@ -101,16 +101,18 @@ class HigherOrderTrigger : public Trigger
  public:
   /** Collect higher order var apply terms
    *
-   * Collect all top-level HO_APPLY terms in n whose head is a variable in
-   * quantified formula q. Append all such terms in apps.
+   * Collect all top-level HO_APPLY terms in n whose head is a variable x in
+   * quantified formula q. Append all such terms in apps[x].
+   * This method may modify n so that it is in the expected form required for
+   * higher-order matching, in particular, APPLY_UF terms with variable
+   * operators are converted to curried applications of HO_APPLY.
    */
   static void collectHoVarApplyTerms(Node q,
-                                     TNode n,
+                                     Node& n,
                                      std::map<Node, std::vector<Node> >& apps);
   /** Collect higher order var apply terms
    *
-   * Collect all top-level HO_APPLY terms in terms ns whose head is a variable
-   * in quantified formula q, store in apps.
+   * Same as above, but with multiple terms ns.
    */
   static void collectHoVarApplyTerms(Node q,
                                      std::vector<Node>& ns,
index 4e75f7df89cda8eb4cae5f8001cd36b2cacdbf1d..def9a68bcb1af8f54c53df0746787ec4be83c75f 100644 (file)
@@ -113,10 +113,19 @@ Node TermUtil::getRemoveQuantifiers2( Node n, std::map< Node, Node >& visited )
 Node TermUtil::getInstConstAttr( Node n ) {
   if (!n.hasAttribute(InstConstantAttribute()) ){
     Node q;
-    for( unsigned i=0; i<n.getNumChildren(); i++ ){
-      q = getInstConstAttr(n[i]);
-      if( !q.isNull() ){
-        break;
+    if (n.hasOperator())
+    {
+      q = getInstConstAttr(n.getOperator());
+    }
+    if (q.isNull())
+    {
+      for (const Node& nc : n)
+      {
+        q = getInstConstAttr(nc);
+        if (!q.isNull())
+        {
+          break;
+        }
       }
     }
     InstConstantAttribute ica;
@@ -277,6 +286,10 @@ void TermUtil::computeVarContains2( Node n, Kind k, std::vector< Node >& varCont
         varContains.push_back( n );
       }
     }else{
+      if (n.hasOperator())
+      {
+        computeVarContains2(n.getOperator(), k, varContains, visited);
+      }
       for( unsigned i=0; i<n.getNumChildren(); i++ ){
         computeVarContains2( n[i], k, varContains, visited );
       }
index 61920250e0d274e3b7df0926faa6d23c5c5a726b..d06b5268b9c17d6289d2737087683c34165fbc5a 100644 (file)
@@ -223,6 +223,8 @@ Trigger* Trigger::mkTrigger( QuantifiersEngine* qe, Node f, std::vector< Node >&
   Trace("trigger") << "Collect higher-order variable triggers..." << std::endl;
   std::map<Node, std::vector<Node> > ho_apps;
   HigherOrderTrigger::collectHoVarApplyTerms(f, trNodes, ho_apps);
+  Trace("trigger") << "...got " << ho_apps.size()
+                   << " higher-order applications." << std::endl;
   Trigger* t;
   if (!ho_apps.empty())
   {
index b6c494d29bdc168e41b4b3f04fa00c5563c839cd..4a7ceb96f5f62106b9679c64ab289fb2b7a07f79 100644 (file)
@@ -37,18 +37,16 @@ TESTS = \
   ho-std-fmf.smt2 \
   fta0409.smt2 \
   auth0068.smt2 \
-  modulo-func-equality.smt2
-
+  modulo-func-equality.smt2 \
+  ho-matching-enum.smt2 \
+  ho-matching-enum-2.smt2 \
+  ho-matching-nested-app.smt2 \
+  simple-matching.smt2 \
+  simple-matching-partial.smt2
+  
 EXTRA_DIST = $(TESTS)
 
-# need PR 1204 : 
-
 # hoa0102.smt2
-# ho-matching-enum.smt2 
-# ho-matching-enum-2.smt2
-# ho-matching-nested-app.smt2
-# simple-matching.smt2
-# simple-matching-partial.smt2
 
 
 #if CVC4_BUILD_PROFILE_COMPETITION