00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00028 #ifndef TREEDECOMPOSITION_H
00029 #define TREEDECOMPOSITION_H
00030
00031 #include <iostream>
00032 #include <string>
00033 #include <list>
00034 #include <vector>
00035 #include <set>
00036 #include <sstream>
00037 #include <stack>
00038 #include "graph.h"
00039 #include "treewidth.h"
00040 using namespace std;
00041
00042 typedef MyNode Node;
00043 typedef MyEdge Edge;
00044 typedef MyNode::EdgeIterator EdgeIterator;
00045 typedef MyGraph Graph;
00046 typedef MyGraph::NodeIterator NodeIterator;
00047 typedef string NodeId;
00048 typedef string BagId;
00049
00058 class TreeDecomposition {
00059
00060 private:
00061 map< BagId, set<NodeId> > bagMap;
00062 map< BagId, set<NodeId> > blackNodesMap;
00063 Graph _tree;
00064 const Graph _origGraph;
00065 vector<BagId> bagOrder;
00066 vector<NodeId> nodeOrder;
00067 int bagCount;
00068 int nodeCount;
00069
00070 vector<NodeId> getNodes(Graph graph) {
00071 vector<NodeId> nodes;
00072 NodeIterator nodesItr = graph.nodes();
00073 while (nodesItr.hasNext()) {
00074 Node node = nodesItr.next();
00075 nodes.push_back(node.getId());
00076 }
00077 return nodes;
00078 }
00079
00080 vector<Edge> getEdges(Graph& graph) {
00081 vector<Edge> edges;
00082 Graph::MyEdgeIterator edgeItr = graph.edges();
00083 while (edgeItr.hasNext()) {
00084 Edge edge = edgeItr.next();
00085 edges.push_back(edge);
00086 }
00087 return edges;
00088 }
00089
00090 vector<NodeId> getNeighbors(Graph& graph, NodeId nodeId) {
00091 vector<NodeId> neighbors;
00092 EdgeIterator edgeItr = graph.incidentEdges(nodeId);
00093 while (edgeItr.hasNext()) {
00094 const Edge& edge = *edgeItr.next();
00095 Node* nodePtr = edge.opposite(nodeId);
00096 neighbors.push_back(nodePtr->getId());
00097 }
00098 return neighbors;
00099 }
00100
00101 set<NodeId> getNeighborSet(Graph& graph, NodeId nodeId) {
00102 cout << endl << "getNeighborSet called: ";
00103 set<NodeId> result;
00104 vector<NodeId> neighbors = getNeighbors(graph, nodeId);
00105 for (int i = 0; i < neighbors.size(); i++) {
00106 result.insert(neighbors[i]);
00107 }
00108 cout << result << endl;
00109 return result;
00110 }
00111
00112
00113 void connectNeighbors(Graph& graph, NodeId nodeId) {
00114 vector<NodeId> neighbors = getNeighbors(graph, nodeId);
00115 for (int i = 0; i < neighbors.size(); i++) {
00116 for (int j = i+1; j < neighbors.size(); j++) {
00117 graph.addEdge(neighbors[i], neighbors[j]);
00118 }
00119 }
00120 }
00121
00122
00123 bool isTree(Graph& graph) {
00124 if (graph.numNodes() != graph.numEdges() + 1)
00125 return false;
00126 Treewidth treewidth(graph);
00127 int prevSize = 0;
00128 while (treewidth.numNodes() != prevSize) {
00129 prevSize = treewidth.numNodes();
00130 treewidth.runRule(Treewidth::TWIG_RULE);
00131 }
00132 return treewidth.numNodes() == 1;
00133 }
00134
00135
00136 bool isClique(Graph& graph) {
00137 unsigned int numNodes = graph.numNodes();
00138 unsigned int numEdges = graph.numEdges();
00139 if (numNodes*(numNodes - 1)/2 == numEdges)
00140 return true;
00141 return(false);
00142 }
00143
00144
00145
00146 BagId findBagWithNeighbors(set<NodeId> neighborSet, int minIndex) {
00147 BagId bagId;
00148 set<BagId> bagSet;
00149 vector<BagId> intersection(neighborSet.size());
00150 vector<BagId>::iterator endOfIntersection;
00151 for (int i = minIndex; i < bagOrder.size(); i++) {
00152 bagId = bagOrder[i];
00153 set<BagId> bagSet = bagMap[bagId];
00154 endOfIntersection = set_intersection(
00155 neighborSet.begin(), neighborSet.end(),
00156 bagSet.begin(), bagSet.end(), intersection.begin());
00157 int intersectionSize = endOfIntersection - intersection.begin();
00158 if (intersectionSize == neighborSet.size())
00159 return bagId;
00160 }
00161 return "";
00162 }
00163
00165 BagId addBag(const set<NodeId>& nodeSet) {
00166 ostringstream oss;
00167 oss << "bag" << (1000000 + bagCount);
00168 BagId bagId = oss.str();
00169 _tree.addNode(bagId);
00170 bagMap[bagId] = nodeSet;
00171 bagCount++;
00172 updateBlackNodes(bagId, nodeSet);
00173 return bagId;
00174 }
00175
00179 void updateBlackNodes(BagId bagId, const set<NodeId>& nodeSet) {
00180 Graph induced;
00181 _origGraph.computeInducedSubgraph(nodeSet, induced);
00182
00183 NodeIterator itr = induced.nodes();
00184 while (itr.hasNext()) {
00185 Node node = itr.next();
00186 if (node.degree() == 0)
00187 blackNodesMap[bagId].insert(node.getId());
00188 }
00189 }
00190
00191 public:
00192 TreeDecomposition()
00193 : bagCount(0), nodeCount(0) {}
00194
00195 TreeDecomposition(Graph graph)
00196 : bagCount(0), nodeCount(0), _origGraph(graph) {}
00197
00198 void printBags() {
00199 for (map< BagId, set<NodeId> >::iterator itr = bagMap.begin();
00200 itr != bagMap.end(); itr++) {
00201
00202 BagId bagId = itr->first;
00203 cout << bagId << "|";
00204 set<NodeId> nodes = itr->second;
00205 for (set<NodeId>::iterator nodeItr = nodes.begin();
00206 nodeItr != nodes.end(); nodeItr++) {
00207 NodeId nodeId = *nodeItr;
00208 cout << nodeId;
00209 set<NodeId> blackNodes = blackNodesMap[bagId];
00210 if (blackNodes.find(nodeId) != blackNodes.end())
00211 cout << "*";
00212 cout << ' ';
00213 }
00214 cout << endl;
00215 }
00216 }
00217
00218 int getMaxBagSize() {
00219 int max = 0;
00220 map< BagId, set<NodeId> >::iterator itr = bagMap.begin();
00221 while (itr != bagMap.end()) {
00222 if (itr->second.size() > max)
00223 max = itr->second.size();
00224 itr++;
00225 }
00226 return max;
00227 }
00228
00230 BagId getMaxBagId() {
00231 BagId maxBagId = "undefined";
00232 int max = 0;
00233 map< BagId, set<NodeId> >::iterator itr = bagMap.begin();
00234 while (itr != bagMap.end()) {
00235 if (itr->second.size() > max) {
00236 max = itr->second.size();
00237 maxBagId = itr->first;
00238 }
00239 itr++;
00240 }
00241 return maxBagId;
00242 }
00243
00244 set<NodeId> getBlackNodesForBagId(BagId bagId) {
00245 return blackNodesMap[bagId];
00246 }
00247
00255 class TreeWidthNodeSelector
00256 {
00257 protected:
00258
00259
00260 MyGraph &_graph;
00261 public:
00262 TreeWidthNodeSelector(MyGraph & g)
00263 : _graph(g)
00264 {}
00265
00266 virtual ~TreeWidthNodeSelector()
00267 {}
00268
00270 virtual void initialise() = 0;
00271
00273 virtual MyNodeId getNextNode() = 0;
00274
00278 virtual void update(MyNodeId deletedNodeId, set< MyNodeId > &neighbours)=0;
00279
00280 };
00281
00287 class TreeWidthNodeSelectorMinDegree : public TreeWidthNodeSelector
00288 {
00289 protected:
00290
00291 unsigned int _minDegree;
00292
00293
00294
00295 vector< list< MyNodeId > > _degreeLists;
00296
00297
00298
00299 map< MyNodeId, list< MyNodeId >::iterator > _nodePositions;
00300 public:
00301 TreeWidthNodeSelectorMinDegree(MyGraph & g)
00302 : TreeWidthNodeSelector(g), _minDegree(0),
00303 _degreeLists(_graph.numNodes() + 1),
00304 _nodePositions()
00305 {}
00306
00307 virtual ~TreeWidthNodeSelectorMinDegree()
00308 {}
00309
00311
00312 virtual void initialise() {
00313 _graph._createDegreeLists(_minDegree, _degreeLists, _nodePositions);
00314 }
00315
00317 virtual MyNodeId getNextNode() {
00318 static unsigned int numNodes = 0;
00319
00320
00321 string nodeId = _degreeLists[_minDegree].front();
00322 _degreeLists[_minDegree].pop_front();
00323 cout << ++numNodes << " Returning node " << nodeId << " with degree "
00324 << _minDegree << ". ";
00325 return(nodeId);
00326 }
00327
00328
00333 virtual void update(MyNodeId deletedNodeId, set<NodeId> &neighbours) {
00334
00335 _graph._decrementDegrees(_degreeLists, _nodePositions, neighbours);
00336
00337
00338 if ((0 != _minDegree) && (0 != _degreeLists[_minDegree - 1].size()))
00339 _minDegree--;
00340 else if (0 != _degreeLists[_minDegree].size()) {}
00341 else while ((_minDegree <= _graph.numNodes()) &&
00342 (0 == _degreeLists[++_minDegree].size()));
00343 }
00344
00345 };
00346
00347 struct MyNodeFillInRatioPQNode
00348 {
00349 MyNT _fillInRatio;
00350 unsigned int _fillIn;
00351 MyNodeId _id;
00352 };
00353
00354
00355
00356
00357 struct compareFillInValues : public
00358 binary_function<
00359 const MyNodeFillInRatioPQNode&, const MyNodeFillInRatioPQNode&, bool>
00360 {
00361 bool operator()(
00362 const MyNodeFillInRatioPQNode& __x,
00363 const MyNodeFillInRatioPQNode& __y) const
00364 {
00365 return(__x._fillIn > __y._fillIn);
00366 }
00367 };
00368
00376 class TreeWidthNodeSelectorMinFillIn : public TreeWidthNodeSelector
00377 {
00378 protected:
00379 typedef priority_queue< MyNodeFillInRatioPQNode,
00380 vector< MyNodeFillInRatioPQNode >,
00381 compareFillInValues >
00382 MyFillInPQ;
00383 MyFillInPQ _npq;
00384
00385 vector<NodeId> getNeighbors(Graph& graph, NodeId nodeId) {
00386 vector<NodeId> neighbors;
00387 EdgeIterator edgeItr = graph.incidentEdges(nodeId);
00388 while (edgeItr.hasNext()) {
00389 const Edge& edge = *edgeItr.next();
00390 Node* nodePtr = edge.opposite(nodeId);
00391 neighbors.push_back(nodePtr->getId());
00392 }
00393 return neighbors;
00394 }
00395
00396
00397 unsigned int computeFillIn(Graph& graph, NodeId nodeId) {
00398 vector<NodeId> neighbors = getNeighbors(graph, nodeId);
00399 unsigned int fillIn = 0;
00400 for (int i = 0; i < neighbors.size(); i++) {
00401 for (int j = i+1; j < neighbors.size(); j++) {
00402 if (!graph.isEdge(neighbors[i], neighbors[j]))
00403 fillIn++;
00404 }
00405 }
00406 return(fillIn);
00407 }
00408
00409 public:
00410 TreeWidthNodeSelectorMinFillIn(MyGraph & g)
00411 : TreeWidthNodeSelector(g), _npq() {}
00412
00413 virtual ~TreeWidthNodeSelectorMinFillIn() {}
00414
00416 virtual void initialise() {
00417 MyGraph::NodeIterator nitr = _graph.nodes();
00418 MyNodeFillInRatioPQNode npqNode;
00419 MyNT quotient;
00420 unsigned int degree;
00421 while (nitr.hasNext())
00422 {
00423 MyNode &node = nitr.next();
00424 npqNode._id = node.getId();
00425 npqNode._fillIn = computeFillIn(_graph, npqNode._id);
00426 degree = node.degree();
00427 quotient = degree*(degree - 1)/2.0;
00428 if (0 == quotient)
00429 npqNode._fillInRatio = 0;
00430 else
00431 npqNode._fillInRatio = npqNode._fillIn/quotient;
00432 _npq.push(npqNode);
00433 }
00434 }
00435
00437 virtual MyNodeId getNextNode() {
00438 static unsigned int numNodes = 0;
00439 MyNodeFillInRatioPQNode pqNode;
00440 do
00441 {
00442 pqNode = _npq.top();
00443 _npq.pop();
00444 }
00445
00446
00447 while (!_graph.isNode(pqNode._id));
00448 cout << ++numNodes << " Returning node " << pqNode._id
00449 << " with fill in " << pqNode._fillIn
00450 << " and fill in ratio " << pqNode._fillInRatio << ". ";
00451
00452 return(pqNode._id);
00453 }
00454
00459 virtual void update(MyNodeId deletedNodeId, set<NodeId> &neighbours) {
00460 set<NodeId>::const_iterator nitr;
00461 MyNodeFillInRatioPQNode npqNode;
00462 unsigned int degree;
00463 MyNT quotient;
00464 for (nitr = neighbours.begin(); nitr != neighbours.end(); nitr++)
00465 {
00466 npqNode._id = *nitr;
00467 npqNode._fillIn = computeFillIn(_graph, npqNode._id);
00468 degree = _graph._getNode(npqNode._id).degree();
00469 quotient = degree*(degree - 1)/2.0;
00470 if (0 == quotient)
00471 npqNode._fillInRatio = 0;
00472 else
00473 npqNode._fillInRatio = npqNode._fillIn/quotient;
00474 _npq.push(npqNode);
00475 }
00476 }
00477
00478 };
00479
00480
00481
00482
00483
00484 struct compareFillInRatioValues
00485 : public binary_function< const MyNodeFillInRatioPQNode&,
00486 const MyNodeFillInRatioPQNode&, bool>
00487 {
00488 bool operator()(const MyNodeFillInRatioPQNode& __x,
00489 const MyNodeFillInRatioPQNode& __y) const
00490 {
00491 return(__x._fillInRatio > __y._fillInRatio);
00492 }
00493 };
00494
00501 class TreeWidthNodeSelectorMinFillInRatio
00502 : public TreeWidthNodeSelectorMinFillIn
00503 {
00504 protected:
00505
00506
00507 typedef priority_queue<
00508 MyNodeFillInRatioPQNode,
00509 vector< MyNodeFillInRatioPQNode >,
00510 compareFillInRatioValues > MyFillInRatioPQ;
00511
00512 MyFillInRatioPQ _npq;
00513 public:
00514 TreeWidthNodeSelectorMinFillInRatio(MyGraph & g)
00515 : TreeWidthNodeSelectorMinFillIn(g), _npq()
00516 {}
00517
00518 virtual ~TreeWidthNodeSelectorMinFillInRatio()
00519 {}
00520 };
00521
00522
00523
00524
00525
00526
00527
00528
00529
00530
00531 void decompose() {
00532 Graph graph = _origGraph;
00533
00534 unsigned int maxBagSize = 0;
00535 MyNodeId id, nodeId;
00536
00537
00538
00539 TreeWidthNodeSelectorMinDegree twns(graph);
00540 twns.initialise();
00541
00542 while (!isTree(graph) && !isClique(graph)) {
00543 nodeId = twns.getNextNode();
00544 nodeOrder.push_back(nodeId);
00545
00546 #ifdef DEBUG
00547
00548 if (!graph.isNode(nodeId)) {
00549 cerr << "Node id " << nodeId
00550 << " is not a graph node but the node selector returned it."
00551 << endl;
00552 continue;
00553 }
00554 #endif
00555 set<NodeId> bagNodes = getNeighborSet(graph, nodeId);
00556 connectNeighbors(graph, nodeId);
00557 graph.deleteNode(nodeId);
00558
00559
00560
00561
00562 twns.update(nodeId, bagNodes);
00563
00564 bagNodes.insert(nodeId);
00565 BagId newBagId = addBag(bagNodes);
00566 cout << "adding bag: " << bagNodes << endl;
00567 bagOrder.push_back(newBagId);
00568 if (bagNodes.size() > maxBagSize)
00569 maxBagSize = bagNodes.size();
00570 cout << " Graph size is (" << graph.numNodes()
00571 << ", " << graph.numEdges() << "). Treewidth is "
00572 << maxBagSize << "." << endl;
00573 }
00574
00575 cout << "Base Case (tree/clique): " << endl;
00576
00577 set<NodeId> nodeSet;
00578 graph.getNodeSet(nodeSet);
00579 BagId newBagId = addBag(nodeSet);
00580 bagOrder.push_back(newBagId);
00581
00582
00583
00584
00585
00586
00587
00588
00589 cout << "Going to add edges" << endl;
00590 for (int i = nodeOrder.size()-1; i >= 0; i--) {
00591 cout << ".";
00592 set<NodeId> naybears = bagMap[bagOrder[i]];
00593 naybears.erase(nodeOrder[i]);
00594 BagId bagToConnect = findBagWithNeighbors(naybears, i+1);
00595 _tree.addEdge(bagOrder[i], bagToConnect);
00596 }
00597 cout << endl;
00598
00599 }
00600
00601 void computeInducedSubtree(const NodeId nodeId, TreeDecomposition& subtree) {
00602 set<NodeId> bag;
00603 bag.insert(nodeId);
00604 set<BagId> bagsWithNode;
00605
00606 NodeIterator bagItr = _tree.nodes();
00607 while (bagItr.hasNext()) {
00608 BagId bagId = bagItr.next().getId();
00609 set<NodeId> nodeSet = bagMap[bagId];
00610 if (nodeSet.find(nodeId) != nodeSet.end()) {
00611 cout << "found bag: " << bagId << endl;
00612 bagsWithNode.insert(bagId);
00613 subtree.bagMap[bagId] = bag;
00614 }
00615 }
00616
00617 _tree.computeInducedSubgraph(bagsWithNode, subtree._tree);
00618 }
00619
00620 };
00621
00622 #endif