diff -r d8475431bbbb -r 8e85e6bbefdf src/lemon/graph_adaptor.h --- a/src/lemon/graph_adaptor.h Sat May 21 21:04:57 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1218 +0,0 @@ -/* -*- C++ -*- - * src/lemon/graph_adaptor.h - Part of LEMON, a generic C++ optimization library - * - * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport - * (Egervary Research Group on Combinatorial Optimization, EGRES). - * - * Permission to use, modify and distribute this software is granted - * provided that this copyright notice appears in all copies. For - * precise terms see the accompanying LICENSE file. - * - * This software is provided "AS IS" with no warranty of any kind, - * express or implied, and with no claim as to its suitability for any - * purpose. - * - */ - -#ifndef LEMON_GRAPH_ADAPTOR_H -#define LEMON_GRAPH_ADAPTOR_H - -///\ingroup graph_adaptors -///\file -///\brief Several graph adaptors. -/// -///This file contains several useful graph adaptor functions. -/// -///\author Marton Makai - -#include -#include -#include -#include -#include - -namespace lemon { - - // Graph adaptors - - /*! - \addtogroup graph_adaptors - @{ - */ - - /*! - Base type for the Graph Adaptors - - \warning Graph adaptors are in even more experimental state than the other - parts of the lib. Use them at you own risk. - - This is the base type for most of LEMON graph adaptors. - This class implements a trivial graph adaptor i.e. it only wraps the - functions and types of the graph. The purpose of this class is to - make easier implementing graph adaptors. E.g. if an adaptor is - considered which differs from the wrapped graph only in some of its - functions or types, then it can be derived from GraphAdaptor, and only the - differences should be implemented. - - \author Marton Makai - */ - template - class GraphAdaptorBase { - public: - typedef _Graph Graph; - /// \todo Is it needed? - typedef Graph BaseGraph; - typedef Graph ParentGraph; - - protected: - Graph* graph; - GraphAdaptorBase() : graph(0) { } - void setGraph(Graph& _graph) { graph=&_graph; } - - public: - GraphAdaptorBase(Graph& _graph) : graph(&_graph) { } - - typedef typename Graph::Node Node; - typedef typename Graph::Edge Edge; - - void first(Node& i) const { graph->first(i); } - void first(Edge& i) const { graph->first(i); } - void firstIn(Edge& i, const Node& n) const { graph->firstIn(i, n); } - void firstOut(Edge& i, const Node& n ) const { graph->firstOut(i, n); } - - void next(Node& i) const { graph->next(i); } - void next(Edge& i) const { graph->next(i); } - void nextIn(Edge& i) const { graph->nextIn(i); } - void nextOut(Edge& i) const { graph->nextOut(i); } - - Node source(const Edge& e) const { return graph->source(e); } - Node target(const Edge& e) const { return graph->target(e); } - - int nodeNum() const { return graph->nodeNum(); } - int edgeNum() const { return graph->edgeNum(); } - - Node addNode() const { return Node(graph->addNode()); } - Edge addEdge(const Node& source, const Node& target) const { - return Edge(graph->addEdge(source, target)); } - - void erase(const Node& i) const { graph->erase(i); } - void erase(const Edge& i) const { graph->erase(i); } - - void clear() const { graph->clear(); } - - bool forward(const Edge& e) const { return graph->forward(e); } - bool backward(const Edge& e) const { return graph->backward(e); } - - int id(const Node& v) const { return graph->id(v); } - int id(const Edge& e) const { return graph->id(e); } - - Edge opposite(const Edge& e) const { return Edge(graph->opposite(e)); } - - template - class NodeMap : public _Graph::template NodeMap<_Value> { - public: - typedef typename _Graph::template NodeMap<_Value> Parent; - NodeMap(const GraphAdaptorBase<_Graph>& gw) : Parent(*gw.graph) { } - NodeMap(const GraphAdaptorBase<_Graph>& gw, const _Value& value) - : Parent(*gw.graph, value) { } - }; - - template - class EdgeMap : public _Graph::template EdgeMap<_Value> { - public: - typedef typename _Graph::template EdgeMap<_Value> Parent; - EdgeMap(const GraphAdaptorBase<_Graph>& gw) : Parent(*gw.graph) { } - EdgeMap(const GraphAdaptorBase<_Graph>& gw, const _Value& value) - : Parent(*gw.graph, value) { } - }; - - }; - - template - class GraphAdaptor : - public IterableGraphExtender > { - public: - typedef _Graph Graph; - typedef IterableGraphExtender > Parent; - protected: - GraphAdaptor() : Parent() { } - - public: - GraphAdaptor(Graph& _graph) { setGraph(_graph); } - }; - - template - class RevGraphAdaptorBase : public GraphAdaptorBase<_Graph> { - public: - typedef _Graph Graph; - typedef GraphAdaptorBase<_Graph> Parent; - protected: - RevGraphAdaptorBase() : Parent() { } - public: - typedef typename Parent::Node Node; - typedef typename Parent::Edge Edge; - - // using Parent::first; - void firstIn(Edge& i, const Node& n) const { Parent::firstOut(i, n); } - void firstOut(Edge& i, const Node& n ) const { Parent::firstIn(i, n); } - - // using Parent::next; - void nextIn(Edge& i) const { Parent::nextOut(i); } - void nextOut(Edge& i) const { Parent::nextIn(i); } - - Node source(const Edge& e) const { return Parent::target(e); } - Node target(const Edge& e) const { return Parent::source(e); } - }; - - - /// A graph adaptor which reverses the orientation of the edges. - - ///\warning Graph adaptors are in even more experimental state than the other - ///parts of the lib. Use them at you own risk. - /// - /// Let \f$G=(V, A)\f$ be a directed graph and - /// suppose that a graph instange \c g of type - /// \c ListGraph implements \f$G\f$. - /// \code - /// ListGraph g; - /// \endcode - /// For each directed edge - /// \f$e\in A\f$, let \f$\bar e\f$ denote the edge obtained by - /// reversing its orientation. - /// Then RevGraphAdaptor implements the graph structure with node-set - /// \f$V\f$ and edge-set - /// \f$\{\bar e : e\in A \}\f$, i.e. the graph obtained from \f$G\f$ be - /// reversing the orientation of its edges. The following code shows how - /// such an instance can be constructed. - /// \code - /// RevGraphAdaptor gw(g); - /// \endcode - ///\author Marton Makai - template - class RevGraphAdaptor : - public IterableGraphExtender > { - public: - typedef _Graph Graph; - typedef IterableGraphExtender< - RevGraphAdaptorBase<_Graph> > Parent; - protected: - RevGraphAdaptor() { } - public: - RevGraphAdaptor(_Graph& _graph) { setGraph(_graph); } - }; - - - template - class SubGraphAdaptorBase : public GraphAdaptorBase<_Graph> { - public: - typedef _Graph Graph; - typedef GraphAdaptorBase<_Graph> Parent; - protected: - NodeFilterMap* node_filter_map; - EdgeFilterMap* edge_filter_map; - SubGraphAdaptorBase() : Parent(), - node_filter_map(0), edge_filter_map(0) { } - - void setNodeFilterMap(NodeFilterMap& _node_filter_map) { - node_filter_map=&_node_filter_map; - } - void setEdgeFilterMap(EdgeFilterMap& _edge_filter_map) { - edge_filter_map=&_edge_filter_map; - } - - public: -// SubGraphAdaptorBase(Graph& _graph, -// NodeFilterMap& _node_filter_map, -// EdgeFilterMap& _edge_filter_map) : -// Parent(&_graph), -// node_filter_map(&node_filter_map), -// edge_filter_map(&edge_filter_map) { } - - typedef typename Parent::Node Node; - typedef typename Parent::Edge Edge; - - void first(Node& i) const { - Parent::first(i); - while (i!=INVALID && !(*node_filter_map)[i]) Parent::next(i); - } - void first(Edge& i) const { - Parent::first(i); - while (i!=INVALID && !(*edge_filter_map)[i]) Parent::next(i); - } - void firstIn(Edge& i, const Node& n) const { - Parent::firstIn(i, n); - while (i!=INVALID && !(*edge_filter_map)[i]) Parent::nextIn(i); - } - void firstOut(Edge& i, const Node& n) const { - Parent::firstOut(i, n); - while (i!=INVALID && !(*edge_filter_map)[i]) Parent::nextOut(i); - } - - void next(Node& i) const { - Parent::next(i); - while (i!=INVALID && !(*node_filter_map)[i]) Parent::next(i); - } - void next(Edge& i) const { - Parent::next(i); - while (i!=INVALID && !(*edge_filter_map)[i]) Parent::next(i); - } - void nextIn(Edge& i) const { - Parent::nextIn(i); - while (i!=INVALID && !(*edge_filter_map)[i]) Parent::nextIn(i); - } - void nextOut(Edge& i) const { - Parent::nextOut(i); - while (i!=INVALID && !(*edge_filter_map)[i]) Parent::nextOut(i); - } - - /// This function hides \c n in the graph, i.e. the iteration - /// jumps over it. This is done by simply setting the value of \c n - /// to be false in the corresponding node-map. - void hide(const Node& n) const { node_filter_map->set(n, false); } - - /// This function hides \c e in the graph, i.e. the iteration - /// jumps over it. This is done by simply setting the value of \c e - /// to be false in the corresponding edge-map. - void hide(const Edge& e) const { edge_filter_map->set(e, false); } - - /// The value of \c n is set to be true in the node-map which stores - /// hide information. If \c n was hidden previuosly, then it is shown - /// again - void unHide(const Node& n) const { node_filter_map->set(n, true); } - - /// The value of \c e is set to be true in the edge-map which stores - /// hide information. If \c e was hidden previuosly, then it is shown - /// again - void unHide(const Edge& e) const { edge_filter_map->set(e, true); } - - /// Returns true if \c n is hidden. - bool hidden(const Node& n) const { return !(*node_filter_map)[n]; } - - /// Returns true if \c n is hidden. - bool hidden(const Edge& e) const { return !(*edge_filter_map)[e]; } - - /// \warning This is a linear time operation and works only if s - /// \c Graph::NodeIt is defined. - /// \todo assign tags. - int nodeNum() const { - int i=0; - Node n; - for (first(n); n!=INVALID; next(n)) ++i; - return i; - } - - /// \warning This is a linear time operation and works only if - /// \c Graph::EdgeIt is defined. - /// \todo assign tags. - int edgeNum() const { - int i=0; - Edge e; - for (first(e); e!=INVALID; next(e)) ++i; - return i; - } - - - }; - - /*! \brief A graph adaptor for hiding nodes and edges from a graph. - - \warning Graph adaptors are in even more experimental state than the other - parts of the lib. Use them at you own risk. - - SubGraphAdaptor shows the graph with filtered node-set and - edge-set. - Let \f$G=(V, A)\f$ be a directed graph - and suppose that the graph instance \c g of type ListGraph implements - \f$G\f$. - Let moreover \f$b_V\f$ and - \f$b_A\f$ be bool-valued functions resp. on the node-set and edge-set. - SubGraphAdaptor<...>::NodeIt iterates - on the node-set \f$\{v\in V : b_V(v)=true\}\f$ and - SubGraphAdaptor<...>::EdgeIt iterates - on the edge-set \f$\{e\in A : b_A(e)=true\}\f$. Similarly, - SubGraphAdaptor<...>::OutEdgeIt and SubGraphAdaptor<...>::InEdgeIt iterates - only on edges leaving and entering a specific node which have 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 ListGraph 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 SubGraphAdaptor, 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. - - For other examples see also the documentation of NodeSubGraphAdaptor and - EdgeSubGraphAdaptor. - - \author Marton Makai - */ - template - class SubGraphAdaptor : - public IterableGraphExtender< - SubGraphAdaptorBase<_Graph, NodeFilterMap, EdgeFilterMap> > { - public: - typedef _Graph Graph; - typedef IterableGraphExtender< - SubGraphAdaptorBase<_Graph, NodeFilterMap, EdgeFilterMap> > Parent; - protected: - SubGraphAdaptor() { } - public: - SubGraphAdaptor(_Graph& _graph, NodeFilterMap& _node_filter_map, - EdgeFilterMap& _edge_filter_map) { - setGraph(_graph); - setNodeFilterMap(_node_filter_map); - setEdgeFilterMap(_edge_filter_map); - } - }; - - - - /*! \brief An adaptor for hiding nodes from a graph. - - \warning Graph adaptors are in even more experimental state than the other - parts of the lib. Use them at you own risk. - - An adaptor for hiding nodes from a graph. - This adaptor specializes SubGraphAdaptor in the way that only the node-set - can be filtered. Note that this does not mean of considering induced - subgraph, the edge-iterators consider the original edge-set. - \author Marton Makai - */ - template - class NodeSubGraphAdaptor : - public SubGraphAdaptor > { - public: - typedef SubGraphAdaptor > Parent; - protected: - ConstMap const_true_map; - public: - NodeSubGraphAdaptor(Graph& _graph, NodeFilterMap& _node_filter_map) : - Parent(), const_true_map(true) { - Parent::setGraph(_graph); - Parent::setNodeFilterMap(_node_filter_map); - Parent::setEdgeFilterMap(const_true_map); - } - }; - - - /*! \brief An adaptor for hiding edges from a graph. - - \warning Graph adaptors are in even more experimental state than the other - parts of the lib. Use them at you own risk. - - An adaptor for hiding edges from a graph. - This adaptor specializes SubGraphAdaptor in the way that only the edge-set - can be filtered. The usefulness of this adaptor is demonstrated in the - problem of searching a maximum number of edge-disjoint shortest paths - between - two nodes \c s and \c t. Shortest here means being shortest w.r.t. - non-negative edge-lengths. Note that - the comprehension of the presented solution - need's some elementary knowledge from combinatorial optimization. - - If a single shortest path is to be - searched between \c s and \c t, then this can be done easily by - applying the Dijkstra algorithm. 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 paths 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 the dimacs file \ref sub_graph_adaptor_demo.dim. - The full source code is available in \ref sub_graph_adaptor_demo.cc. - If you are interested in more demo programs, you can use - \ref dim_to_dot.cc to generate .dot files from dimacs files. - The .dot file of the following figure of was generated generated by - the demo program \ref dim_to_dot.cc. - - \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, source--length->target): " << endl; - for(EdgeIt e(g); e!=INVALID; ++e) - cout << g.id(e) << ", " << g.id(g.source(e)) << "--" - << length[e] << "->" << g.id(g.target(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); - - typedef EdgeSubGraphAdaptor SubGW; - SubGW gw(g, 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.source(e)) << "--" - << length[e] << "->" << g.id(g.target(e)) << endl; - \endcode - The program has the following (expected :-)) output: - \code - edges with lengths (of form id, source--length->target): - 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 EdgeSubGraphAdaptor : - public SubGraphAdaptor, - EdgeFilterMap> { - public: - typedef SubGraphAdaptor, - EdgeFilterMap> Parent; - protected: - ConstMap const_true_map; - public: - EdgeSubGraphAdaptor(Graph& _graph, EdgeFilterMap& _edge_filter_map) : - Parent(), const_true_map(true) { - Parent::setGraph(_graph); - Parent::setNodeFilterMap(const_true_map); - Parent::setEdgeFilterMap(_edge_filter_map); - } - }; - - template - class UndirGraphAdaptorBase : - public UndirGraphExtender > { - public: - typedef _Graph Graph; - typedef UndirGraphExtender > Parent; - protected: - UndirGraphAdaptorBase() : Parent() { } - public: - typedef typename Parent::UndirEdge UndirEdge; - typedef typename Parent::Edge Edge; - - /// \bug Why cant an edge say that it is forward or not??? - /// By this, a pointer to the graph have to be stored - /// The implementation - template - class EdgeMap { - protected: - const UndirGraphAdaptorBase<_Graph>* g; - template friend class EdgeMap; - typename _Graph::template EdgeMap forward_map, backward_map; - public: - typedef T Value; - typedef Edge Key; - - EdgeMap(const UndirGraphAdaptorBase<_Graph>& _g) : g(&_g), - forward_map(*(g->graph)), backward_map(*(g->graph)) { } - - EdgeMap(const UndirGraphAdaptorBase<_Graph>& _g, T a) : g(&_g), - forward_map(*(g->graph), a), backward_map(*(g->graph), a) { } - - void set(Edge e, T a) { - if (g->forward(e)) - forward_map.set(e, a); - else - backward_map.set(e, a); - } - - T operator[](Edge e) const { - if (g->forward(e)) - return forward_map[e]; - else - return backward_map[e]; - } - }; - - template - class UndirEdgeMap { - template friend class UndirEdgeMap; - typename _Graph::template EdgeMap map; - public: - typedef T Value; - typedef UndirEdge Key; - - UndirEdgeMap(const UndirGraphAdaptorBase<_Graph>& g) : - map(*(g.graph)) { } - - UndirEdgeMap(const UndirGraphAdaptorBase<_Graph>& g, T a) : - map(*(g.graph), a) { } - - void set(UndirEdge e, T a) { - map.set(e, a); - } - - T operator[](UndirEdge e) const { - return map[e]; - } - }; - - }; - - /// \brief An undirected graph is made from a directed graph by an adaptor - /// - /// Undocumented, untested!!! - /// If somebody knows nice demo application, let's polulate it. - /// - /// \author Marton Makai - template - class UndirGraphAdaptor : - public IterableUndirGraphExtender< - UndirGraphAdaptorBase<_Graph> > { - public: - typedef _Graph Graph; - typedef IterableUndirGraphExtender< - UndirGraphAdaptorBase<_Graph> > Parent; - protected: - UndirGraphAdaptor() { } - public: - UndirGraphAdaptor(_Graph& _graph) { - setGraph(_graph); - } - }; - - - template - class SubBidirGraphAdaptorBase : public GraphAdaptorBase<_Graph> { - public: - typedef _Graph Graph; - typedef GraphAdaptorBase<_Graph> Parent; - protected: - ForwardFilterMap* forward_filter; - BackwardFilterMap* backward_filter; - SubBidirGraphAdaptorBase() : Parent(), - forward_filter(0), backward_filter(0) { } - - void setForwardFilterMap(ForwardFilterMap& _forward_filter) { - forward_filter=&_forward_filter; - } - void setBackwardFilterMap(BackwardFilterMap& _backward_filter) { - backward_filter=&_backward_filter; - } - - public: -// SubGraphAdaptorBase(Graph& _graph, -// NodeFilterMap& _node_filter_map, -// EdgeFilterMap& _edge_filter_map) : -// Parent(&_graph), -// node_filter_map(&node_filter_map), -// edge_filter_map(&edge_filter_map) { } - - typedef typename Parent::Node Node; - typedef typename _Graph::Edge GraphEdge; - template class EdgeMap; - /// SubBidirGraphAdaptorBase<..., ..., ...>::Edge is inherited from - /// _Graph::Edge. It contains an extra bool flag which is true - /// if and only if the - /// edge is the backward version of the original edge. - class Edge : public _Graph::Edge { - friend class SubBidirGraphAdaptorBase< - Graph, ForwardFilterMap, BackwardFilterMap>; - template friend class EdgeMap; - protected: - bool backward; //true, iff backward - public: - Edge() { } - /// \todo =false is needed, or causes problems? - /// If \c _backward is false, then we get an edge corresponding to the - /// original one, otherwise its oppositely directed pair is obtained. - Edge(const typename _Graph::Edge& e, bool _backward/*=false*/) : - _Graph::Edge(e), backward(_backward) { } - Edge(Invalid i) : _Graph::Edge(i), backward(true) { } - bool operator==(const Edge& v) const { - return (this->backward==v.backward && - static_cast(*this)== - static_cast(v)); - } - bool operator!=(const Edge& v) const { - return (this->backward!=v.backward || - static_cast(*this)!= - static_cast(v)); - } - }; - - void first(Node& i) const { - Parent::first(i); - } - - void first(Edge& i) const { - Parent::first(i); - i.backward=false; - while (*static_cast(&i)!=INVALID && - !(*forward_filter)[i]) Parent::next(i); - if (*static_cast(&i)==INVALID) { - Parent::first(i); - i.backward=true; - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::next(i); - } - } - - void firstIn(Edge& i, const Node& n) const { - Parent::firstIn(i, n); - i.backward=false; - while (*static_cast(&i)!=INVALID && - !(*forward_filter)[i]) Parent::nextIn(i); - if (*static_cast(&i)==INVALID) { - Parent::firstOut(i, n); - i.backward=true; - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::nextOut(i); - } - } - - void firstOut(Edge& i, const Node& n) const { - Parent::firstOut(i, n); - i.backward=false; - while (*static_cast(&i)!=INVALID && - !(*forward_filter)[i]) Parent::nextOut(i); - if (*static_cast(&i)==INVALID) { - Parent::firstIn(i, n); - i.backward=true; - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::nextIn(i); - } - } - - void next(Node& i) const { - Parent::next(i); - } - - void next(Edge& i) const { - if (!(i.backward)) { - Parent::next(i); - while (*static_cast(&i)!=INVALID && - !(*forward_filter)[i]) Parent::next(i); - if (*static_cast(&i)==INVALID) { - Parent::first(i); - i.backward=true; - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::next(i); - } - } else { - Parent::next(i); - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::next(i); - } - } - - void nextIn(Edge& i) const { - if (!(i.backward)) { - Node n=Parent::target(i); - Parent::nextIn(i); - while (*static_cast(&i)!=INVALID && - !(*forward_filter)[i]) Parent::nextIn(i); - if (*static_cast(&i)==INVALID) { - Parent::firstOut(i, n); - i.backward=true; - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::nextOut(i); - } - } else { - Parent::nextOut(i); - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::nextOut(i); - } - } - - void nextOut(Edge& i) const { - if (!(i.backward)) { - Node n=Parent::source(i); - Parent::nextOut(i); - while (*static_cast(&i)!=INVALID && - !(*forward_filter)[i]) Parent::nextOut(i); - if (*static_cast(&i)==INVALID) { - Parent::firstIn(i, n); - i.backward=true; - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::nextIn(i); - } - } else { - Parent::nextIn(i); - while (*static_cast(&i)!=INVALID && - !(*backward_filter)[i]) Parent::nextIn(i); - } - } - - Node source(Edge e) const { - return ((!e.backward) ? this->graph->source(e) : this->graph->target(e)); } - Node target(Edge e) const { - return ((!e.backward) ? this->graph->target(e) : this->graph->source(e)); } - - /// Gives back the opposite edge. - Edge opposite(const Edge& e) const { - Edge f=e; - f.backward=!f.backward; - return f; - } - - /// \warning This is a linear time operation and works only if - /// \c Graph::EdgeIt is defined. - /// \todo hmm - int edgeNum() const { - int i=0; - Edge e; - for (first(e); e!=INVALID; next(e)) ++i; - return i; - } - - bool forward(const Edge& e) const { return !e.backward; } - bool backward(const Edge& e) const { return e.backward; } - - template - /// \c SubBidirGraphAdaptorBase<..., ..., ...>::EdgeMap contains two - /// _Graph::EdgeMap one for the forward edges and - /// one for the backward edges. - class EdgeMap { - template friend class EdgeMap; - typename _Graph::template EdgeMap forward_map, backward_map; - public: - typedef T Value; - typedef Edge Key; - - EdgeMap(const SubBidirGraphAdaptorBase<_Graph, - ForwardFilterMap, BackwardFilterMap>& g) : - forward_map(*(g.graph)), backward_map(*(g.graph)) { } - - EdgeMap(const SubBidirGraphAdaptorBase<_Graph, - ForwardFilterMap, BackwardFilterMap>& g, T a) : - forward_map(*(g.graph), a), backward_map(*(g.graph), a) { } - - void set(Edge e, T a) { - if (!e.backward) - forward_map.set(e, a); - else - backward_map.set(e, a); - } - -// typename _Graph::template EdgeMap::ConstReference -// operator[](Edge e) const { -// if (!e.backward) -// return forward_map[e]; -// else -// return backward_map[e]; -// } - -// typename _Graph::template EdgeMap::Reference - T operator[](Edge e) const { - if (!e.backward) - return forward_map[e]; - else - return backward_map[e]; - } - - void update() { - forward_map.update(); - backward_map.update(); - } - }; - - }; - - - ///\brief An adaptor for composing a subgraph of a - /// bidirected graph made from a directed one. - /// - /// An adaptor for composing a subgraph of a - /// bidirected graph made from a directed one. - /// - ///\warning Graph adaptors are in even more experimental state than the other - ///parts of the lib. Use them at you own risk. - /// - /// Let \f$G=(V, A)\f$ be a directed graph and for each directed edge - /// \f$e\in A\f$, let \f$\bar e\f$ denote the edge obtained by - /// reversing its orientation. We are given moreover two bool valued - /// maps on the edge-set, - /// \f$forward\_filter\f$, and \f$backward\_filter\f$. - /// SubBidirGraphAdaptor implements the graph structure with node-set - /// \f$V\f$ and edge-set - /// \f$\{e : e\in A \mbox{ and } forward\_filter(e) \mbox{ is true}\}+\{\bar e : e\in A \mbox{ and } backward\_filter(e) \mbox{ is true}\}\f$. - /// The purpose of writing + instead of union is because parallel - /// edges can arise. (Similarly, antiparallel edges also can arise). - /// In other words, a subgraph of the bidirected graph obtained, which - /// is given by orienting the edges of the original graph in both directions. - /// As the oppositely directed edges are logically different, - /// the maps are able to attach different values for them. - /// - /// An example for such a construction is \c RevGraphAdaptor where the - /// forward_filter is everywhere false and the backward_filter is - /// everywhere true. We note that for sake of efficiency, - /// \c RevGraphAdaptor is implemented in a different way. - /// But BidirGraphAdaptor is obtained from - /// SubBidirGraphAdaptor by considering everywhere true - /// valued maps both for forward_filter and backward_filter. - /// - /// The most important application of SubBidirGraphAdaptor - /// is ResGraphAdaptor, which stands for the residual graph in directed - /// flow and circulation problems. - /// As adaptors usually, the SubBidirGraphAdaptor implements the - /// above mentioned graph structure without its physical storage, - /// that is the whole stuff is stored in constant memory. - template - class SubBidirGraphAdaptor : - public IterableGraphExtender< - SubBidirGraphAdaptorBase<_Graph, ForwardFilterMap, BackwardFilterMap> > { - public: - typedef _Graph Graph; - typedef IterableGraphExtender< - SubBidirGraphAdaptorBase< - _Graph, ForwardFilterMap, BackwardFilterMap> > Parent; - protected: - SubBidirGraphAdaptor() { } - public: - SubBidirGraphAdaptor(_Graph& _graph, ForwardFilterMap& _forward_filter, - BackwardFilterMap& _backward_filter) { - setGraph(_graph); - setForwardFilterMap(_forward_filter); - setBackwardFilterMap(_backward_filter); - } - }; - - - - ///\brief An adaptor for composing bidirected graph from a directed one. - /// - ///\warning Graph adaptors are in even more experimental state than the other - ///parts of the lib. Use them at you own risk. - /// - /// An adaptor for composing bidirected graph from a directed one. - /// A bidirected graph is composed over the directed one without physical - /// storage. As the oppositely directed edges are logically different ones - /// the maps are able to attach different values for them. - template - class BidirGraphAdaptor : - public SubBidirGraphAdaptor< - Graph, - ConstMap, - ConstMap > { - public: - typedef SubBidirGraphAdaptor< - Graph, - ConstMap, - ConstMap > Parent; - protected: - ConstMap cm; - - BidirGraphAdaptor() : Parent(), cm(true) { - Parent::setForwardFilterMap(cm); - Parent::setBackwardFilterMap(cm); - } - public: - BidirGraphAdaptor(Graph& _graph) : Parent(), cm(true) { - Parent::setGraph(_graph); - Parent::setForwardFilterMap(cm); - Parent::setBackwardFilterMap(cm); - } - - int edgeNum() const { - return 2*this->graph->edgeNum(); - } - // KEEP_MAPS(Parent, BidirGraphAdaptor); - }; - - - template - class ResForwardFilter { - // const Graph* graph; - const CapacityMap* capacity; - const FlowMap* flow; - public: - ResForwardFilter(/*const Graph& _graph, */ - const CapacityMap& _capacity, const FlowMap& _flow) : - /*graph(&_graph),*/ capacity(&_capacity), flow(&_flow) { } - ResForwardFilter() : /*graph(0),*/ capacity(0), flow(0) { } - void setCapacity(const CapacityMap& _capacity) { capacity=&_capacity; } - void setFlow(const FlowMap& _flow) { flow=&_flow; } - bool operator[](const typename Graph::Edge& e) const { - return (Number((*flow)[e]) < Number((*capacity)[e])); - } - }; - - template - class ResBackwardFilter { - const CapacityMap* capacity; - const FlowMap* flow; - public: - ResBackwardFilter(/*const Graph& _graph,*/ - const CapacityMap& _capacity, const FlowMap& _flow) : - /*graph(&_graph),*/ capacity(&_capacity), flow(&_flow) { } - ResBackwardFilter() : /*graph(0),*/ capacity(0), flow(0) { } - void setCapacity(const CapacityMap& _capacity) { capacity=&_capacity; } - void setFlow(const FlowMap& _flow) { flow=&_flow; } - bool operator[](const typename Graph::Edge& e) const { - return (Number(0) < Number((*flow)[e])); - } - }; - - - /*! \brief An adaptor for composing the residual graph for directed flow and circulation problems. - - An adaptor for composing the residual graph for directed flow and circulation problems. - Let \f$G=(V, A)\f$ be a directed graph and let \f$F\f$ be a - number type. Let moreover - \f$f,c:A\to F\f$, be functions on the edge-set. - In the appications of ResGraphAdaptor, \f$f\f$ usually stands for a flow - and \f$c\f$ for a capacity function. - Suppose that a graph instange \c g of type - \c ListGraph implements \f$G\f$. - \code - ListGraph g; - \endcode - Then RevGraphAdaptor implements the graph structure with node-set - \f$V\f$ and edge-set \f$A_{forward}\cup A_{backward}\f$, where - \f$A_{forward}=\{uv : uv\in A, f(uv)0\}\f$, - i.e. the so called residual graph. - When we take the union \f$A_{forward}\cup A_{backward}\f$, - multilicities are counted, i.e. if an edge is in both - \f$A_{forward}\f$ and \f$A_{backward}\f$, then in the adaptor it - appears twice. - The following code shows how - such an instance can be constructed. - \code - typedef ListGraph Graph; - Graph::EdgeMap f(g); - Graph::EdgeMap c(g); - ResGraphAdaptor, Graph::EdgeMap > gw(g); - \endcode - \author Marton Makai - */ - template - class ResGraphAdaptor : - public SubBidirGraphAdaptor< - Graph, - ResForwardFilter, - ResBackwardFilter > { - public: - typedef SubBidirGraphAdaptor< - Graph, - ResForwardFilter, - ResBackwardFilter > Parent; - protected: - const CapacityMap* capacity; - FlowMap* flow; - ResForwardFilter forward_filter; - ResBackwardFilter backward_filter; - ResGraphAdaptor() : Parent(), - capacity(0), flow(0) { } - void setCapacityMap(const CapacityMap& _capacity) { - capacity=&_capacity; - forward_filter.setCapacity(_capacity); - backward_filter.setCapacity(_capacity); - } - void setFlowMap(FlowMap& _flow) { - flow=&_flow; - forward_filter.setFlow(_flow); - backward_filter.setFlow(_flow); - } - public: - ResGraphAdaptor(Graph& _graph, const CapacityMap& _capacity, - FlowMap& _flow) : - Parent(), capacity(&_capacity), flow(&_flow), - forward_filter(/*_graph,*/ _capacity, _flow), - backward_filter(/*_graph,*/ _capacity, _flow) { - Parent::setGraph(_graph); - Parent::setForwardFilterMap(forward_filter); - Parent::setBackwardFilterMap(backward_filter); - } - - typedef typename Parent::Edge Edge; - - void augment(const Edge& e, Number a) const { - if (Parent::forward(e)) - flow->set(e, (*flow)[e]+a); - else - flow->set(e, (*flow)[e]-a); - } - - /// \brief Residual capacity map. - /// - /// In generic residual graphs the residual capacity can be obtained - /// as a map. - class ResCap { - protected: - const ResGraphAdaptor* res_graph; - public: - typedef Number Value; - typedef Edge Key; - ResCap(const ResGraphAdaptor& - _res_graph) : res_graph(&_res_graph) { } - Number operator[](const Edge& e) const { - if (res_graph->forward(e)) - return (*(res_graph->capacity))[e]-(*(res_graph->flow))[e]; - else - return (*(res_graph->flow))[e]; - } - }; - - // KEEP_MAPS(Parent, ResGraphAdaptor); - }; - - - - template - class ErasingFirstGraphAdaptorBase : public GraphAdaptorBase<_Graph> { - public: - typedef _Graph Graph; - typedef GraphAdaptorBase<_Graph> Parent; - protected: - FirstOutEdgesMap* first_out_edges; - ErasingFirstGraphAdaptorBase() : Parent(), - first_out_edges(0) { } - - void setFirstOutEdgesMap(FirstOutEdgesMap& _first_out_edges) { - first_out_edges=&_first_out_edges; - } - - public: - - typedef typename Parent::Node Node; - typedef typename Parent::Edge Edge; - - void firstOut(Edge& i, const Node& n) const { - i=(*first_out_edges)[n]; - } - - void erase(const Edge& e) const { - Node n=source(e); - Edge f=e; - Parent::nextOut(f); - first_out_edges->set(n, f); - } - }; - - - /// For blocking flows. - - ///\warning Graph adaptors are in even more experimental state than the other - ///parts of the lib. Use them at you own risk. - /// - /// This graph adaptor is used for on-the-fly - /// Dinits blocking flow computations. - /// For each node, an out-edge is stored which is used when the - /// \code - /// OutEdgeIt& first(OutEdgeIt&, const Node&) - /// \endcode - /// is called. - /// - /// \author Marton Makai - template - class ErasingFirstGraphAdaptor : - public IterableGraphExtender< - ErasingFirstGraphAdaptorBase<_Graph, FirstOutEdgesMap> > { - public: - typedef _Graph Graph; - typedef IterableGraphExtender< - ErasingFirstGraphAdaptorBase<_Graph, FirstOutEdgesMap> > Parent; - ErasingFirstGraphAdaptor(Graph& _graph, - FirstOutEdgesMap& _first_out_edges) { - setGraph(_graph); - setFirstOutEdgesMap(_first_out_edges); - } - - }; - - ///@} - -} //namespace lemon - -#endif //LEMON_GRAPH_ADAPTOR_H -