00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #ifndef TREEWIDTH_H
00046 #define TREEWIDTH_H
00047
00048 #include <iostream>
00049 #include <map>
00050 #include <set>
00051 #include <stack>
00052 #include <string>
00053 #include <vector>
00054 #include "graph.h"
00055 using namespace std;
00056
00057 typedef MyNode Node;
00058 typedef MyEdge Edge;
00059 typedef MyNode::EdgeIterator EdgeIterator;
00060 typedef MyGraph Graph;
00061 typedef MyGraph::NodeIterator NodeIterator;
00062 typedef string NodeId;
00063
00064 class Treewidth {
00065
00066 private:
00067
00068 int low;
00069 Graph graph;
00070
00071 public:
00072
00073 enum RuleType {ISLET_RULE = 1, TWIG_RULE = 2, SERIES_RULE = 4,
00074 TRIANGLE_RULE = 8, SIMPLICIAL_RULE = 16, ALMOST_SIMPLICIAL_RULE = 32,
00075 ALL_RULES_MASK = 0xffff};
00076
00077
00078 Treewidth(string graphFile) : graph(graphFile, "asdf"), low(0) {}
00079 Treewidth(Graph graphIn) : graph(graphIn), low(0) {}
00080
00081 void getGraph(Graph &g) const {
00082 g = graph;
00083 }
00084
00085
00086 Graph getGraphCopy() {
00087 Graph g = graph;
00088 return g;
00089 }
00090
00091 vector<NodeId> getNodes() {
00092 vector<NodeId> nodes;
00093 NodeIterator nodesItr = graph.nodes();
00094 while (nodesItr.hasNext()) {
00095 Node node = nodesItr.next();
00096 nodes.push_back(node.getId());
00097 }
00098 return nodes;
00099 }
00100
00101 int getDegree(NodeId nodeId) {
00102 return graph.degree(nodeId);
00103 }
00104
00105 int getLow() {
00106 return low;
00107 }
00108
00109 int numNodes() {
00110 return graph.numNodes();
00111 }
00112
00113 int numEdges() {
00114 return graph.numEdges();
00115 }
00116
00117 void printEdges(ostream& ostr) {
00118 graph.printEdges(ostr);
00119 }
00120
00121 void runRule(RuleType rule) {
00122 stack<string> nodesToProcess;
00123 set<string> deletedNodes;
00124 NodeIterator nodesItr = graph.nodes();
00125 while (nodesItr.hasNext()) {
00126 Node node = nodesItr.next();
00127 nodesToProcess.push(node.getId());
00128 }
00129 while (!nodesToProcess.empty()) {
00130 NodeId nodeId = nodesToProcess.top();
00131 nodesToProcess.pop();
00132
00133 if (deletedNodes.find(nodeId) != deletedNodes.end())
00134 continue;
00135
00136 int degree = graph.degree(nodeId);
00137 switch(rule) {
00138 case ISLET_RULE:
00139 if (degree == 0) {
00140
00141 graph.deleteNode(nodeId);
00142 deletedNodes.insert(nodeId);
00143 }
00144 break;
00145 case TWIG_RULE:
00146 if (degree == 1) {
00147 pushNeighbors(nodesToProcess, nodeId);
00148
00149 graph.deleteNode(nodeId);
00150 deletedNodes.insert(nodeId);
00151 updateLow(degree);
00152 }
00153 break;
00154 case SERIES_RULE:
00155 if (degree == 2) {
00156 pushNeighbors(nodesToProcess, nodeId);
00157 connectNeighbors(nodeId);
00158
00159 graph.deleteNode(nodeId);
00160 deletedNodes.insert(nodeId);
00161 updateLow(degree);
00162 }
00163 break;
00164 case TRIANGLE_RULE:
00165 if (degree == 3) {
00166 vector<NodeId> neighbors = getNeighbors(nodeId);
00167 if (graph.isEdge(neighbors[0], neighbors[1])
00168 || graph.isEdge(neighbors[1], neighbors[2])
00169 || graph.isEdge(neighbors[0], neighbors[2])) {
00170 pushNeighbors(nodesToProcess, nodeId);
00171 connectNeighbors(nodeId);
00172
00173 graph.deleteNode(nodeId);
00174 deletedNodes.insert(nodeId);
00175 updateLow(degree);
00176 }
00177 }
00178 break;
00179 case SIMPLICIAL_RULE:
00180 if (isSimplicial(nodeId)) {
00181 pushNeighbors(nodesToProcess, nodeId);
00182
00183 graph.deleteNode(nodeId);
00184 deletedNodes.insert(nodeId);
00185 updateLow(degree);
00186 }
00187 break;
00188 case ALMOST_SIMPLICIAL_RULE:
00189 if (isAlmostSimplicial(nodeId)) {
00190 pushNeighbors(nodesToProcess, nodeId);
00191 connectNeighbors(nodeId);
00192
00193 graph.deleteNode(nodeId);
00194 deletedNodes.insert(nodeId);
00195 updateLow(degree);
00196 }
00197 break;
00198 }
00199 }
00200 }
00201
00202
00203 void connectNeighbors(NodeId nodeId) {
00204 vector<NodeId> neighbors = getNeighbors(nodeId);
00205 for (int i = 0; i < neighbors.size(); i++) {
00206 for (int j = i+1; j < neighbors.size(); j++) {
00207 graph.addEdge(neighbors[i], neighbors[j]);
00208 }
00209 }
00210 }
00211
00212
00213 void pushNeighbors(stack<NodeId>& s, NodeId nodeId) {
00214 vector<NodeId> neighbors = getNeighbors(nodeId);
00215 for (int i = 0; i < neighbors.size(); i++) {
00216 s.push(neighbors[i]);
00217 }
00218 }
00219
00220 void updateLow(int degree) {
00221 low = degree > low ? degree : low;
00222 }
00223
00224
00225 bool isSimplicial(NodeId nodeId) {
00226 if (graph.degree(nodeId) <= 1)
00227 return true;
00228 vector<NodeId> neighbors = getNeighbors(nodeId);
00229 int size = neighbors.size();
00230 for (int i = 0; i < size; i++) {
00231 for (int j = i+1; j < size; j++) {
00232 if (!graph.isEdge(neighbors[i], neighbors[j])) {
00233 return false;
00234 }
00235 }
00236 }
00237 return true;
00238 }
00239
00240
00241
00242 bool isAlmostSimplicial(NodeId nodeId) {
00243 if (graph.degree(nodeId) <= 2)
00244 return true;
00245 map< NodeId, set<NodeId> > neigborsMap;
00246 vector<NodeId> neighbors = getNeighbors(nodeId);
00247 int numNeighbors = neighbors.size();
00248
00249
00250 for (int i = 0; i < numNeighbors ; i++) {
00251 set<NodeId> neighborsNeighbors;
00252 neighborsNeighbors.insert(neighbors[i]);
00253 for (int j = 0; j < numNeighbors; j++) {
00254 if (i == j) continue;
00255 if (graph.isEdge(neighbors[i], neighbors[j])) {
00256 neighborsNeighbors.insert(neighbors[j]);
00257 }
00258 }
00259 neigborsMap[neighbors[i]] = neighborsNeighbors;
00260 }
00261 bool foundLonely = false;
00262 NodeId lonelyNodeId = "";
00263 for (int i = 0; i < numNeighbors ; i++) {
00264 if (neigborsMap[neighbors[i]].size() < numNeighbors-1) {
00265 if (foundLonely && neighbors[i] != lonelyNodeId) {
00266 return false;
00267 } else {
00268 foundLonely = true;
00269 lonelyNodeId = neighbors[i];
00270 }
00271 } else if (neigborsMap[neighbors[i]].size() == numNeighbors-1) {
00272 for (int j = 0; j < numNeighbors; j++) {
00273
00274 if (neigborsMap[neighbors[i]].find(neighbors[j]) ==
00275 neigborsMap[neighbors[i]].end()) {
00276 if (foundLonely && neighbors[j] != lonelyNodeId) {
00277 return false;
00278 } else {
00279 foundLonely = true;
00280 lonelyNodeId = neighbors[j];
00281 }
00282 }
00283 }
00284 }
00285 }
00286 return true;
00287 }
00288
00289 vector<NodeId> getNeighbors(NodeId nodeId) {
00290 vector<NodeId> neighbors;
00291 EdgeIterator edgeItr = graph.incidentEdges(nodeId);
00292 while (edgeItr.hasNext()) {
00293 Edge edge = *edgeItr.next();
00294 Node* nodePtr = edge.opposite(nodeId);
00295 neighbors.push_back(nodePtr->getId());
00296 }
00297 return neighbors;
00298 }
00299
00300 void core(unsigned int k) {
00301 graph.core(k, graph, false, &cout);
00302 }
00303
00304
00305 vector<NodeId> getClique(NodeId nodeId) {
00306 vector<NodeId> nodes;
00307 if (isSimplicial(nodeId)) {
00308 nodes = getNeighbors(nodeId);
00309 nodes.push_back(nodeId);
00310 return nodes;
00311 }
00312
00313 return nodes;
00314 }
00315
00316 void reduce() {
00317 unsigned int prevSize = 0;
00318 while (numNodes() != prevSize) {
00319 prevSize = numNodes();
00320
00321 cout << "running islet rule... ";
00322 runRule(ISLET_RULE);
00323 cout << " num nodes: " << numNodes()
00324 << "\tlow: " << getLow() << endl;
00325
00326 cout << "running twig rule... ";
00327 runRule(TWIG_RULE);
00328 cout << " num nodes: " << numNodes()
00329 << "\tlow: " << getLow() << endl;
00330 if (numNodes() != prevSize) continue;
00331
00332 cout << "running series rule... ";
00333 runRule(SERIES_RULE);
00334 cout << " num nodes: " << numNodes()
00335 << "\tlow: " << getLow() << endl;
00336 if (numNodes() != prevSize) continue;
00337
00338 cout << "running triangleRule... ";
00339 runRule(TRIANGLE_RULE);
00340 cout << " num nodes: " << numNodes()
00341 << "\tlow: " << getLow() << endl;
00342 if (numNodes() != prevSize) continue;
00343
00344 cout << "running simplicialRule... ";
00345 runRule(SIMPLICIAL_RULE);
00346 cout << " num nodes: " << numNodes()
00347 << "\tlow: " << getLow() << endl;
00348 if (numNodes() != prevSize) continue;
00349
00350 cout << "running almostSimplicialRule...";
00351 runRule(ALMOST_SIMPLICIAL_RULE);
00352 cout << " num nodes: " << numNodes()
00353 << "\tlow: " << getLow() << endl;
00354
00355 }
00356 }
00357
00358 int lowerBound() {
00359 reduce();
00360 return low;
00361 }
00362
00363 };
00364
00365 #endif