summaryrefslogtreecommitdiff
path: root/src/theory/uf/ecdata.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/theory/uf/ecdata.h')
-rw-r--r--src/theory/uf/ecdata.h145
1 files changed, 110 insertions, 35 deletions
diff --git a/src/theory/uf/ecdata.h b/src/theory/uf/ecdata.h
index 221512669..9b87aa6cb 100644
--- a/src/theory/uf/ecdata.h
+++ b/src/theory/uf/ecdata.h
@@ -23,20 +23,43 @@
namespace CVC4 {
namespace theory {
-
+namespace uf {
+
+/**
+ * Link is a context dependent linked list of nodes.
+ * Link is intended to be allocated in a Context's memory manager.
+ * The next pointer of the list is context dependent, but the node being
+ * pointed to is fixed for the life of the Link.
+ *
+ * Clients of Link are intended not to modify the node that is being pointed
+ * to in good faith. This may change in the future.
+ */
struct Link {
+ /**
+ * Pointer to the next element in linked list.
+ * This is context dependent.
+ */
context::CDO< Link* > next;
- /**
- * As I have not yet succeeded in justifying to myself that soft references are safe
- * I am leaving this a hard refernce for now.
+ /* 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.
*/
- Node data;
+ TNode data;
- Link(context::Context* context, Node n, Link * l = NULL):
+ /**
+ * 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)
{}
+ /**
+ * Allocates a new Link in the region for the provided ContextMemoryManager.
+ * This allows for cheap cleanup on pop.
+ */
static void* operator new(size_t size, context::ContextMemoryManager* pCMM) {
return pCMM->newData(size);
}
@@ -44,21 +67,82 @@ struct Link {
};
-
+/**
+ * ECData is a equivalence class object that is context dependent.
+ * It is developed in order to support the congruence closure algorithm
+ * in TheoryUF, and is not intended to be used outside of that package.
+ *
+ * ECData maintains:
+ * - find pointer for the equivalence class (disjoint set forest)
+ * - the node that represents the equivalence class.
+ * - maintains a predecessorlist/watchlist
+ *
+ * ECData does not have support for the canonical find and union operators
+ * for disjoint set forests. Instead it only provides access to the find
+ * pointer. The implementation of find is ccFind in TheoryUF.
+ * union is broken into 2 phases:
+ * 1) setting the find point with setFind
+ * 2) taking over the watch list of the other node.
+ * This is a technical requirement for the implementation of TheoryUF.
+ * (See ccUnion in TheoryUF for more information.)
+ *
+ * The intended paradigm for iterating over the watch list of ec is:
+ * for(Link* i = ec->getFirst(); i != NULL; i = i->next );
+ *
+ * See also ECAttr() in theory_uf.h, and theory_uf.cpp where the codde that uses
+ * ECData lives.
+ */
class ECData : public context::ContextObj {
private:
+ /**
+ * This is the standard disjoint set forest find pointer.
+ *
+ * Why an ECData pointer instead of a node?
+ * 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;
+
/**
- * Is it safe to make this a soft link? Why or why not?
+ * This is pointer back to the node that represents this equivalence class.
+ *
+ * The following invariant should be maintained:
+ * (n.getAttribute(ECAttr()))->rep == n
+ * i.e. rep is equal to the node that maps to the ECData using ECAttr.
+ *
+ * Tricky part: This needs to be a TNode, not a Node.
+ * Suppose that rep were a hard link.
+ * When a node n maps to an ECData via the ECAttr() there will be a hard
+ * link back to n in the ECData. The attribute does not do garbage collection
+ * until the node gets garbage collected, which does not happen until its
+ * ref count drops to 0. So because of this cycle neither the node and
+ * the ECData will never get garbage collected.
+ * So this needs to be a soft link.
*/
- Node rep;
+ TNode rep;
+ /* Watch list datastructures. */
+ /** Maintains watch list size for more efficient merging */
unsigned watchListSize;
+
+ /**
+ *Pointer to the beginning of the watchlist.
+ *This value is NULL iff the watch list is empty.
+ */
Link* first;
+
+ /**
+ * Pointer to the end of the watch-list.
+ * This is maintained in order to constant time list merging.
+ * (This does not give any asymptotic improve as this is currently always
+ * preceeded by an O(|watchlist|) operation.)
+ * This value is NULL iff the watch list is empty.
+ */
Link* last;
+ /** Context dependent operations */
context::ContextObj* save(context::ContextMemoryManager* pCMM);
void restore(context::ContextObj* pContextObj);
@@ -72,12 +156,13 @@ public:
/**
* Adds a node to the watch list of the equivalence class.
- * Requires a context to do memory management.
+ * Requires a Context in-order to do context dependent memory allocation.
+ *
* @param n the node to be added.
* @pre isClassRep() == true
*/
- void addPredecessor(Node n, context::Context* context);
-
+ void addPredecessor(TNode n, context::Context* context);
+
/**
@@ -86,11 +171,16 @@ public:
* This is required as ECData is context dependent
* @param n the node that corresponds to this ECData
*/
- ECData(context::Context* context, const Node & n);
-
- static void takeOverDescendantWatchList(ECData * nslave, ECData * nmaster);
+ ECData(context::Context* context, TNode n);
- static ECData * ccFind(ECData * fp);
+ /**
+ * An ECData takes over the watch list of another ECData.
+ * This is the second step in the union operator for ECData.
+ * This should be called after nslave->setFind(nmaster);
+ * After this is done nslave's watch list should never be accessed by
+ * getLast() or getFirst()
+ */
+ static void takeOverDescendantWatchList(ECData * nslave, ECData * nmaster);
/**
@@ -117,35 +207,20 @@ public:
/**
+ * Sets the find pointer of the equivalence class to be another ECData object.
+ *
* @pre isClassRep() == true
* @pre ec->isClassRep() == true
* @post isClassRep() == false
* @post ec->isClassRep() == true
*/
void setFind(ECData * ec);
-
-private:
-
-
- /**
- * @pre isClassRep() == true
- */
- void setWatchListSize(unsigned newSize);
-
- /**
- * @pre isClassRep() == true
- */
- void setFirst(Link * nfirst);
- Link* getLast();
- /**
- * @pre isClassRep() == true
- */
- void setLast(Link * nlast);
-
}; /* class ECData */
+
+}/* CVC4::theory::uf namespace */
}/* CVC4::theory namespace */
}/* CVC4 namespace */
generated by cgit on debian on lair
contact matthew@masot.net with questions or feedback