Main Page | Modules | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

ShGraphImpl.hpp

00001 // Sh: A GPU metaprogramming language.
00002 //
00003 // Copyright 2003-2005 Serious Hack Inc.
00004 // 
00005 // This software is provided 'as-is', without any express or implied
00006 // warranty. In no event will the authors be held liable for any damages
00007 // arising from the use of this software.
00008 // 
00009 // Permission is granted to anyone to use this software for any purpose,
00010 // including commercial applications, and to alter it and redistribute it
00011 // freely, subject to the following restrictions:
00012 // 
00013 // 1. The origin of this software must not be misrepresented; you must
00014 // not claim that you wrote the original software. If you use this
00015 // software in a product, an acknowledgment in the product documentation
00016 // would be appreciated but is not required.
00017 // 
00018 // 2. Altered source versions must be plainly marked as such, and must
00019 // not be misrepresented as being the original software.
00020 // 
00021 // 3. This notice may not be removed or altered from any source
00022 // distribution.
00024 #ifndef SHGRAPHIMPL_HPP 
00025 #define SHGRAPHIMPL_HPP 
00026 
00027 #include "ShGraph.hpp"
00028 #include <stack>
00029 #include <map>
00030 
00031 namespace SH {
00032 
00033 // TODO should clear arguments passed in by reference to the different
00034 // algs like shortest path and trans closuer
00035 
00036 
00037 template<typename G>
00038 ShGraphVertex<G>::ShGraphVertex()
00039   : marked(false)
00040 {}
00041 
00042 template<typename G>
00043 ShGraphVertex<G>::ShGraphVertex(const ShGraphVertex<G> &other)
00044   : marked(other.marked)
00045 {}
00046 
00047 template<typename G>
00048 std::ostream& ShGraphVertex<G>::graphvizDump(std::ostream &out) const
00049 {
00050   out << " [label=\"\", shape=circle, height=0.25]";
00051   return out;
00052 }
00053 
00054 template<typename G>
00055 ShGraphEdge<G>::ShGraphEdge()
00056   : start(0), end(0)
00057 {}
00058 
00059 template<typename G>
00060 ShGraphEdge<G>::ShGraphEdge(typename G::Vertex *start, typename G::Vertex *end)
00061   : start(start), end(end)
00062 {}
00063 
00064 template<typename G>
00065 ShGraphEdge<G>::ShGraphEdge(const ShGraphEdge<G> &other)
00066   : start(0), end(0) 
00067 {}
00068 
00069 template<typename G>
00070 std::ostream& ShGraphEdge<G>::graphvizDump(std::ostream &out) const
00071 {
00072   return out; // use default edge
00073 }
00074 
00075 template<typename G>
00076 ShGraph<G>::ShGraph()
00077 {}
00078 
00079 template<typename G>
00080 ShGraph<G>::ShGraph(const ShGraph<G> &other)
00081 {
00082   *this = other;
00083 }
00084 
00085 template<typename G>
00086 ShGraph<G>::~ShGraph()
00087 {
00088   clear();
00089 }
00090 
00091 template<typename G>
00092 void ShGraph<G>::addVertex(typename G::Vertex *v)
00093 {
00094   verts.insert(v);
00095 }
00096 
00097 template<typename G>
00098 void ShGraph<G>::addEdge(typename G::Edge *e)
00099 {
00100   edges.insert(e);
00101   e->start->edges.push_back(e);
00102 }
00103 
00104 template<typename G>
00105 void ShGraph<G>::removeVertex(typename G::Vertex *v)
00106 {
00107   for(typename EdgeList::iterator E = v->edges.begin(); E != v->edges.end(); ++E) {
00108     edges.erase(*E);
00109   }
00110   verts.erase(v);
00111 }
00112 
00113 template<typename G>
00114 void ShGraph<G>::removeEdge(typename G::Edge *e)
00115 {
00116   edges.erase(e);
00117   e->start->edges.remove(e);
00118   delete e;
00119 }
00120 
00121 template<typename G>
00122 void ShGraph<G>::clear()
00123 {
00124   for(typename VertexSet::iterator V = verts.begin(); V != verts.end(); ++V) delete *V;
00125   for(typename EdgeSet::iterator E = edges.begin(); E != edges.end(); ++E) delete *E;
00126  
00127   verts.clear();
00128   edges.clear();
00129 }
00130 
00131 template<typename G>
00132 void ShGraph<G>::clearMarked()
00133 {
00134   for(typename VertexSet::iterator V = verts.begin(); V != verts.end(); ++V) (*V)->marked = false;
00135 }
00136 
00137 template<typename G>
00138 ShGraph<G>& ShGraph<G>::operator=(const ShGraph<G> &other)
00139 {
00140   clear();
00141 
00142   VertexMap<Vertex *> vmap;
00143 
00144   // mappings for null pointers
00145   vmap[0] = 0;
00146 
00147   for(typename VertexSet::const_iterator V = other.verts.begin(); V != other.verts.end(); ++V) {
00148     typename G::Vertex *newv = new Vertex(**V);
00149     vmap[*V] = newv;
00150     addVertex(newv);
00151   }
00152 
00153   for(typename EdgeSet::const_iterator E = other.edges.begin(); E != other.edges.end(); ++E) {
00154     typename G::Edge *newe = new Edge(**E);
00155     newe->start = vmap[(*E)->start];
00156     newe->end = vmap[(*E)->end];
00157     addEdge(newe);
00158   }
00159 
00160   return *this;
00161 }
00162 
00163 template<typename G>
00164 template<typename F>
00165 void ShGraph<G>::dfs(typename G::Vertex *start, F &functor)
00166 {
00167   std::stack<typename G::Vertex *> worklist;
00168 
00169   for(worklist.push(start); !worklist.empty(); worklist.pop()) {
00170     typename G::Vertex *workVertex = worklist.top();
00171     if(workVertex->marked) continue; // useful for cycle detection
00172     workVertex->marked = true;
00173 
00174     for(typename EdgeList::iterator E = workVertex->edges.begin(); E != workVertex->edges.end(); ++E) {
00175       worklist.push(E->end);
00176     }
00177     functor(workVertex);
00178   }
00179 }
00180 
00181 template<typename G>
00182 template<typename W>
00183 typename W::WeightType ShGraph<G>::bellmanFord(typename G::Vertex *start, typename G::Vertex *end, W &weigher, EdgeList *path) 
00184 {
00185   // essentially the same as above, with predecessors
00186   // TODO refactor so the algorithm shows up only once
00187   std::map<typename G::Vertex *, typename W::WeightType> dist;
00188   std::map<typename G::Vertex *, typename G::Edge *> pred; // edge going back to predecessor in SP so far
00189 
00190   for(typename VertexSet::const_iterator V = verts.begin(); V != verts.end(); ++V) {
00191     dist[*V] = W::LARGE;
00192     pred[*V] = 0;
00193   }
00194 
00195   dist[start] = W::ZERO; 
00196 
00197   for(int i = 0; i < verts.size(); ++i) {
00198     for(typename EdgeSet::iterator E = edges.begin(); E != edges.end(); ++E) {
00199       Edge &e = **E;
00200 
00201       typename W::WeightType testDist = dist[e.start] + weigher(e);
00202       if(testDist < dist[e.end]) {
00203         dist[e.end] = testDist;
00204         pred[e.end] = &e;
00205       }
00206     }
00207   }
00208 
00209   // trace shortest path
00210   if(path) {
00211     path->clear();
00212     for(typename G::Edge *finger = pred[end]; finger != 0; finger = pred[finger->start]) {
00213       path->push_front(finger);
00214     }
00215   }
00216 
00217   return dist[end];
00218 }
00219 
00220 template<typename G>
00221 template<typename W>
00222 void ShGraph<G>::floydWarshall(W &weigher, VertexPairMap<typename W::WeightType> &dist, FirstStepMap *path) 
00223 {
00224   typename VertexSet::const_iterator V, U, X; 
00225   typename EdgeSet::iterator E;
00226 
00227   dist.clear();
00228   if(path) path->clear();
00229 
00230   // initialize distances to LARGE for distinct pairs
00231   for(V = verts.begin(); V != verts.end(); ++V) for(U = verts.begin(); U != verts.end(); ++U) {
00232     if(V == U) dist(*V, *U) = W::ZERO; 
00233     else dist(*V, *U) = W::LARGE;
00234   }
00235 
00236   // initialize to minimum edge weight for adjacent vertices
00237   for(E = edges.begin(); E != edges.end(); ++E) {
00238     Edge& e = **E;
00239     typename W::WeightType &testDist = dist(e.start, e.end);
00240     if(testDist > weigher(e)) {
00241       testDist = weigher(e);
00242       if(path) (*path)(e.start, e.end) = &e;
00243     }
00244   }
00245 
00246   // do the bottom-up dynamic programming
00247   // loop invariant of the outer loop
00248   //    dist(A, B) contains the shortest path from A to B using only the
00249   //        nodes in verts.begin() to V as intermediates
00250   //    path(A, B) contains the first edge in the above shortest path
00251   for(V = verts.begin(); V != verts.end(); ++V) {
00252     for(U = verts.begin(); U != verts.end(); ++U) {
00253       for(X = verts.begin(); X != verts.end(); ++X) {
00254         typename W::WeightType &oldDist = dist(*U, *X);
00255         typename W::WeightType testDist = dist(*U, *V) + dist(*V, *X);
00256         if(oldDist > testDist && (dist(*U, *V) != W::LARGE && 
00257               dist(*V, *X) != W::LARGE)) {
00258           oldDist = testDist;
00259           if(path) (*path)(*U, *X) = (*path)(*U, *V);
00260         }
00261       }
00262     }
00263   }
00264 }
00265 
00266 
00267 template<typename G>
00268 void ShGraph<G>::transitiveClosure(TransitiveClosureMap &tcm)
00269 {
00270   typename VertexSet::const_iterator V, U, X; 
00271   typename EdgeSet::iterator E;
00272   typedef VertexPairMap<bool> TCMap; // transitive closure map
00273 
00274   // initialize to minimum edge weight for adjacent vertices
00275   tcm.clear();
00276   for(V = verts.begin(); V != verts.end(); ++V) tcm(*V, *V) = true;
00277 
00278   for(E = edges.begin(); E != edges.end(); ++E) {
00279     Edge& e = **E;
00280     tcm(e.start, e.end) = true;
00281   }
00282 
00283   // do bottom-up dynamic programming
00284   for(V = verts.begin(); V != verts.end(); ++V) {
00285     for(U = verts.begin(); U != verts.end(); ++U) {
00286       for(X = verts.begin(); X != verts.end(); ++X) {
00287         tcm(*U, *X) = tcm(*U, *X) || (tcm(*U, *V) && tcm(*V, *X));
00288       }
00289     }
00290   }
00291 }
00292 
00293 template<typename G>
00294 void ShGraph<G>::rootSet(VertexSet &roots) {
00295   roots = verts;
00296   typename EdgeSet::const_iterator E;
00297   for(E = edges.begin(); E != edges.end(); ++E) {
00298     roots.erase((*E)->end);
00299   }
00300 }
00301 
00302 template<typename G>
00303 struct NegativeWeigher {
00304   typedef int WeightType;
00305   static const int LARGE=2000000000; // TODO MAX_INT
00306   static const int ZERO=0;
00307   int operator()(const typename G::Edge &e) { return -1; }
00308 }; 
00309 
00310 template<typename G>
00311 void ShGraph<G>::vertexHeight(const VertexSet &roots, HeightMap &heights) {
00312   heights.clear();
00313   VertexPairMap<int> dist;
00314   NegativeWeigher<G> weigher;
00315   typename VertexSet::const_iterator U, V;
00316 
00317   floydWarshall(weigher, dist);
00318   for(U = verts.begin(); U != verts.end(); ++U) {
00319     for(V = roots.begin(); V != roots.end(); ++V) {
00320       heights[*U] = std::max(heights[*U], -dist(*V, *U));
00321     }
00322   }
00323 }
00324 
00325 
00326 template<typename G>
00327 void ShGraph<G>::leastCommonAncestor(LCAMap &ancestor)
00328 {
00329   typename VertexSet::const_iterator U, V, W;
00330   typename EdgeSet::const_iterator E;
00331 
00332   // First step, identify the "roots" of the DAG (those that have no
00333   // ancestors) 
00334   VertexSet roots;
00335   rootSet(roots);
00336 
00337   // Find the height of each node by longest path distance from any root
00338   HeightMap heights;
00339   vertexHeight(roots, heights);
00340 
00341   // Calculate the transitive closure matrix 
00342   TransitiveClosureMap tcm;
00343   transitiveClosure(tcm);
00344 
00345   // Identify a candidate least common ancestor (greatest height)
00346   // for each pair of verts 
00347   ancestor.clear();
00348   for(U = verts.begin(); U != verts.end(); ++U) {
00349     for(V = verts.begin(); V != verts.end(); ++V) {
00350       int maxHeight = -1;
00351       for(W = verts.begin(); W != verts.end(); ++W) {
00352         // if W is an ancestor of both U and V, check if its the LCA so far 
00353         if(tcm(*W, *U) && tcm(*W, *V) && heights[*W] > maxHeight) {
00354           ancestor(*U, *V) = ancestor(*V, *U) = *W;
00355           maxHeight = heights[*W]; 
00356         }
00357       }
00358     }
00359   }
00360 }
00361 
00362 template<typename G>
00363 std::ostream& ShGraphDefaultDumper<G>::operator()(std::ostream& out, const typename G::Vertex *v)
00364 {
00365   return v->graphvizDump(out);
00366 }
00367 
00368 template<typename G>
00369 std::ostream& ShGraphDefaultDumper<G>::operator()(std::ostream& out, const typename G::Edge *e)
00370 {
00371   return e->graphvizDump(out);
00372 }
00373 
00374 template<typename G>
00375 std::ostream& graphvizDump(std::ostream &out, const ShGraph<G> &g)
00376 {
00377   ShGraphDefaultDumper<G> dumper;
00378   return graphvizDump(out, g, dumper); 
00379 }
00380 
00381 template<typename G, typename D>
00382 std::ostream& graphvizDump(std::ostream &out, const ShGraph<G> &g, D &dumpFunctor)
00383 {
00384   out << "digraph {" << std::endl;
00385     typename ShGraph<G>::VertexSet::const_iterator V = g.verts.begin();
00386     for(; V != g.verts.end(); ++V) {
00387       out << "\"" << *V << "\" ";
00388       dumpFunctor(out, *V);
00389       out << ";" << std::endl;
00390       out << std::endl;
00391     }
00392 
00393     typename ShGraph<G>::EdgeSet::const_iterator E = g.edges.begin();
00394     for(; E != g.edges.end(); ++E) {
00395       const typename G::Edge &e = **E;
00396       out << "\"" << e.start << "\" ";
00397       out << "-> ";
00398       out << "\"" << e.end << "\" ";
00399       dumpFunctor(out, *E);
00400       out << ";" << std::endl;
00401       out << std::endl;
00402     }
00403   out << "}" << std::endl;
00404 
00405   return out;
00406 }
00407 
00408 }
00409 
00410 #endif

Generated on Thu Apr 21 17:32:47 2005 for Sh by  doxygen 1.4.2