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

Generated on Mon Jan 24 18:36:32 2005 for Sh by  doxygen 1.4.1