#include "util/trans_closure.h"
+#include "util/Assert.h"
using namespace std;
TransitiveClosure::~TransitiveClosure() {
unsigned i;
for (i = 0; i < adjMatrix.size(); ++i) {
- adjMatrix[i]->deleteSelf();
+ if (adjMatrix[i]) {
+ adjMatrix[i]->deleteSelf();
+ }
}
}
bool TransitiveClosure::addEdge(unsigned i, unsigned j)
{
- if (adjMatrix.size() > j && adjMatrix[j]->read(i)) {
- return false;
+ // Check for loops
+ Assert(i != j, "Cannot add self-loop");
+ if (adjMatrix.size() > j && adjMatrix[j] != NULL && adjMatrix[j]->read(i)) {
+ return true;
+ }
+
+ // Grow matrix if necessary
+ unsigned maxSize = ((i > j) ? i : j) + 1;
+ while (maxSize > adjMatrix.size()) {
+ adjMatrix.push_back(NULL);
}
- while (i >= adjMatrix.size()) {
- adjMatrix.push_back(new (true) CDBV(d_context));
+
+ // Add edge from i to j and everything j can reach
+ if (adjMatrix[i] == NULL) {
+ adjMatrix[i] = new (true) CDBV(d_context);
}
adjMatrix[i]->write(j);
+ if (adjMatrix[j] != NULL) {
+ adjMatrix[i]->merge(adjMatrix[j]);
+ }
+
+ // Add edges from everything that can reach i to j and everything that j can reach
unsigned k;
for (k = 0; k < adjMatrix.size(); ++k) {
- if (adjMatrix[k]->read(i)) {
+ if (adjMatrix[k] != NULL && adjMatrix[k]->read(i)) {
adjMatrix[k]->write(j);
- adjMatrix[k]->merge(adjMatrix[j]);
+ if (adjMatrix[j] != NULL) {
+ adjMatrix[k]->merge(adjMatrix[j]);
+ }
}
}
- return true;
+
+ return false;
+}
+
+
+void TransitiveClosure::debugPrintMatrix()
+{
+ unsigned i,j;
+ for (i = 0; i < adjMatrix.size(); ++i) {
+ for (j = 0; j < adjMatrix.size(); ++j) {
+ if (adjMatrix[i] != NULL && adjMatrix[i]->read(j)) {
+ cout << "1 ";
+ }
+ else cout << "0 ";
+ }
+ cout << endl;
+ }
}
}
void testSimple() {
- //Debug.on("cc");
- // add terms, then add equalities
+ bool b;
+ b = d_tc->addEdge(1,2);
+ TS_ASSERT(!b);
+
+ b = d_tc->addEdge(2,3);
+ TS_ASSERT(!b);
+
+ b = d_tc->addEdge(3,1);
+ TS_ASSERT(b);
+
+ b = d_tc->addEdge(2,4);
+ TS_ASSERT(!b);
+
+ b = d_tc->addEdge(2,5);
+ TS_ASSERT(!b);
+
+ b = d_tc->addEdge(4,6);
+ TS_ASSERT(!b);
+ b = d_tc->addEdge(6,2);
+ TS_ASSERT(b);
+ }
+
+
+ void test1() {
bool b;
b = d_tc->addEdge(1,2);
TS_ASSERT(!b);
+ d_context->push();
+
b = d_tc->addEdge(2,3);
TS_ASSERT(!b);
b = d_tc->addEdge(3,1);
TS_ASSERT(b);
+
+ d_context->pop();
+
+ b = d_tc->addEdge(3,1);
+ TS_ASSERT(!b);
+
+ b = d_tc->addEdge(2,3);
+ TS_ASSERT(b);
+
+ d_context->push();
+
+ b = d_tc->addEdge(6,4);
+ TS_ASSERT(!b);
+
+ b = d_tc->addEdge(2,6);
+ TS_ASSERT(!b);
+
+ b = d_tc->addEdge(4,1);
+ TS_ASSERT(b);
+
+ d_context->pop();
+
+ b = d_tc->addEdge(4,1);
+
+ TS_ASSERT(!b);
}
+ void test2() {
+ bool b;
+ b = d_tc->addEdge(1,2);
+ TS_ASSERT(!b);
+ b = d_tc->addEdge(1,3);
+ TS_ASSERT(!b);
+ b = d_tc->addEdge(1,4);
+ TS_ASSERT(!b);
+ b = d_tc->addEdge(1,5);
+ TS_ASSERT(!b);
+ b = d_tc->addEdge(1,6);
+ TS_ASSERT(!b);
+ b = d_tc->addEdge(1,7);
+ TS_ASSERT(!b);
+ b = d_tc->addEdge(1,8);
+ TS_ASSERT(!b);
+ b = d_tc->addEdge(1,9);
+ TS_ASSERT(!b);
+
+ b = d_tc->addEdge(3,2);
+ TS_ASSERT(!b);
+ b = d_tc->addEdge(4,7);
+ TS_ASSERT(!b);
+
+ b = d_tc->addEdge(2,1);
+ TS_ASSERT(b);
+ b = d_tc->addEdge(3,1);
+ TS_ASSERT(b);
+ b = d_tc->addEdge(4,1);
+ TS_ASSERT(b);
+ b = d_tc->addEdge(5,1);
+ TS_ASSERT(b);
+ b = d_tc->addEdge(6,1);
+ TS_ASSERT(b);
+ b = d_tc->addEdge(7,1);
+ TS_ASSERT(b);
+ b = d_tc->addEdge(8,1);
+ TS_ASSERT(b);
+ b = d_tc->addEdge(9,1);
+ TS_ASSERT(b);
+ }
};/* class TransitiveClosureBlack */