Set Constant's normal form and other short fixes
authorKshitij Bansal <kshitij@cs.nyu.edu>
Mon, 10 Nov 2014 18:11:20 +0000 (13:11 -0500)
committerKshitij Bansal <kshitij@cs.nyu.edu>
Wed, 19 Nov 2014 01:29:45 +0000 (20:29 -0500)
Other short fixes:
* use debug tag "theory::assertions::fulleffort" to dump assertions only at FULL_EFFORT
* theoryof-mode fix in smt_engine.cpp
* hack in TheoryModel::getModelValue [TODO: notify Clark/Andy]
* Lemma generation when it rewrites to true/false fix
* TermInfoManager::addTerm(..) fix
* Move SUBSET rewrite to preRewrite
* On preRegister, queue up propagation to be done upfront
** Hospital4 fails when all other fixes have been applied but not this one. Good to have an actual benchmark which relies on this code.
* TheorySetsProperties::getCardinality(..) fix

Thanks to Alvise Rabitti and Stefano Calzavara for reporting some of these; and to Morgan and Clark for help in fixing!

src/smt/smt_engine.cpp
src/theory/sets/normal_form.h
src/theory/sets/theory_sets_private.cpp
src/theory/sets/theory_sets_private.h
src/theory/sets/theory_sets_rewriter.cpp
src/theory/sets/theory_sets_type_enumerator.h
src/theory/sets/theory_sets_type_rules.h
src/theory/theory_engine.cpp

