# HG changeset patch # User marci # Date 1096565420 0 # Node ID e89f3bd26fd46373f50e24d9c6f52431a0646de8 # Parent 882790531532084ca5aa46476d604b4c35767693 documentation os SubGraphWrapper with code example. diff -r 882790531532 -r e89f3bd26fd4 src/lemon/graph_wrapper.h --- a/src/lemon/graph_wrapper.h Thu Sep 30 16:08:20 2004 +0000 +++ b/src/lemon/graph_wrapper.h Thu Sep 30 17:30:20 2004 +0000 @@ -327,48 +327,159 @@ - /// A graph wrapper for hiding nodes and edges from a graph. + /*! \brief A graph wrapper for hiding nodes and edges from a graph. - ///\warning Graph wrappers are in even more experimental state than the other - ///parts of the lib. Use them at you own risk. - /// - /// This wrapper shows a graph with filtered node-set and - /// edge-set. - /// Given a bool-valued map on the node-set and one on - /// the edge-set of the graph, the iterators show only the objects - /// having true value. We have to note that this does not mean that an - /// induced subgraph is obtained, the node-iterator cares only the filter - /// on the node-set, and the edge-iterators care only the filter on the - /// edge-set. - /// \code - /// typedef SmartGraph Graph; - /// Graph g; - /// typedef Graph::Node Node; - /// typedef Graph::Edge Edge; - /// Node u=g.addNode(); //node of id 0 - /// Node v=g.addNode(); //node of id 1 - /// Node e=g.addEdge(u, v); //edge of id 0 - /// Node f=g.addEdge(v, u); //edge of id 1 - /// Graph::NodeMap nm(g, true); - /// nm.set(u, false); - /// Graph::EdgeMap em(g, true); - /// em.set(e, false); - /// typedef SubGraphWrapper, Graph::EdgeMap > SubGW; - /// SubGW gw(g, nm, em); - /// for (SubGW::NodeIt n(gw); n!=INVALID; ++n) std::cout << g.id(n) << std::endl; - /// std::cout << ":-)" << std::endl; - /// for (SubGW::EdgeIt e(gw); e!=INVALID; ++e) std::cout << g.id(e) << std::endl; - /// \endcode - /// The output of the above code is the following. - /// \code - /// 1 - /// :-) - /// 1 - /// \endcode - /// Note that \c n is of type \c SubGW::NodeIt, but it can be converted to - /// \c Graph::Node that is why \c g.id(n) can be applied. - /// - ///\author Marton Makai + \warning Graph wrappers are in even more experimental state than the other + parts of the lib. Use them at you own risk. + + This wrapper shows a graph with filtered node-set and + edge-set. + Given a bool-valued map on the node-set and one on + the edge-set of the graph, the iterators show only the objects + having true value. We have to note that this does not mean that an + induced subgraph is obtained, the node-iterator cares only the filter + on the node-set, and the edge-iterators care only the filter on the + edge-set. + \code + typedef SmartGraph Graph; + Graph g; + typedef Graph::Node Node; + typedef Graph::Edge Edge; + Node u=g.addNode(); //node of id 0 + Node v=g.addNode(); //node of id 1 + Node e=g.addEdge(u, v); //edge of id 0 + Node f=g.addEdge(v, u); //edge of id 1 + Graph::NodeMap nm(g, true); + nm.set(u, false); + Graph::EdgeMap em(g, true); + em.set(e, false); + typedef SubGraphWrapper, Graph::EdgeMap > SubGW; + SubGW gw(g, nm, em); + for (SubGW::NodeIt n(gw); n!=INVALID; ++n) std::cout << g.id(n) << std::endl; + std::cout << ":-)" << std::endl; + for (SubGW::EdgeIt e(gw); e!=INVALID; ++e) std::cout << g.id(e) << std::endl; + \endcode + The output of the above code is the following. + \code + 1 + :-) + 1 + \endcode + Note that \c n is of type \c SubGW::NodeIt, but it can be converted to + \c Graph::Node that is why \c g.id(n) can be applied. + + Consider now a mathematically more invloved problem, where the application + of SubGraphWrapper is reasonable sure enough. If a shortest path is to be + searched between two nodes \c s and \c t, then this can be done easily by + applying the Dijkstra algorithm class. What happens, if a maximum number of + edge-disjoint shortest paths is to be computed. It can be proved that an + edge can be in a shortest path if and only if it is tight with respect to + the potential function computed by Dijkstra. Moreover, any path containing + only such edges is a shortest one. Thus we have to compute a maximum number + of edge-disjoint path between \c s and \c t in the graph which has edge-set + all the tight edges. The computation will be demonstrated on the following + graph, which is read from a dimacs file. + + \dot + digraph lemon_dot_example { + node [ shape=ellipse, fontname=Helvetica, fontsize=10 ]; + n0 [ label="0 (s)" ]; + n1 [ label="1" ]; + n2 [ label="2" ]; + n3 [ label="3" ]; + n4 [ label="4" ]; + n5 [ label="5" ]; + n6 [ label="6 (t)" ]; + edge [ shape=ellipse, fontname=Helvetica, fontsize=10 ]; + n5 -> n6 [ label="9, length:4" ]; + n4 -> n6 [ label="8, length:2" ]; + n3 -> n5 [ label="7, length:1" ]; + n2 -> n5 [ label="6, length:3" ]; + n2 -> n6 [ label="5, length:5" ]; + n2 -> n4 [ label="4, length:2" ]; + n1 -> n4 [ label="3, length:3" ]; + n0 -> n3 [ label="2, length:1" ]; + n0 -> n2 [ label="1, length:2" ]; + n0 -> n1 [ label="0, length:3" ]; + } + \enddot + + \code + Graph g; + Node s, t; + LengthMap length(g); + + readDimacs(std::cin, g, length, s, t); + + cout << "edges with lengths (of form id, tail--length->head): " << endl; + for(EdgeIt e(g); e!=INVALID; ++e) + cout << g.id(e) << ", " << g.id(g.tail(e)) << "--" + << length[e] << "->" << g.id(g.head(e)) << endl; + + cout << "s: " << g.id(s) << " t: " << g.id(t) << endl; + \endcode + Next, the potential function is computed with Dijkstra. + \code + typedef Dijkstra Dijkstra; + Dijkstra dijkstra(g, length); + dijkstra.run(s); + \endcode + Next, we consrtruct a map which filters the edge-set to the tight edges. + \code + typedef TightEdgeFilterMap + TightEdgeFilter; + TightEdgeFilter tight_edge_filter(g, dijkstra.distMap(), length); + + ConstMap const_true_map(true); + typedef SubGraphWrapper, TightEdgeFilter> SubGW; + SubGW gw(g, const_true_map, tight_edge_filter); + \endcode + Then, the maximum nimber of edge-disjoint \c s-\c t paths are computed + with a max flow algorithm Preflow. + \code + ConstMap const_1_map(1); + Graph::EdgeMap flow(g, 0); + + Preflow, Graph::EdgeMap > + preflow(gw, s, t, const_1_map, flow); + preflow.run(); + \endcode + Last, the output is: + \code + cout << "maximum number of edge-disjoint shortest path: " + << preflow.flowValue() << endl; + cout << "edges of the maximum number of edge-disjoint shortest s-t paths: " + << endl; + for(EdgeIt e(g); e!=INVALID; ++e) + if (flow[e]) + cout << " " << g.id(g.tail(e)) << "--" + << length[e] << "->" << g.id(g.head(e)) << endl; + \endcode + The program has the following (expected :-)) output: + \code + edges with lengths (of form id, tail--length->head): + 9, 5--4->6 + 8, 4--2->6 + 7, 3--1->5 + 6, 2--3->5 + 5, 2--5->6 + 4, 2--2->4 + 3, 1--3->4 + 2, 0--1->3 + 1, 0--2->2 + 0, 0--3->1 + s: 0 t: 6 + maximum number of edge-disjoint shortest path: 2 + edges of the maximum number of edge-disjoint shortest s-t paths: + 9, 5--4->6 + 8, 4--2->6 + 7, 3--1->5 + 4, 2--2->4 + 2, 0--1->3 + 1, 0--2->2 + \endcode + \author Marton Makai + */ template class SubGraphWrapper : public GraphWrapper {