Committing a bug fix from Dejan. This resolves an issue with restoring ECData.
authorTim King <taking@cs.nyu.edu>
Thu, 4 Mar 2010 20:10:46 +0000 (20:10 +0000)
committerTim King <taking@cs.nyu.edu>
Thu, 4 Mar 2010 20:10:46 +0000 (20:10 +0000)
src/expr/expr_manager.h
src/theory/uf/ecdata.cpp
src/theory/uf/ecdata.h
src/theory/uf/theory_uf.cpp
src/theory/uf/theory_uf.h
test/unit/theory/theory_uf_white.h

index 67fa0664aab2029a4a2d16b23a5d5f6bd99fc6a8..f5edc54642b8110796ff3601f5c1ecf2b848a92d 100644 (file)
@@ -24,8 +24,8 @@ namespace CVC4 {
 
 class Expr;
 class Type;
-class BooleanType; 
-class FunctionType; 
+class BooleanType;
+class FunctionType;
 class KindType;
 class SmtEngine;
 class NodeManager;
@@ -91,12 +91,12 @@ public:
   Expr mkExpr(Kind kind, const std::vector<Expr>& children);
 
   /** Make a function type from domain to range. */
-  const FunctionType* 
-    mkFunctionType(const Type* domain, 
+  const FunctionType*
+    mkFunctionType(const Type* domain,
                    const Type* range);
 
   /** Make a function type with input types from argTypes. */
-  const FunctionType* 
+  const FunctionType*
     mkFunctionType(const std::vector<const Type*>& argTypes, 
                    const Type* range);
 
index 5a89a493906be2cfc941d6c8df11a3c26d902d9f..22db1e6d05d0c04b1fbf4b1611893b6d985a0c3f 100644 (file)
@@ -23,16 +23,16 @@ using namespace uf;
 
 ECData::ECData(Context * context, TNode n) :
   ContextObj(context),
-  find(this),
-  rep(n),
-  watchListSize(0),
-  first(NULL),
-  last(NULL)
+  d_find(this),
+  d_rep(n),
+  d_watchListSize(0),
+  d_first(NULL),
+  d_last(NULL)
 {}
 
 
 bool ECData::isClassRep(){
-  return this == this->find;
+  return this == this->d_find;
 }
 
 void ECData::addPredecessor(TNode n, Context* context){
@@ -40,13 +40,13 @@ void ECData::addPredecessor(TNode n, Context* context){
 
   makeCurrent();
 
-  Link * newPred = new (context->getCMM())  Link(context, n, first);
-  first = newPred;
-  if(last == NULL){
-    last = newPred;
+  Link * newPred = new (context->getCMM())  Link(context, n, d_first);
+  d_first = newPred;
+  if(d_last == NULL){
+    d_last = newPred;
   }
 
-  ++watchListSize;
+  ++d_watchListSize;
 }
 
 ContextObj* ECData::save(ContextMemoryManager* pCMM) {
@@ -54,30 +54,35 @@ ContextObj* ECData::save(ContextMemoryManager* pCMM) {
 }
 
 void ECData::restore(ContextObj* pContextObj) {
-  *this = *((ECData*)pContextObj);
+  ECData* data = (ECData*)pContextObj;
+  d_find = data->d_find;
+  d_first = data->d_first;
+  d_last = data->d_last;
+  d_rep = data->d_rep;
+  d_watchListSize = data->d_watchListSize;
 }
 
 Node ECData::getRep(){
-  return rep;
+  return d_rep;
 }
 
 unsigned ECData::getWatchListSize(){
-  return watchListSize;
+  return d_watchListSize;
 }
 
 
 void ECData::setFind(ECData * ec){
   makeCurrent();
-  find = ec;
+  d_find = ec;
 }
 
 ECData * ECData::getFind(){
-  return find;
+  return d_find;
 }
 
 
 Link* ECData::getFirst(){
-  return first;
+  return d_first;
 }
 
 
@@ -87,14 +92,14 @@ void ECData::takeOverDescendantWatchList(ECData * nslave, ECData * nmaster){
 
   nmaster->makeCurrent();
 
-  nmaster->watchListSize +=  nslave->watchListSize;
+  nmaster->d_watchListSize +=  nslave->d_watchListSize;
 
-  if(nmaster->first == NULL){
-    nmaster->first = nslave->first;
-    nmaster->last = nslave->last;
-  }else if(nslave->first != NULL){
-    Link * currLast = nmaster->last;
-    currLast->next = nslave->first;
-    nmaster->last = nslave->last;
+  if(nmaster->d_first == NULL){
+    nmaster->d_first = nslave->d_first;
+    nmaster->d_last = nslave->d_last;
+  }else if(nslave->d_first != NULL){
+    Link * currLast = nmaster->d_last;
+    currLast->d_next = nslave->d_first;
+    nmaster->d_last = nslave->d_last;
   }
 }
index 5bb3a57bd065b063cc2371a473d3e08f3919e9eb..735712cdcf826fee83ceda19f706766cb9ac8496 100644 (file)
@@ -41,21 +41,21 @@ struct Link {
    * Pointer to the next element in linked list.
    * This is context dependent. 
    */
-  context::CDO< Link* > next;
+  context::CDO< Link* > d_next;
 
   /* Link is supposed to be allocated in a region of a ContextMemoryManager.
    * In order to avoid having to decrement the ref count at deletion time,
    * it is preferrable for the user of Link to maintain the invariant that
    * data will survival for the entire scope of the TNode.
    */
-  TNode data;
+  TNode d_data;
 
   /**
    * Creates a new Link w.r.t. a context for the node n.
    * An optional parameter is to specify the next element in the link.
    */
   Link(context::Context* context, TNode n, Link * l = NULL):
-    next(context, l), data(n)
+    d_next(context, l), d_data(n)
   {}
 
   /**
@@ -103,7 +103,7 @@ private:
    * This was chosen to be a ECData pointer in order to shortcut at least one
    * table every time the find pointer is examined.
    */
-  ECData* find;
+  ECData* d_find;
 
 
   /**
@@ -122,17 +122,17 @@ private:
    * the ECData will never get garbage collected.
    * So this needs to be a soft link.
    */
-  TNode rep;
+  TNode d_rep;
 
   /* Watch list datastructures. */
   /** Maintains watch list size for more efficient merging */
-  unsigned watchListSize;
+  unsigned d_watchListSize;
 
   /**
    *Pointer to the beginning of the watchlist.
    *This value is NULL iff the watch list is empty.
    */
-  Link* first;
+  Link* d_first;
 
   /**
    * Pointer to the end of the watch-list.
@@ -141,7 +141,7 @@ private:
    * preceeded by an O(|watchlist|) operation.)
    * This value is NULL iff the watch list is empty.
    */
-  Link* last;
+  Link* d_last;
 
 
   /** Context dependent operations */
index 485f5f6d3c59eb8a2a015aa9607157a0f04d7bb6..b4597c7c7aaf9fc722743a14613c001c4537f20e 100644 (file)
@@ -122,9 +122,9 @@ void TheoryUF::registerTerm(TNode n){
       /* Because this can be called after nodes have been merged we may need
        * to be merged with other predecessors of the equivalence class.
        */
-      for(Link* Px = ecChild->getFirst(); Px != NULL; Px = Px->next ){
-        if(equiv(n, Px->data)){
-          Node pend = n.eqNode(Px->data);
+      for(Link* Px = ecChild->getFirst(); Px != NULL; Px = Px->d_next ){
+        if(equiv(n, Px->d_data)){
+          Node pend = n.eqNode(Px->d_data);
           d_pending.push_back(pend);
         }
       }
@@ -210,10 +210,10 @@ void TheoryUF::ccUnion(ECData* ecX, ECData* ecY){
 
   nslave->setFind(nmaster);
 
-  for(Link* Px = nmaster->getFirst(); Px != NULL; Px = Px->next ){
-    for(Link* Py = nslave->getFirst(); Py != NULL; Py = Py->next ){
-      if(equiv(Px->data,Py->data)){
-        Node pendingEq = (Px->data).eqNode(Py->data);
+  for(Link* Px = nmaster->getFirst(); Px != NULL; Px = Px->d_next ){
+    for(Link* Py = nslave->getFirst(); Py != NULL; Py = Py->d_next ){
+      if(equiv(Px->d_data,Py->d_data)){
+        Node pendingEq = (Px->d_data).eqNode(Py->d_data);
         d_pending.push_back(pendingEq);
       }
     }
index 5ac5e3001466f457268df18adc05409327b1f836..d432d733f6c3f1f1454dd784b6bdbbce570ce235 100644 (file)
@@ -84,8 +84,6 @@ public:
   ~TheoryUF();
 
 
-  //TODO Tim: I am going to delay documenting these functions while Morgan
-  //has pending changes to the contracts
 
   /**
    * Registers a previously unseen [in this context] node n.
index 5aeb5f8a5309d37feec531a42f79f6ed05a1a51f..fe2c8d8215c43fd44bdafdb76d3a9e31ca941212 100644 (file)
@@ -115,6 +115,64 @@ public:
     delete d_nm;
   }
 
+  void testPushPopChain(){
+    Node x = d_nm->mkVar();
+    Node f = d_nm->mkVar();
+    Node f_x = d_nm->mkNode(kind::APPLY, f, x);
+    Node f_f_x = d_nm->mkNode(kind::APPLY, f, f_x);
+    Node f_f_f_x = d_nm->mkNode(kind::APPLY, f, f_f_x);
+    Node f_f_f_f_x = d_nm->mkNode(kind::APPLY, f, f_f_f_x);
+    Node f_f_f_f_f_x = d_nm->mkNode(kind::APPLY, f, f_f_f_f_x);
+
+    Node f3_x_eq_x = f_f_f_x.eqNode(x);
+    Node f5_x_eq_x = f_f_f_f_f_x.eqNode(x);
+    Node f5_x_eq_f5_x = f_f_f_f_f_x.eqNode(f_f_f_f_f_x);
+    Node f1_x_neq_x = f_x.eqNode(x).notNode();
+
+    Node expectedConflict = d_nm->mkNode(kind::AND,
+                                         f1_x_neq_x,
+                                         f5_x_eq_f5_x,
+                                         f3_x_eq_x,
+                                         f5_x_eq_x
+                                         );
+
+    d_euf->assertFact( f5_x_eq_f5_x );
+
+    d_euf->assertFact( f3_x_eq_x );
+    d_euf->assertFact( f1_x_neq_x );
+    d_euf->check(level);
+    d_context->push();
+
+    d_euf->assertFact( f5_x_eq_x );
+    d_euf->check(level);
+
+    TS_ASSERT_EQUALS(1, d_outputChannel.getNumCalls());
+    TS_ASSERT_EQUALS(CONFLICT, d_outputChannel.getIthCallType(0));
+    Node realConflict = d_outputChannel.getIthNode(0);
+    TS_ASSERT_EQUALS(expectedConflict, realConflict);
+
+    d_context->pop();
+    d_euf->check(level);
+
+    //Test that no additional calls to the output channel occurred.
+    TS_ASSERT_EQUALS(1, d_outputChannel.getNumCalls());
+
+    d_euf->assertFact( f5_x_eq_x );
+
+    d_euf->check(level);
+
+    TS_ASSERT_EQUALS(2, d_outputChannel.getNumCalls());
+    TS_ASSERT_EQUALS(CONFLICT, d_outputChannel.getIthCallType(0));
+    TS_ASSERT_EQUALS(CONFLICT, d_outputChannel.getIthCallType(1));
+    Node  firstConflict = d_outputChannel.getIthNode(0);
+    Node secondConflict = d_outputChannel.getIthNode(1);
+    TS_ASSERT_EQUALS(expectedConflict,  firstConflict);
+    TS_ASSERT_EQUALS(expectedConflict, secondConflict);
+
+  }
+
+
+
   /* test that {f(f(x)) == x, f(f(f(x))) != f(x)} is inconsistent */
   void testSimpleChain(){
     Node x = d_nm->mkVar();
@@ -200,4 +258,33 @@ public:
     Node realConflict = d_outputChannel.getIthNode(0);
     TS_ASSERT_EQUALS(expectedConflict, realConflict);
   }
+
+
+  void testPushPopA(){
+    Node x = d_nm->mkVar();
+    Node x_eq_x = x.eqNode(x);
+
+    d_context->push();
+    d_euf->assertFact( x_eq_x );
+    d_euf->check(level);
+    d_context->pop();
+    d_euf->check(level);
+  }
+
+  void testPushPopB(){
+    Node x = d_nm->mkVar();
+    Node f = d_nm->mkVar();
+    Node f_x = d_nm->mkNode(kind::APPLY, f, x);
+    Node f_x_eq_x = f_x.eqNode(x);
+
+    d_euf->assertFact( f_x_eq_x );
+    d_context->push();
+    d_euf->check(level);
+    d_context->pop();
+    d_euf->check(level);
+  }
+
+
+
+
 };