index a80177429f45151e8cfa41c65a375e7a2d6a9158..86b0faaf676546d1f0c17f60f1341fac0e2267e0 100644 (file)
@@ -1029,7 +1029,10 @@ void SmtEngine::setDefaults() {
 
   // Set the options for the theoryOf
   if(!options::theoryOfMode.wasSetByUser()) {
-    if(d_logic.isSharingEnabled() && !d_logic.isTheoryEnabled(THEORY_BV) && !d_logic.isTheoryEnabled(THEORY_STRINGS)) {
+    if(d_logic.isSharingEnabled() &&
+       !d_logic.isTheoryEnabled(THEORY_BV) &&
+       !d_logic.isTheoryEnabled(THEORY_STRINGS) &&
+       !d_logic.isTheoryEnabled(THEORY_SETS) ) {
       Trace("smt") << "setting theoryof-mode to term-based" << endl;
       options::theoryOfMode.set(THEORY_OF_TERM_BASED);
     }
@@ -1057,7 +1060,10 @@ void SmtEngine::setDefaults() {
   } else {
     Theory::setUninterpretedSortOwner(THEORY_UF);
   }
+
   // Turn on ite simplification for QF_LIA and QF_AUFBV
+  // WARNING: These checks match much more than just QF_AUFBV and
+  // QF_LIA logics. --K [2014/10/15]
   if(! options::doITESimp.wasSetByUser()) {
     bool qf_aufbv = !d_logic.isQuantified() &&
       d_logic.isTheoryEnabled(THEORY_ARRAY) &&
index bc34ea6f1ebe29b4ada06febd31d21a3202ee1da..13da6d57ea33f68fa036da1c65564be3bc2872ec 100644 (file)
@@ -26,7 +26,8 @@ namespace sets {
 class NormalForm {
 public:
 
-  static Node elementsToSet(std::set<TNode> elements, TypeNode setType)
+  template<bool ref_count>
+  static Node elementsToSet(std::set<NodeTemplate<ref_count> > elements, TypeNode setType)
   {
     NodeManager* nm = NodeManager::currentNM();
 
@@ -43,6 +44,63 @@ public:
     }
   }
 
+  static bool checkNormalConstant(TNode n) {
+    Debug("sets-checknormal") << "[sets-checknormal] checkNormal " << n << " :" << std::endl;
+    if(n.getKind() == kind::EMPTYSET) {
+      return true;
+    } else if(n.getKind() == kind::SINGLETON) {
+      return n[0].isConst();
+    } else if(n.getKind() == kind::UNION) {
+
+      // assuming (union ... (union {SmallestNodeID} {BiggerNodeId}) ... {BiggestNodeId})
+
+      // store BiggestNodeId in prvs
+      if(n[1].getKind() != kind::SINGLETON) return false;
+      if( !n[1][0].isConst() ) return false;
+      Debug("sets-checknormal") << "[sets-checknormal]              frst element = " << n[1][0] << " " << n[1][0].getId() << std::endl;
+      TNode prvs = n[1][0];
+      n = n[0];
+
+      // check intermediate nodes
+      while(n.getKind() == kind::UNION) {
+       if(n[1].getKind() != kind::SINGLETON) return false;
+       if( !n[1].isConst() ) return false;
+       Debug("sets-checknormal") << "[sets-checknormal]              element = " << n[1][0] << " " << n[1][0].getId() << std::endl;
+       if( n[1][0] >= prvs ) return false;
+       TNode prvs = n[1][0];
+       n = n[0];
+      }
+
+      // check SmallestNodeID is smallest
+      if(n.getKind() != kind::SINGLETON) return false;
+      if( !n[0].isConst() ) return false;
+      Debug("sets-checknormal") << "[sets-checknormal]              lst element = " << n[0] << " " << n[0].getId() << std::endl;
+      if( n[0] >= prvs ) return false;
+
+      // we made it
+      return true;
+
+    } else {
+      return false;
+    }
+  }
+
+  static std::set<Node> getElementsFromNormalConstant(TNode n) {
+    Assert(n.isConst());
+    std::set<Node> ret;
+    if(n.getKind() == kind::EMPTYSET) {
+      return ret;
+    }
+    while(n.getKind() == kind::UNION) {
+      Assert(n[1].getKind() == kind::SINGLETON);
+      ret.insert(ret.begin(), n[1][0]);
+      n = n[0];
+    }
+    Assert(n.getKind() == kind::SINGLETON);
+    ret.insert(n[0]);
+    return ret;
+  }
+
 };
 
 }
index 55bd0eefdf85a1d3ad7fc7287b73be8d21440cf4..e229d3a6f9a401eee16bef04288fe9796564f918 100644 (file)
@@ -732,7 +732,7 @@ Node TheorySetsPrivate::elementsToShape(Elements elements, TypeNode setType) con
   NodeManager* nm = NodeManager::currentNM();
 
   if(elements.size() == 0) {
-    return nm->mkConst(EmptySet(nm->toType(setType)));
+    return nm->mkConst<EmptySet>(EmptySet(nm->toType(setType)));
   } else {
     Elements::iterator it = elements.begin();
     Node cur = SINGLETON(*it);
@@ -747,7 +747,7 @@ Node TheorySetsPrivate::elementsToShape(set<Node> elements, TypeNode setType) co
   NodeManager* nm = NodeManager::currentNM();
 
   if(elements.size() == 0) {
-    return nm->mkConst(EmptySet(nm->toType(setType)));
+    return nm->mkConst<EmptySet>(EmptySet(nm->toType(setType)));
   } else {
     typeof(elements.begin()) it = elements.begin();
     Node cur = SINGLETON(*it);
@@ -765,18 +765,20 @@ void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel)
 
   set<Node> terms;
 
+  if(Trace.isOn("sets-assertions")) {
+    dumpAssertionsHumanified();
+  }
+
   // Compute terms appearing assertions and shared terms
   d_external.computeRelevantTerms(terms);
 
   // Compute for each setterm elements that it contains
   SettermElementsMap settermElementsMap;
-  TNode true_atom = NodeManager::currentNM()->mkConst<bool>(true);
-  TNode false_atom = NodeManager::currentNM()->mkConst<bool>(false);
-  for(eq::EqClassIterator it_eqclasses(true_atom, &d_equalityEngine);
+  for(eq::EqClassIterator it_eqclasses(d_trueNode, &d_equalityEngine);
       ! it_eqclasses.isFinished() ; ++it_eqclasses) {
     TNode n = (*it_eqclasses);
     if(n.getKind() == kind::MEMBER) {
-      Assert(d_equalityEngine.areEqual(n, true_atom));
+      Assert(d_equalityEngine.areEqual(n, d_trueNode));
       TNode x = d_equalityEngine.getRepresentative(n[0]);
       TNode S = d_equalityEngine.getRepresentative(n[1]);
       settermElementsMap[S].insert(x);
@@ -793,7 +795,7 @@ void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel)
   }
 
   if(Debug.isOn("sets-model-details")) {
-    for(eq::EqClassIterator it_eqclasses(false_atom, &d_equalityEngine);
+    for(eq::EqClassIterator it_eqclasses(d_trueNode, &d_equalityEngine);
         ! it_eqclasses.isFinished() ; ++it_eqclasses) {
       TNode n = (*it_eqclasses);
       vector<TNode> explanation;
@@ -854,8 +856,8 @@ void TheorySetsPrivate::collectModelInfo(TheoryModel* m, bool fullModel)
       checkPassed &= checkModel(settermElementsMap, term);
     }
   }
-  if(Debug.isOn("sets-checkmodel-ignore")) {
-    Debug("sets-checkmodel-ignore") << "[sets-checkmodel-ignore] checkPassed value was " << checkPassed << std::endl;
+  if(Trace.isOn("sets-checkmodel-ignore")) {
+    Trace("sets-checkmodel-ignore") << "[sets-checkmodel-ignore] checkPassed value was " << checkPassed << std::endl;
   } else {
     Assert( checkPassed,
             "THEORY_SETS check-model failed. Run with -d sets-model for details." );
@@ -937,7 +939,7 @@ bool TheorySetsPrivate::present(TNode atom) {
 
 
 bool TheorySetsPrivate::holds(TNode atom, bool polarity) {
-  Node polarity_atom = NodeManager::currentNM()->mkConst<bool>(polarity);
+  TNode polarity_atom = polarity ? d_trueNode : d_falseNode;
 
   Node atomModEq = NodeManager::currentNM()->mkNode
     (atom.getKind(), d_equalityEngine.getRepresentative(atom[0]),
@@ -993,21 +995,44 @@ void TheorySetsPrivate::finishPropagation()
 
 void TheorySetsPrivate::addToPending(Node n) {
   Debug("sets-pending") << "[sets-pending] addToPending " << n << std::endl;
-  if(d_pendingEverInserted.find(n) == d_pendingEverInserted.end()) {
-    if(n.getKind() == kind::MEMBER) {
-      Debug("sets-pending") << "[sets-pending] \u2514 added to member queue"
-                            << std::endl;
-      ++d_statistics.d_memberLemmas;
-      d_pending.push(n);
-    } else {
-      Debug("sets-pending") << "[sets-pending] \u2514 added to equality queue"
-                            << std::endl;
-      Assert(n.getKind() == kind::EQUAL);
-      ++d_statistics.d_disequalityLemmas;
-      d_pendingDisequal.push(n);
+
+  if(d_pendingEverInserted.find(n) != d_pendingEverInserted.end()) {
+    Debug("sets-pending") << "[sets-pending] \u2514 skipping " << n
+                         << " as lemma already generated." << std::endl;
+    return;
+  }
+
+  if(n.getKind() == kind::MEMBER) {
+
+    Node nRewritten = theory::Rewriter::rewrite(n);
+
+    if(nRewritten.isConst()) {
+      Debug("sets-pending") << "[sets-pending] \u2514 skipping " << n
+                           << " as we can learn one of the sides." << std::endl;
+      Assert(nRewritten == d_trueNode || nRewritten == d_falseNode);
+
+      bool polarity = (nRewritten == d_trueNode);
+      learnLiteral(n, polarity, d_trueNode);
+      return;
     }
-    d_external.d_out->lemma(getLemma());
+
+    Debug("sets-pending") << "[sets-pending] \u2514 added to member queue"
+                         << std::endl;
+    ++d_statistics.d_memberLemmas;
+    d_pending.push(n);
+    d_external.d_out->splitLemma(getLemma());
     Assert(isComplete());
+
+  } else {
+
+    Debug("sets-pending") << "[sets-pending] \u2514 added to equality queue"
+                         << std::endl;
+    Assert(n.getKind() == kind::EQUAL);
+    ++d_statistics.d_disequalityLemmas;
+    d_pendingDisequal.push(n);
+    d_external.d_out->splitLemma(getLemma());
+    Assert(isComplete());
+
   }
 }
 
@@ -1042,13 +1067,15 @@ Node TheorySetsPrivate::getLemma() {
     d_pendingEverInserted.insert(n);
 
     Assert(n.getKind() == kind::EQUAL && n[0].getType().isSet());
-    Node x = NodeManager::currentNM()->mkSkolem("sde_", n[0].getType().getSetElementType() );
+    TypeNode elementType = n[0].getType().getSetElementType();
+    Node x = NodeManager::currentNM()->mkSkolem("sde_",  elementType);
     Node l1 = MEMBER(x, n[0]), l2 = MEMBER(x, n[1]);
 
     lemma = OR(n, AND(l1, NOT(l2)), AND(NOT(l1), l2));
   }
 
-  Debug("sets-lemma") << "[sets-lemma] Generating for " << n << ", lemma: " << lemma << std::endl;
+  Debug("sets-lemma") << "[sets-lemma] Generating for " << n
+                      << ", lemma: " << lemma << std::endl;
 
   return  lemma;
 }
@@ -1060,6 +1087,8 @@ TheorySetsPrivate::TheorySetsPrivate(TheorySets& external,
   d_external(external),
   d_notify(*this),
   d_equalityEngine(d_notify, c, "theory::sets::TheorySetsPrivate"),
+  d_trueNode(NodeManager::currentNM()->mkConst<bool>(true)),
+  d_falseNode(NodeManager::currentNM()->mkConst<bool>(false)),
   d_conflict(c),
   d_termInfoManager(NULL),
   d_propagationQueue(c),
@@ -1214,12 +1243,10 @@ void TheorySetsPrivate::preRegisterTerm(TNode node)
   default:
     d_termInfoManager->addTerm(node);
     d_equalityEngine.addTriggerTerm(node, THEORY_SETS);
-    // d_equalityEngine.addTerm(node);
   }
+
   if(node.getKind() == kind::SINGLETON) {
-    Node true_node = NodeManager::currentNM()->mkConst<bool>(true);
-    learnLiteral(MEMBER(node[0], node), true, true_node);
-    //intentional fallthrough
+    learnLiteral(MEMBER(node[0], node), true, d_trueNode);
   }
 }
 
@@ -1356,25 +1383,40 @@ const CDTNodeList* TheorySetsPrivate::TermInfoManager::getNonMembers(TNode S) {
 }
 
 void TheorySetsPrivate::TermInfoManager::addTerm(TNode n) {
-  unsigned numChild = n.getNumChildren();
+  if(d_terms.contains(n)) {
+    return;
+  }
+  d_terms.insert(n);
 
-  if(!d_terms.contains(n)) {
-    d_terms.insert(n);
-    d_info[n] = new TheorySetsTermInfo(d_context);
+  if(d_info.find(n) == d_info.end()) {
+    d_info.insert(make_pair(n, new TheorySetsTermInfo(d_context)));
   }
 
   if(n.getKind() == kind::UNION ||
      n.getKind() == kind::INTERSECTION ||
      n.getKind() == kind::SETMINUS) {
 
+    unsigned numChild = n.getNumChildren();
+
     for(unsigned i = 0; i < numChild; ++i) {
+      Assert(d_terms.contains(n[i]));
       if(d_terms.contains(n[i])) {
         Debug("sets-parent") << "Adding " << n << " to parent list of "
                              << n[i] << std::endl;
         d_info[n[i]]->parents->push_back(n);
+
+        typeof(d_info.begin()) ita = d_info.find(d_eqEngine->getRepresentative(n[i]));
+        Assert(ita != d_info.end());
+        CDTNodeList* l = (*ita).second->elementsNotInThisSet;
+        for(typeof(l->begin()) it = l->begin(); it != l->end(); ++it) {
+          d_theory.d_settermPropagationQueue.push_back( std::make_pair( (*it), n ) );
+        }
+        l = (*ita).second->elementsInThisSet;
+        for(typeof(l->begin()) it = l->begin(); it != l->end(); ++it) {
+          d_theory.d_settermPropagationQueue.push_back( std::make_pair( (*it), n ) );
+        }
       }
     }
-
   }
 }
 
index 643f2ab7f1ebf051f0133ae6cde495cb2f4819ae..ad273c546b5ca898dc1a6f3aa06a75f8d059f6e8 100644 (file)
@@ -100,6 +100,10 @@ private:
   /** Equality engine */
   eq::EqualityEngine d_equalityEngine;
 
+  /** True and false constant nodes */
+  Node d_trueNode;
+  Node d_falseNode;
+
   context::CDO<bool> d_conflict;
   Node d_conflictNode;
 
index 226eca62bfdd4c971b5b1884264bfae2cade95ea..635f9856a748f67cea5509d18d1c6aecb991a2da 100644 (file)
@@ -26,9 +26,6 @@ typedef std::hash_map<TNode, Elements, TNodeHashFunction> SettermElementsMap;
 
 bool checkConstantMembership(TNode elementTerm, TNode setTerm)
 {
-  // Assume from pre-rewrite constant sets look like the following:
-  // (union (setenum bla) (union (setenum bla) ... (union (setenum bla) (setenum bla) ) ... ))
-
   if(setTerm.getKind() == kind::EMPTYSET) {
     return false;
   }
@@ -40,25 +37,9 @@ bool checkConstantMembership(TNode elementTerm, TNode setTerm)
   Assert(setTerm.getKind() == kind::UNION && setTerm[1].getKind() == kind::SINGLETON,
          "kind was %d, term: %s", setTerm.getKind(), setTerm.toString().c_str());
 
-  return elementTerm == setTerm[1][0] || checkConstantMembership(elementTerm, setTerm[0]);
-
-  // switch(setTerm.getKind()) {
-  // case kind::EMPTYSET:
-  //   return false;
-  // case kind::SINGLETON:
-  //   return elementTerm == setTerm[0];
-  // case kind::UNION:
-  //   return checkConstantMembership(elementTerm, setTerm[0]) ||
-  //     checkConstantMembership(elementTerm, setTerm[1]);
-  // case kind::INTERSECTION:
-  //   return checkConstantMembership(elementTerm, setTerm[0]) &&
-  //     checkConstantMembership(elementTerm, setTerm[1]);
-  // case kind::SETMINUS:
-  //   return checkConstantMembership(elementTerm, setTerm[0]) &&
-  //     !checkConstantMembership(elementTerm, setTerm[1]);
-  // default:
-  //   Unhandled();
-  // }
+  return
+    elementTerm == setTerm[1][0] ||
+    checkConstantMembership(elementTerm, setTerm[0]);
 }
 
 // static
@@ -66,6 +47,12 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
   NodeManager* nm = NodeManager::currentNM();
   Kind kind = node.getKind();
 
+
+  if(node.isConst()) {
+    // Dare you touch the const and mangle it to something else.
+    return RewriteResponse(REWRITE_DONE, node);
+  }
+
   switch(kind) {
 
   case kind::MEMBER: {
@@ -79,6 +66,10 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
   }//kind::MEMBER
 
   case kind::SUBSET: {
+    Assert(false, "TheorySets::postRrewrite(): Subset is handled in preRewrite.");
+
+    // but in off-chance we do end up here, let us do our best
+
     // rewrite (A subset-or-equal B) as (A union B = B)
     TNode A = node[0];
     TNode B = node[1];
@@ -118,6 +109,16 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
               node[1].getKind() == kind::EMPTYSET) {
       Trace("sets-postrewrite") << "Sets::postRewrite returning " << node[0] << std::endl;
       return RewriteResponse(REWRITE_DONE, node[0]);
+    } else if(node[0].isConst() && node[1].isConst()) {
+      std::set<Node> left = NormalForm::getElementsFromNormalConstant(node[0]);
+      std::set<Node> right = NormalForm::getElementsFromNormalConstant(node[1]);
+      std::set<Node> newSet;
+      std::set_difference(left.begin(), left.end(), right.begin(), right.end(),
+                         std::inserter(newSet, newSet.begin()));
+      Node newNode = NormalForm::elementsToSet(newSet, node.getType());
+      Assert(newNode.isConst());
+      Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
+      return RewriteResponse(REWRITE_DONE, newNode);
     }
     break;
   }//kind::INTERSECION
@@ -130,6 +131,16 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
       return RewriteResponse(REWRITE_DONE, node[0]);
     } else if(node[1].getKind() == kind::EMPTYSET) {
       return RewriteResponse(REWRITE_DONE, node[1]);
+    } else if(node[0].isConst() && node[1].isConst()) {
+      std::set<Node> left = NormalForm::getElementsFromNormalConstant(node[0]);
+      std::set<Node> right = NormalForm::getElementsFromNormalConstant(node[1]);
+      std::set<Node> newSet;
+      std::set_intersection(left.begin(), left.end(), right.begin(), right.end(),
+                         std::inserter(newSet, newSet.begin()));
+      Node newNode = NormalForm::elementsToSet(newSet, node.getType());
+      Assert(newNode.isConst());
+      Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
+      return RewriteResponse(REWRITE_DONE, newNode);
     } else if (node[0] > node[1]) {
       Node newNode = nm->mkNode(node.getKind(), node[1], node[0]);
       Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
@@ -139,6 +150,7 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
   }//kind::INTERSECION
 
   case kind::UNION: {
+    // NOTE: case where it is CONST is taken care of at the top
     if(node[0] == node[1]) {
       Trace("sets-postrewrite") << "Sets::postRewrite returning " << node[0] << std::endl;
       return RewriteResponse(REWRITE_DONE, node[0]);
@@ -146,6 +158,16 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
       return RewriteResponse(REWRITE_DONE, node[1]);
     } else if(node[1].getKind() == kind::EMPTYSET) {
       return RewriteResponse(REWRITE_DONE, node[0]);
+    } else if(node[0].isConst() && node[1].isConst()) {
+      std::set<Node> left = NormalForm::getElementsFromNormalConstant(node[0]);
+      std::set<Node> right = NormalForm::getElementsFromNormalConstant(node[1]);
+      std::set<Node> newSet;
+      std::set_union(left.begin(), left.end(), right.begin(), right.end(),
+                         std::inserter(newSet, newSet.begin()));
+      Node newNode = NormalForm::elementsToSet(newSet, node.getType());
+      Assert(newNode.isConst());
+      Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
+      return RewriteResponse(REWRITE_DONE, newNode);
     } else if (node[0] > node[1]) {
       Node newNode = nm->mkNode(node.getKind(), node[1], node[0]);
       Trace("sets-postrewrite") << "Sets::postRewrite returning " << newNode << std::endl;
@@ -162,83 +184,42 @@ RewriteResponse TheorySetsRewriter::postRewrite(TNode node) {
   return RewriteResponse(REWRITE_DONE, node);
 }
 
-const Elements& collectConstantElements(TNode setterm, SettermElementsMap& settermElementsMap) {
-  SettermElementsMap::const_iterator it = settermElementsMap.find(setterm);
-  if(it == settermElementsMap.end() ) {
-
-    Kind k = setterm.getKind();
-    unsigned numChildren = setterm.getNumChildren();
-    Elements cur;
-    if(numChildren == 2) {
-      const Elements& left = collectConstantElements(setterm[0], settermElementsMap);
-      const Elements& right = collectConstantElements(setterm[1], settermElementsMap);
-      switch(k) {
-      case kind::UNION:
-        if(left.size() >= right.size()) {
-          cur = left; cur.insert(right.begin(), right.end());
-        } else {
-          cur = right; cur.insert(left.begin(), left.end());
-        }
-        break;
-      case kind::INTERSECTION:
-        std::set_intersection(left.begin(), left.end(), right.begin(), right.end(),
-                              std::inserter(cur, cur.begin()) );
-        break;
-      case kind::SETMINUS:
-        std::set_difference(left.begin(), left.end(), right.begin(), right.end(),
-                            std::inserter(cur, cur.begin()) );
-        break;
-      default:
-        Unhandled();
-      }
-    } else {
-      switch(k) {
-      case kind::EMPTYSET:
-        /* assign emptyset, which is default */
-        break;
-      case kind::SINGLETON:
-        Assert(setterm[0].isConst());
-        cur.insert(TheorySetsRewriter::preRewrite(setterm[0]).node);
-        break;
-      default:
-        Unhandled();
-      }
-    }
-    Debug("sets-rewrite-constant") << "[sets-rewrite-constant] "<< setterm << " " << setterm.getId() << std::endl;
-
-    it = settermElementsMap.insert(SettermElementsMap::value_type(setterm, cur)).first;
-  }
-  return it->second;
-}
-
 
 // static
 RewriteResponse TheorySetsRewriter::preRewrite(TNode node) {
   NodeManager* nm = NodeManager::currentNM();
 
-  // do nothing
-  if(node.getKind() == kind::EQUAL && node[0] == node[1])
-    return RewriteResponse(REWRITE_DONE, nm->mkConst(true));
-  // Further optimization, if constants but differing ones
+  if(node.getKind() == kind::EQUAL) {
+
+    if(node[0] == node[1]) {
+      return RewriteResponse(REWRITE_DONE, nm->mkConst(true));
+    }
+
+  }//kind::EQUAL
+  else if(node.getKind() == kind::INSERT) {
 
-  if(node.getKind() == kind::INSERT) {
     Node insertedElements = nm->mkNode(kind::SINGLETON, node[0]);
     size_t setNodeIndex =  node.getNumChildren()-1;
     for(size_t i = 1; i < setNodeIndex; ++i) {
-      insertedElements = nm->mkNode(kind::UNION, insertedElements, nm->mkNode(kind::SINGLETON, node[i]));
+      insertedElements = nm->mkNode(kind::UNION, 
+                                   insertedElements,
+                                   nm->mkNode(kind::SINGLETON, node[i]));
     }
-    return RewriteResponse(REWRITE_AGAIN, nm->mkNode(kind::UNION, insertedElements, node[setNodeIndex]));
+    return RewriteResponse(REWRITE_AGAIN, 
+                          nm->mkNode(kind::UNION,
+                                     insertedElements, 
+                                     node[setNodeIndex]));
+
   }//kind::INSERT
+  else if(node.getKind() == kind::SUBSET) {
 
-  if(node.getType().isSet() && node.isConst()) {
-    //rewrite set to normal form
-    SettermElementsMap setTermElementsMap;   // cache
-    const Elements& elements = collectConstantElements(node, setTermElementsMap);
-    RewriteResponse response(REWRITE_DONE, NormalForm::elementsToSet(elements, node.getType()));
-    Debug("sets-rewrite-constant") << "[sets-rewrite-constant] Rewriting " << node << std::endl
-                                   << "[sets-rewrite-constant]        to " << response.node << std::endl;
-    return response;
-  }
+    // rewrite (A subset-or-equal B) as (A union B = B)
+    return RewriteResponse(REWRITE_AGAIN,
+                           nm->mkNode(kind::EQUAL,
+                                      nm->mkNode(kind::UNION, node[0], node[1]),
+                                      node[1]) );
+
+  }//kind::SUBSET
 
   return RewriteResponse(REWRITE_DONE, node);
 }
index 718c329fd90b25ef0900db1d85154abcb6ca4f9a..551c0b0ee260fbb3fa597d910fe3cc2e5fdc7f7a 100644 (file)
@@ -97,6 +97,7 @@ public:
     Node n = NormalForm::elementsToSet(std::set<TNode>(elements.begin(), elements.end()),
                                        getType());
 
+    Assert(n.isConst());
     Assert(n == Rewriter::rewrite(n));
 
     return n;
index 6754bbb9ee2bc9bf35eb43a28e0afcfebb068ff2..d0e1f18f11bb991098feb039fc8661197b9a9884 100644 (file)
@@ -19,6 +19,8 @@
 #ifndef __CVC4__THEORY__SETS__THEORY_SETS_TYPE_RULES_H
 #define __CVC4__THEORY__SETS__THEORY_SETS_TYPE_RULES_H
 
+#include "theory/sets/normal_form.h"
+
 namespace CVC4 {
 namespace theory {
 namespace sets {
@@ -67,7 +69,11 @@ struct SetsBinaryOperatorTypeRule {
     Assert(n.getKind() == kind::UNION ||
            n.getKind() == kind::INTERSECTION ||
            n.getKind() == kind::SETMINUS);
-    return n[0].isConst() && n[1].isConst();
+    if(n.getKind() == kind::UNION) {
+      return NormalForm::checkNormalConstant(n);
+    } else {
+      return false;
+    }
   }
 };/* struct SetUnionTypeRule */
 
@@ -154,7 +160,7 @@ struct InsertTypeRule {
 
   inline static bool computeIsConst(NodeManager* nodeManager, TNode n) {
     Assert(n.getKind() == kind::INSERT);
-    return n[0].isConst() && n[1].isConst();
+    return false;
   }
 };/* struct InsertTypeRule */
 
@@ -162,7 +168,8 @@ struct InsertTypeRule {
 struct SetsProperties {
   inline static Cardinality computeCardinality(TypeNode type) {
     Assert(type.getKind() == kind::SET_TYPE);
-    Cardinality elementCard = type[0].getCardinality();
+    Cardinality elementCard = 2;
+    elementCard ^= type[0].getCardinality();
     return elementCard;
   }
 
index d83626a6b50b4b4698272371e9180bbadd6a14dd..9d91c096a6c19b48f3cf097882bda02225fe7cc2 100644 (file)
@@ -379,6 +379,13 @@ void TheoryEngine::check(Theory::Effort effort) {
         printAssertions("theory::assertions");
       }
 
+      if(Theory::fullEffort(effort)) {
+        Trace("theory::assertions::fulleffort") << endl;
+        if (Trace.isOn("theory::assertions::fulleffort")) {
+          printAssertions("theory::assertions::fulleffort");
+        }
+      }
+        
       // Note that we've discharged all the facts
       d_factsAsserted = false;
 
@@ -1194,6 +1201,7 @@ theory::EqualityStatus TheoryEngine::getEqualityStatus(TNode a, TNode b) {
 }
 
 Node TheoryEngine::getModelValue(TNode var) {
+  if(var.isConst()) return var;  // FIXME: HACK!!!
   Assert(d_sharedTerms.isShared(var));
   return theoryOf(Theory::theoryOf(var.getType()))->getModelValue(var);
 }