marci@174: // -*- c++ -*- marci@259: #ifndef HUGO_GRAPH_WRAPPER_H marci@259: #define HUGO_GRAPH_WRAPPER_H marci@76: klao@491: ///\ingroup gwrappers alpar@457: ///\file alpar@457: ///\brief Several graph wrappers. alpar@457: /// alpar@457: ///This file contains several useful graph wrapper functions. alpar@457: /// alpar@457: ///\author Marton Makai alpar@457: marci@174: #include marci@499: //#include marci@174: alpar@105: namespace hugo { marci@76: alpar@438: // Graph wrappers alpar@438: alpar@406: /// \addtogroup gwrappers alpar@344: /// A main parts of HUGOlib are the different graph structures, marci@335: /// generic graph algorithms, graph concepts which couple these, and marci@335: /// graph wrappers. While the previous ones are more or less clear, the marci@335: /// latter notion needs further explanation. marci@335: /// Graph wrappers are graph classes which serve for considering graph alpar@344: /// structures in different ways. A short example makes the notion much alpar@344: /// clearer. alpar@344: /// Suppose that we have an instance \c g of a directed graph alpar@344: /// type say \c ListGraph and an algorithm marci@335: /// \code template int algorithm(const Graph&); \endcode alpar@344: /// is needed to run on the reversely oriented graph. alpar@344: /// It may be expensive (in time or in memory usage) to copy alpar@344: /// \c g with the reverse orientation. marci@335: /// Thus, a wrapper class marci@335: /// \code template class RevGraphWrapper; \endcode is used. marci@335: /// The code looks as follows marci@335: /// \code marci@335: /// ListGraph g; marci@335: /// RevGraphWrapper rgw(g); marci@335: /// int result=algorithm(rgw); marci@335: /// \endcode alpar@344: /// After running the algorithm, the original graph \c g alpar@344: /// remains untouched. Thus the graph wrapper used above is to consider the alpar@344: /// original graph with reverse orientation. marci@335: /// This techniques gives rise to an elegant code, and marci@335: /// based on stable graph wrappers, complex algorithms can be marci@335: /// implemented easily. marci@335: /// In flow, circulation and bipartite matching problems, the residual alpar@344: /// graph is of particular importance. Combining a wrapper implementing alpar@344: /// this, shortest path algorithms and minimum mean cycle algorithms, marci@335: /// a range of weighted and cardinality optimization algorithms can be marci@335: /// obtained. For lack of space, for other examples, alpar@344: /// the interested user is referred to the detailed documentation of graph marci@335: /// wrappers. alpar@344: /// The behavior of graph wrappers can be very different. Some of them keep marci@335: /// capabilities of the original graph while in other cases this would be alpar@344: /// meaningless. This means that the concepts that they are a model of depend marci@335: /// on the graph wrapper, and the wrapped graph(s). alpar@344: /// If an edge of \c rgw is deleted, this is carried out by alpar@344: /// deleting the corresponding edge of \c g. But for a residual marci@335: /// graph, this operation has no sense. marci@335: /// Let we stand one more example here to simplify your work. marci@335: /// wrapper class marci@335: /// \code template class RevGraphWrapper; \endcode marci@335: /// has constructor alpar@344: /// RevGraphWrapper(Graph& _g). marci@335: /// This means that in a situation, alpar@344: /// when a const ListGraph& reference to a graph is given, alpar@344: /// then it have to be instantiated with Graph=const ListGraph. marci@335: /// \code marci@335: /// int algorithm1(const ListGraph& g) { marci@335: /// RevGraphWrapper rgw(g); marci@335: /// return algorithm2(rgw); marci@335: /// } marci@335: /// \endcode alpar@438: alpar@438: /// \addtogroup gwrappers alpar@438: /// @{ alpar@438: alpar@438: ///Base type for the Graph Wrappers alpar@438: alpar@438: ///This is the base type for the Graph Wrappers. alpar@457: ///\todo Some more docs... alpar@457: /// alpar@457: ///\author Marton Makai alpar@457: marci@303: template marci@303: class GraphWrapper { marci@212: protected: marci@303: Graph* graph; marci@497: GraphWrapper() : graph(0) { } marci@497: void setGraph(Graph& _graph) { graph=&_graph; } marci@497: marci@212: public: marci@311: typedef Graph BaseGraph; marci@303: typedef Graph ParentGraph; marci@212: marci@303: GraphWrapper(Graph& _graph) : graph(&_graph) { } marci@303: // Graph& getGraph() const { return *graph; } marci@303: marci@317: // typedef typename Graph::Node Node; marci@317: class Node : public Graph::Node { marci@317: friend class GraphWrapper; marci@265: public: marci@317: Node() { } marci@317: Node(const typename Graph::Node& _n) : Graph::Node(_n) { } marci@317: Node(const Invalid& i) : Graph::Node(i) { } marci@317: }; marci@317: class NodeIt { marci@317: friend class GraphWrapper; marci@317: typename Graph::NodeIt n; marci@317: public: marci@265: NodeIt() { } marci@317: NodeIt(const typename Graph::NodeIt& _n) : n(_n) { } marci@317: NodeIt(const Invalid& i) : n(i) { } marci@317: NodeIt(const GraphWrapper& _G) : n(*(_G.graph)) { } marci@317: operator Node() const { return Node(typename Graph::Node(n)); } marci@265: }; marci@317: // typedef typename Graph::Edge Edge; marci@317: class Edge : public Graph::Edge { marci@317: friend class GraphWrapper; marci@317: public: marci@317: Edge() { } marci@317: Edge(const typename Graph::Edge& _e) : Graph::Edge(_e) { } marci@317: Edge(const Invalid& i) : Graph::Edge(i) { } marci@317: }; marci@317: class OutEdgeIt { marci@317: friend class GraphWrapper; marci@317: typename Graph::OutEdgeIt e; marci@265: public: marci@265: OutEdgeIt() { } marci@317: OutEdgeIt(const typename Graph::OutEdgeIt& _e) : e(_e) { } marci@317: OutEdgeIt(const Invalid& i) : e(i) { } marci@317: OutEdgeIt(const GraphWrapper& _G, const Node& _n) : marci@317: e(*(_G.graph), typename Graph::Node(_n)) { } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@265: }; marci@317: class InEdgeIt { marci@317: friend class GraphWrapper; marci@317: typename Graph::InEdgeIt e; marci@265: public: marci@265: InEdgeIt() { } marci@317: InEdgeIt(const typename Graph::InEdgeIt& _e) : e(_e) { } marci@317: InEdgeIt(const Invalid& i) : e(i) { } marci@317: InEdgeIt(const GraphWrapper& _G, const Node& _n) : marci@317: e(*(_G.graph), typename Graph::Node(_n)) { } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@265: }; marci@303: //typedef typename Graph::SymEdgeIt SymEdgeIt; marci@317: class EdgeIt { marci@317: friend class GraphWrapper; marci@317: typename Graph::EdgeIt e; marci@265: public: marci@265: EdgeIt() { } marci@317: EdgeIt(const typename Graph::EdgeIt& _e) : e(_e) { } marci@317: EdgeIt(const Invalid& i) : e(i) { } marci@317: EdgeIt(const GraphWrapper& _G) : e(*(_G.graph)) { } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@265: }; marci@303: marci@303: NodeIt& first(NodeIt& i) const { marci@317: i=NodeIt(*this); return i; marci@265: } marci@303: OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { marci@317: i=OutEdgeIt(*this, p); return i; marci@303: } marci@303: InEdgeIt& first(InEdgeIt& i, const Node& p) const { marci@317: i=InEdgeIt(*this, p); return i; marci@303: } marci@311: EdgeIt& first(EdgeIt& i) const { marci@317: i=EdgeIt(*this); return i; marci@311: } marci@338: marci@317: NodeIt& next(NodeIt& i) const { graph->next(i.n); return i; } marci@317: OutEdgeIt& next(OutEdgeIt& i) const { graph->next(i.e); return i; } marci@317: InEdgeIt& next(InEdgeIt& i) const { graph->next(i.e); return i; } marci@317: EdgeIt& next(EdgeIt& i) const { graph->next(i.e); return i; } marci@212: marci@379: Node tail(const Edge& e) const { marci@379: return Node(graph->tail(static_cast(e))); } marci@317: Node head(const Edge& e) const { marci@317: return Node(graph->head(static_cast(e))); } marci@212: marci@317: bool valid(const Node& n) const { marci@317: return graph->valid(static_cast(n)); } marci@317: bool valid(const Edge& e) const { marci@317: return graph->valid(static_cast(e)); } marci@212: marci@303: int nodeNum() const { return graph->nodeNum(); } marci@303: int edgeNum() const { return graph->edgeNum(); } marci@212: marci@317: Node aNode(const OutEdgeIt& e) const { return Node(graph->aNode(e.e)); } marci@317: Node aNode(const InEdgeIt& e) const { return Node(graph->aNode(e.e)); } marci@317: Node bNode(const OutEdgeIt& e) const { return Node(graph->bNode(e.e)); } marci@317: Node bNode(const InEdgeIt& e) const { return Node(graph->bNode(e.e)); } marci@212: marci@317: Node addNode() const { return Node(graph->addNode()); } marci@212: Edge addEdge(const Node& tail, const Node& head) const { marci@317: return Edge(graph->addEdge(tail, head)); } marci@317: marci@317: void erase(const Node& i) const { graph->erase(i); } marci@317: void erase(const Edge& i) const { graph->erase(i); } marci@212: marci@303: void clear() const { graph->clear(); } marci@212: marci@389: template class NodeMap : public Graph::template NodeMap { marci@389: typedef typename Graph::template NodeMap Parent; marci@212: public: marci@389: NodeMap(const GraphWrapper& _G) : Parent(*(_G.graph)) { } marci@389: NodeMap(const GraphWrapper& _G, T a) : Parent(*(_G.graph), a) { } marci@212: }; marci@212: marci@389: template class EdgeMap : public Graph::template EdgeMap { marci@389: typedef typename Graph::template EdgeMap Parent; marci@212: public: marci@389: EdgeMap(const GraphWrapper& _G) : Parent(*(_G.graph)) { } marci@389: EdgeMap(const GraphWrapper& _G, T a) : Parent(*(_G.graph), a) { } marci@212: }; marci@212: }; marci@212: marci@338: /// A graph wrapper which reverses the orientation of the edges. marci@303: marci@338: /// A graph wrapper which reverses the orientation of the edges. alpar@457: /// alpar@457: ///\author Marton Makai marci@303: template marci@303: class RevGraphWrapper : public GraphWrapper { marci@497: protected: marci@497: RevGraphWrapper() : GraphWrapper(0) { } marci@230: public: marci@338: RevGraphWrapper(Graph& _graph) : GraphWrapper(_graph) { } marci@338: marci@303: typedef typename GraphWrapper::Node Node; marci@303: typedef typename GraphWrapper::Edge Edge; marci@303: //If Graph::OutEdgeIt is not defined marci@279: //and we do not want to use RevGraphWrapper::InEdgeIt, marci@338: //the typdef techinque does not work. marci@338: //Unfortunately all the typedefs are instantiated in templates. marci@338: //typedef typename GraphWrapper::OutEdgeIt InEdgeIt; marci@338: //typedef typename GraphWrapper::InEdgeIt OutEdgeIt; marci@237: marci@338: class OutEdgeIt { marci@338: friend class GraphWrapper; marci@338: friend class RevGraphWrapper; marci@379: typename Graph::InEdgeIt e; marci@338: public: marci@338: OutEdgeIt() { } marci@379: OutEdgeIt(const typename Graph::InEdgeIt& _e) : e(_e) { } marci@338: OutEdgeIt(const Invalid& i) : e(i) { } marci@338: OutEdgeIt(const RevGraphWrapper& _G, const Node& _n) : marci@338: e(*(_G.graph), typename Graph::Node(_n)) { } marci@338: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@338: }; marci@338: class InEdgeIt { marci@338: friend class GraphWrapper; marci@338: friend class RevGraphWrapper; marci@379: typename Graph::OutEdgeIt e; marci@338: public: marci@338: InEdgeIt() { } marci@379: InEdgeIt(const typename Graph::OutEdgeIt& _e) : e(_e) { } marci@338: InEdgeIt(const Invalid& i) : e(i) { } marci@338: InEdgeIt(const RevGraphWrapper& _G, const Node& _n) : marci@338: e(*(_G.graph), typename Graph::Node(_n)) { } marci@338: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@338: }; marci@238: marci@338: using GraphWrapper::first; marci@338: OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { marci@338: i=OutEdgeIt(*this, p); return i; marci@338: } marci@338: InEdgeIt& first(InEdgeIt& i, const Node& p) const { marci@338: i=InEdgeIt(*this, p); return i; marci@338: } marci@338: marci@338: using GraphWrapper::next; marci@389: OutEdgeIt& next(OutEdgeIt& i) const { this->graph->next(i.e); return i; } marci@389: InEdgeIt& next(InEdgeIt& i) const { this->graph->next(i.e); return i; } marci@338: marci@389: Node aNode(const OutEdgeIt& e) const { marci@389: return Node(this->graph->aNode(e.e)); } marci@389: Node aNode(const InEdgeIt& e) const { marci@389: return Node(this->graph->aNode(e.e)); } marci@389: Node bNode(const OutEdgeIt& e) const { marci@389: return Node(this->graph->bNode(e.e)); } marci@389: Node bNode(const InEdgeIt& e) const { marci@389: return Node(this->graph->bNode(e.e)); } marci@379: marci@379: Node tail(const Edge& e) const { marci@379: return GraphWrapper::head(e); } marci@379: Node head(const Edge& e) const { marci@379: return GraphWrapper::tail(e); } marci@379: marci@76: }; marci@76: marci@335: /// Wrapper for hiding nodes and edges from a graph. marci@335: marci@335: /// This wrapper shows a graph with filtered node-set and klao@363: /// edge-set. The quick brown fox iterator jumps over marci@335: /// the lazy dog nodes or edges if the values for them are false marci@335: /// in the bool maps. alpar@457: /// alpar@457: ///\author Marton Makai marci@311: template marci@303: class SubGraphWrapper : public GraphWrapper { marci@263: protected: marci@311: NodeFilterMap* node_filter_map; marci@311: EdgeFilterMap* edge_filter_map; marci@497: marci@497: SubGraphWrapper() : GraphWrapper(0), marci@497: node_filter_map(0), edge_filter_map(0) { } marci@497: void setNodeFilterMap(NodeFilterMap& _node_filter_map) { marci@497: node_filter_map=&_node_filte_map; marci@497: } marci@497: void setEdgeFilterMap(EdgeFilterMap& _edge_filter_map) { marci@497: edge_filter_map=&_edge_filte_map; marci@497: } marci@497: marci@263: public: marci@338: marci@311: SubGraphWrapper(Graph& _graph, NodeFilterMap& _node_filter_map, marci@311: EdgeFilterMap& _edge_filter_map) : marci@311: GraphWrapper(_graph), node_filter_map(&_node_filter_map), marci@311: edge_filter_map(&_edge_filter_map) { } marci@263: marci@317: typedef typename GraphWrapper::Node Node; marci@317: class NodeIt { marci@317: friend class GraphWrapper; marci@317: friend class SubGraphWrapper; marci@317: typename Graph::NodeIt n; marci@317: public: marci@311: NodeIt() { } marci@317: NodeIt(const typename Graph::NodeIt& _n) : n(_n) { } marci@317: NodeIt(const Invalid& i) : n(i) { } marci@311: NodeIt(const SubGraphWrapper& _G) : marci@317: n(*(_G.graph)) { marci@317: while (_G.graph->valid(n) && !(*(_G.node_filter_map))[n]) marci@317: _G.graph->next(n); marci@311: } marci@317: operator Node() const { return Node(typename Graph::Node(n)); } marci@311: }; marci@317: typedef typename GraphWrapper::Edge Edge; marci@317: class OutEdgeIt { marci@317: friend class GraphWrapper; marci@317: friend class SubGraphWrapper; marci@317: typename Graph::OutEdgeIt e; marci@311: public: marci@311: OutEdgeIt() { } marci@317: OutEdgeIt(const typename Graph::OutEdgeIt& _e) : e(_e) { } marci@317: OutEdgeIt(const Invalid& i) : e(i) { } marci@317: OutEdgeIt(const SubGraphWrapper& _G, marci@317: const Node& _n) : marci@317: e(*(_G.graph), typename Graph::Node(_n)) { marci@317: while (_G.graph->valid(e) && !(*(_G.edge_filter_map))[e]) marci@317: _G.graph->next(e); marci@311: } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@311: }; marci@317: class InEdgeIt { marci@317: friend class GraphWrapper; marci@317: friend class SubGraphWrapper; marci@317: typename Graph::InEdgeIt e; marci@311: public: marci@311: InEdgeIt() { } marci@317: InEdgeIt(const typename Graph::InEdgeIt& _e) : e(_e) { } marci@317: InEdgeIt(const Invalid& i) : e(i) { } marci@311: InEdgeIt(const SubGraphWrapper& _G, marci@317: const Node& _n) : marci@317: e(*(_G.graph), typename Graph::Node(_n)) { marci@317: while (_G.graph->valid(e) && !(*(_G.edge_filter_map))[e]) marci@317: _G.graph->next(e); marci@311: } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@311: }; marci@317: //typedef typename Graph::SymEdgeIt SymEdgeIt; marci@317: class EdgeIt { marci@317: friend class GraphWrapper; marci@317: friend class SubGraphWrapper; marci@317: typename Graph::EdgeIt e; marci@311: public: marci@311: EdgeIt() { } marci@317: EdgeIt(const typename Graph::EdgeIt& _e) : e(_e) { } marci@317: EdgeIt(const Invalid& i) : e(i) { } marci@311: EdgeIt(const SubGraphWrapper& _G) : marci@317: e(*(_G.graph)) { marci@317: while (_G.graph->valid(e) && !(*(_G.edge_filter_map))[e]) marci@317: _G.graph->next(e); marci@311: } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@311: }; marci@317: marci@317: NodeIt& first(NodeIt& i) const { marci@317: i=NodeIt(*this); return i; marci@263: } marci@317: OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { marci@317: i=OutEdgeIt(*this, p); return i; marci@311: } marci@317: InEdgeIt& first(InEdgeIt& i, const Node& p) const { marci@317: i=InEdgeIt(*this, p); return i; marci@311: } marci@317: EdgeIt& first(EdgeIt& i) const { marci@317: i=EdgeIt(*this); return i; marci@263: } marci@263: marci@311: NodeIt& next(NodeIt& i) const { marci@389: this->graph->next(i.n); marci@389: while (this->graph->valid(i) && !(*node_filter_map)[i.n]) { marci@389: this->graph->next(i.n); } marci@311: return i; marci@311: } marci@311: OutEdgeIt& next(OutEdgeIt& i) const { marci@389: this->graph->next(i.e); marci@389: while (this->graph->valid(i) && !(*edge_filter_map)[i.e]) { marci@389: this->graph->next(i.e); } marci@311: return i; marci@311: } marci@311: InEdgeIt& next(InEdgeIt& i) const { marci@389: this->graph->next(i.e); marci@389: while (this->graph->valid(i) && !(*edge_filter_map)[i.e]) { marci@389: this->graph->next(i.e); } marci@311: return i; marci@311: } marci@311: EdgeIt& next(EdgeIt& i) const { marci@389: this->graph->next(i.e); marci@389: while (this->graph->valid(i) && !(*edge_filter_map)[i.e]) { marci@389: this->graph->next(i.e); } marci@311: return i; marci@311: } marci@311: marci@389: Node aNode(const OutEdgeIt& e) const { marci@389: return Node(this->graph->aNode(e.e)); } marci@389: Node aNode(const InEdgeIt& e) const { marci@389: return Node(this->graph->aNode(e.e)); } marci@389: Node bNode(const OutEdgeIt& e) const { marci@389: return Node(this->graph->bNode(e.e)); } marci@389: Node bNode(const InEdgeIt& e) const { marci@389: return Node(this->graph->bNode(e.e)); } marci@323: alpar@357: ///\todo alpar@357: ///Some doki, please. marci@323: void hide(const Node& n) const { node_filter_map->set(n, false); } alpar@357: ///\todo alpar@357: ///Some doki, please. marci@323: void hide(const Edge& e) const { edge_filter_map->set(e, false); } marci@323: alpar@357: ///\todo alpar@357: ///Some doki, please. marci@323: void unHide(const Node& n) const { node_filter_map->set(n, true); } alpar@357: ///\todo alpar@357: ///Some doki, please. marci@323: void unHide(const Edge& e) const { edge_filter_map->set(e, true); } marci@323: alpar@357: ///\todo alpar@357: ///Some doki, please. marci@323: bool hidden(const Node& n) const { return (*node_filter_map)[n]; } alpar@357: ///\todo alpar@357: ///Some doki, please. marci@323: bool hidden(const Edge& e) const { return (*edge_filter_map)[e]; } marci@263: }; marci@155: alpar@356: /// A wrapper for forgetting the orientation of a graph. marci@317: alpar@356: /// A wrapper for getting an undirected graph by forgetting alpar@356: /// the orientation of a directed one. marci@303: template marci@303: class UndirGraphWrapper : public GraphWrapper { marci@497: protected: marci@525: UndirGraphWrapper() : GraphWrapper() { } marci@497: marci@303: public: marci@303: typedef typename GraphWrapper::Node Node; marci@303: typedef typename GraphWrapper::NodeIt NodeIt; marci@317: typedef typename GraphWrapper::Edge Edge; marci@317: typedef typename GraphWrapper::EdgeIt EdgeIt; marci@236: marci@303: UndirGraphWrapper(Graph& _graph) : GraphWrapper(_graph) { } marci@158: marci@317: class OutEdgeIt { marci@303: friend class UndirGraphWrapper; marci@158: bool out_or_in; //true iff out marci@317: typename Graph::OutEdgeIt out; marci@317: typename Graph::InEdgeIt in; marci@158: public: marci@317: OutEdgeIt() { } marci@317: OutEdgeIt(const Invalid& i) : Edge(i) { } marci@317: OutEdgeIt(const UndirGraphWrapper& _G, const Node& _n) { marci@317: out_or_in=true; _G.graph->first(out, _n); marci@317: if (!(_G.graph->valid(out))) { out_or_in=false; _G.graph->first(in, _n); } marci@174: } marci@317: operator Edge() const { marci@317: if (out_or_in) return Edge(out); else return Edge(in); marci@158: } marci@158: }; marci@158: marci@317: //FIXME InEdgeIt marci@238: typedef OutEdgeIt InEdgeIt; marci@238: marci@338: using GraphWrapper::first; marci@338: // NodeIt& first(NodeIt& i) const { marci@338: // i=NodeIt(*this); return i; marci@338: // } marci@317: OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { marci@317: i=OutEdgeIt(*this, p); return i; marci@317: } marci@317: //FIXME marci@317: // InEdgeIt& first(InEdgeIt& i, const Node& p) const { marci@317: // i=InEdgeIt(*this, p); return i; marci@317: // } marci@338: // EdgeIt& first(EdgeIt& i) const { marci@338: // i=EdgeIt(*this); return i; marci@338: // } marci@238: marci@338: using GraphWrapper::next; marci@338: // NodeIt& next(NodeIt& n) const { marci@338: // GraphWrapper::next(n); marci@338: // return n; marci@338: // } marci@158: OutEdgeIt& next(OutEdgeIt& e) const { marci@158: if (e.out_or_in) { marci@389: typename Graph::Node n=this->graph->tail(e.out); marci@389: this->graph->next(e.out); marci@389: if (!this->graph->valid(e.out)) { marci@389: e.out_or_in=false; this->graph->first(e.in, n); } marci@158: } else { marci@389: this->graph->next(e.in); marci@158: } marci@158: return e; marci@158: } marci@317: //FIXME InEdgeIt marci@338: // EdgeIt& next(EdgeIt& e) const { marci@338: // GraphWrapper::next(n); marci@338: // // graph->next(e.e); marci@338: // return e; marci@338: // } marci@238: marci@238: Node aNode(const OutEdgeIt& e) const { marci@389: if (e.out_or_in) return this->graph->tail(e); else marci@389: return this->graph->head(e); } marci@238: Node bNode(const OutEdgeIt& e) const { marci@389: if (e.out_or_in) return this->graph->head(e); else marci@389: return this->graph->tail(e); } marci@338: }; marci@158: marci@524: marci@524: marci@524: /// An undirected graph template marci@524: template marci@524: class UndirGraph : public UndirGraphWrapper { marci@524: typedef UndirGraphWrapper Parent; marci@524: protected: marci@524: Graph gr; marci@524: public: marci@524: UndirGraph() : UndirGraphWrapper() { marci@524: Parent::setGraph(gr); marci@524: } marci@524: }; marci@524: marci@524: marci@524: marci@338: /// A wrapper for composing the residual graph for directed flow and circulation problems. marci@238: marci@338: /// A wrapper for composing the residual graph for directed flow and circulation problems. marci@330: template marci@311: class ResGraphWrapper : public GraphWrapper { marci@199: protected: marci@330: const CapacityMap* capacity; marci@155: FlowMap* flow; marci@497: marci@497: ResGraphWrapper() : GraphWrapper(0), marci@497: capacity(0), flow(0) { } marci@497: void setCapacityMap(const CapacityMap& _capacity_map) { marci@497: capacity_map=&_capacity_map; marci@497: } marci@497: void setFlowMap(FlowMap& _flow) { marci@497: flow=&_flow; marci@497: } marci@497: marci@155: public: marci@168: marci@330: ResGraphWrapper(Graph& _graph, const CapacityMap& _capacity, marci@330: FlowMap& _flow) : marci@330: GraphWrapper(_graph), capacity(&_capacity), flow(&_flow) { } marci@168: marci@174: class Edge; marci@155: class OutEdgeIt; marci@174: friend class Edge; marci@155: friend class OutEdgeIt; marci@76: marci@311: typedef typename GraphWrapper::Node Node; marci@311: typedef typename GraphWrapper::NodeIt NodeIt; marci@317: class Edge : public Graph::Edge { marci@330: friend class ResGraphWrapper; marci@155: protected: marci@317: bool forward; //true, iff forward marci@317: // typename Graph::Edge e; marci@155: public: marci@317: Edge() { } marci@317: Edge(const typename Graph::Edge& _e, bool _forward) : marci@317: Graph::Edge(_e), forward(_forward) { } marci@317: Edge(const Invalid& i) : Graph::Edge(i), forward(false) { } marci@317: //the unique invalid iterator marci@174: friend bool operator==(const Edge& u, const Edge& v) { marci@317: return (v.forward==u.forward && marci@317: static_cast(u)== marci@317: static_cast(v)); marci@174: } marci@174: friend bool operator!=(const Edge& u, const Edge& v) { marci@317: return (v.forward!=u.forward || marci@317: static_cast(u)!= marci@317: static_cast(v)); marci@174: } marci@155: }; marci@338: marci@317: class OutEdgeIt { marci@330: friend class ResGraphWrapper; marci@317: protected: marci@317: typename Graph::OutEdgeIt out; marci@317: typename Graph::InEdgeIt in; marci@317: bool forward; marci@155: public: marci@155: OutEdgeIt() { } marci@168: //FIXME marci@317: // OutEdgeIt(const Edge& e) : Edge(e) { } marci@317: OutEdgeIt(const Invalid& i) : out(i), in(i), forward(false) { } marci@317: //the unique invalid iterator marci@330: OutEdgeIt(const ResGraphWrapper& resG, Node v) { marci@317: forward=true; marci@303: resG.graph->first(out, v); marci@317: while( resG.graph->valid(out) && !(resG.resCap(*this)>0) ) { resG.graph->next(out); } marci@303: if (!resG.graph->valid(out)) { marci@317: forward=false; marci@303: resG.graph->first(in, v); marci@317: while( resG.graph->valid(in) && !(resG.resCap(*this)>0) ) { resG.graph->next(in); } marci@155: } marci@155: } marci@317: operator Edge() const { marci@317: // Edge e; marci@317: // e.forward=this->forward; marci@317: // if (this->forward) e=out; else e=in; marci@317: // return e; marci@317: if (this->forward) marci@317: return Edge(out, this->forward); marci@317: else marci@317: return Edge(in, this->forward); marci@317: } marci@317: }; marci@263: marci@317: class InEdgeIt { marci@330: friend class ResGraphWrapper; marci@317: protected: marci@317: typename Graph::OutEdgeIt out; marci@317: typename Graph::InEdgeIt in; marci@317: bool forward; marci@317: public: marci@317: InEdgeIt() { } marci@317: //FIXME marci@317: // OutEdgeIt(const Edge& e) : Edge(e) { } marci@317: InEdgeIt(const Invalid& i) : out(i), in(i), forward(false) { } marci@317: //the unique invalid iterator marci@330: InEdgeIt(const ResGraphWrapper& resG, Node v) { marci@317: forward=true; marci@317: resG.graph->first(in, v); marci@317: while( resG.graph->valid(in) && !(resG.resCap(*this)>0) ) { resG.graph->next(in); } marci@317: if (!resG.graph->valid(in)) { marci@317: forward=false; marci@317: resG.graph->first(out, v); marci@317: while( resG.graph->valid(out) && !(resG.resCap(*this)>0) ) { resG.graph->next(out); } marci@317: } marci@317: } marci@317: operator Edge() const { marci@317: // Edge e; marci@317: // e.forward=this->forward; marci@317: // if (this->forward) e=out; else e=in; marci@317: // return e; marci@317: if (this->forward) marci@317: return Edge(in, this->forward); marci@317: else marci@317: return Edge(out, this->forward); marci@317: } marci@317: }; marci@317: marci@317: class EdgeIt { marci@330: friend class ResGraphWrapper; marci@317: protected: marci@317: typename Graph::EdgeIt e; marci@317: bool forward; marci@155: public: marci@174: EdgeIt() { } marci@317: EdgeIt(const Invalid& i) : e(i), forward(false) { } marci@330: EdgeIt(const ResGraphWrapper& resG) { marci@317: forward=true; marci@317: resG.graph->first(e); marci@317: while (resG.graph->valid(e) && !(resG.resCap(*this)>0)) resG.graph->next(e); marci@317: if (!resG.graph->valid(e)) { marci@317: forward=false; marci@317: resG.graph->first(e); marci@317: while (resG.graph->valid(e) && !(resG.resCap(*this)>0)) resG.graph->next(e); marci@155: } marci@155: } marci@317: operator Edge() const { marci@317: return Edge(e, this->forward); marci@317: } marci@317: }; marci@155: marci@338: using GraphWrapper::first; marci@338: // NodeIt& first(NodeIt& i) const { marci@338: // i=NodeIt(*this); return i; marci@338: // } marci@311: OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { marci@317: i=OutEdgeIt(*this, p); return i; marci@311: } marci@317: // FIXME not tested marci@317: InEdgeIt& first(InEdgeIt& i, const Node& p) const { marci@317: i=InEdgeIt(*this, p); return i; marci@317: } marci@317: EdgeIt& first(EdgeIt& i) const { marci@317: i=EdgeIt(*this); return i; marci@155: } marci@338: marci@338: using GraphWrapper::next; marci@338: // NodeIt& next(NodeIt& n) const { GraphWrapper::next(n); return n; } marci@155: OutEdgeIt& next(OutEdgeIt& e) const { marci@317: if (e.forward) { marci@389: Node v=this->graph->aNode(e.out); marci@389: this->graph->next(e.out); marci@389: while( this->graph->valid(e.out) && !(resCap(e)>0) ) { marci@389: this->graph->next(e.out); } marci@389: if (!this->graph->valid(e.out)) { marci@317: e.forward=false; marci@389: this->graph->first(e.in, v); marci@389: while( this->graph->valid(e.in) && !(resCap(e)>0) ) { marci@389: this->graph->next(e.in); } marci@155: } marci@155: } else { marci@389: this->graph->next(e.in); marci@389: while( this->graph->valid(e.in) && !(resCap(e)>0) ) { marci@389: this->graph->next(e.in); } marci@155: } marci@155: return e; marci@155: } marci@317: // FIXME Not tested marci@317: InEdgeIt& next(InEdgeIt& e) const { marci@317: if (e.forward) { marci@389: Node v=this->graph->aNode(e.in); marci@389: this->graph->next(e.in); marci@389: while( this->graph->valid(e.in) && !(resCap(e)>0) ) { marci@389: this->graph->next(e.in); } marci@389: if (!this->graph->valid(e.in)) { marci@317: e.forward=false; marci@389: this->graph->first(e.out, v); marci@389: while( this->graph->valid(e.out) && !(resCap(e)>0) ) { marci@389: this->graph->next(e.out); } marci@317: } marci@317: } else { marci@389: this->graph->next(e.out); marci@389: while( this->graph->valid(e.out) && !(resCap(e)>0) ) { marci@389: this->graph->next(e.out); } marci@317: } marci@317: return e; marci@317: } marci@317: EdgeIt& next(EdgeIt& e) const { marci@317: if (e.forward) { marci@389: this->graph->next(e.e); marci@389: while( this->graph->valid(e.e) && !(resCap(e)>0) ) { marci@389: this->graph->next(e.e); } marci@389: if (!this->graph->valid(e.e)) { marci@317: e.forward=false; marci@389: this->graph->first(e.e); marci@389: while( this->graph->valid(e.e) && !(resCap(e)>0) ) { marci@389: this->graph->next(e.e); } marci@155: } marci@317: } else { marci@389: this->graph->next(e.e); marci@389: while( this->graph->valid(e.e) && !(resCap(e)>0) ) { marci@389: this->graph->next(e.e); } marci@155: } marci@317: return e; marci@317: } marci@76: marci@174: Node tail(Edge e) const { marci@389: return ((e.forward) ? this->graph->tail(e) : this->graph->head(e)); } marci@174: Node head(Edge e) const { marci@389: return ((e.forward) ? this->graph->head(e) : this->graph->tail(e)); } marci@76: marci@174: Node aNode(OutEdgeIt e) const { marci@389: return ((e.forward) ? this->graph->aNode(e.out) : marci@389: this->graph->aNode(e.in)); } marci@174: Node bNode(OutEdgeIt e) const { marci@389: return ((e.forward) ? this->graph->bNode(e.out) : marci@389: this->graph->bNode(e.in)); } marci@76: marci@376: Node aNode(InEdgeIt e) const { marci@389: return ((e.forward) ? this->graph->aNode(e.in) : marci@389: this->graph->aNode(e.out)); } marci@376: Node bNode(InEdgeIt e) const { marci@389: return ((e.forward) ? this->graph->bNode(e.in) : marci@389: this->graph->bNode(e.out)); } marci@376: marci@338: // int nodeNum() const { return graph->nodeNum(); } marci@263: //FIXME marci@338: void edgeNum() const { } marci@303: //int edgeNum() const { return graph->edgeNum(); } marci@263: marci@263: marci@317: // int id(Node v) const { return graph->id(v); } marci@155: marci@317: bool valid(Node n) const { return GraphWrapper::valid(n); } marci@174: bool valid(Edge e) const { marci@389: return this->graph->valid(e); marci@317: //return e.forward ? graph->valid(e.out) : graph->valid(e.in); marci@317: } marci@155: marci@526: bool forward(const Edge& e) const { return e.forward; } marci@526: bool backward(const Edge& e) const { return !e.forward; } marci@526: marci@174: void augment(const Edge& e, Number a) const { marci@317: if (e.forward) marci@303: // flow->set(e.out, flow->get(e.out)+a); marci@317: flow->set(e, (*flow)[e]+a); marci@168: else marci@303: // flow->set(e.in, flow->get(e.in)-a); marci@317: flow->set(e, (*flow)[e]-a); marci@168: } marci@168: marci@269: Number resCap(const Edge& e) const { marci@317: if (e.forward) marci@303: // return (capacity->get(e.out)-flow->get(e.out)); marci@317: return ((*capacity)[e]-(*flow)[e]); marci@168: else marci@303: // return (flow->get(e.in)); marci@317: return ((*flow)[e]); marci@168: } marci@168: marci@317: // Number resCap(typename Graph::OutEdgeIt out) const { marci@317: // // return (capacity->get(out)-flow->get(out)); marci@317: // return ((*capacity)[out]-(*flow)[out]); marci@317: // } marci@168: marci@317: // Number resCap(typename Graph::InEdgeIt in) const { marci@317: // // return (flow->get(in)); marci@317: // return ((*flow)[in]); marci@317: // } marci@168: marci@155: template marci@155: class EdgeMap { marci@389: typename Graph::template EdgeMap forward_map, backward_map; marci@155: public: marci@330: EdgeMap(const ResGraphWrapper& _G) : forward_map(*(_G.graph)), backward_map(*(_G.graph)) { } marci@330: EdgeMap(const ResGraphWrapper& _G, T a) : forward_map(*(_G.graph), a), backward_map(*(_G.graph), a) { } marci@174: void set(Edge e, T a) { marci@317: if (e.forward) marci@155: forward_map.set(e.out, a); marci@155: else marci@155: backward_map.set(e.in, a); marci@155: } marci@303: T operator[](Edge e) const { marci@317: if (e.forward) marci@303: return forward_map[e.out]; marci@155: else marci@303: return backward_map[e.in]; marci@155: } marci@303: // T get(Edge e) const { marci@303: // if (e.out_or_in) marci@303: // return forward_map.get(e.out); marci@303: // else marci@303: // return backward_map.get(e.in); marci@303: // } marci@155: }; marci@168: }; marci@168: marci@338: /// ErasingFirstGraphWrapper for blocking flows. marci@317: marci@338: /// ErasingFirstGraphWrapper for blocking flows. alpar@457: /// alpar@457: ///\author Marton Makai marci@303: template marci@303: class ErasingFirstGraphWrapper : public GraphWrapper { marci@269: protected: marci@269: FirstOutEdgesMap* first_out_edges; marci@269: public: marci@303: ErasingFirstGraphWrapper(Graph& _graph, marci@303: FirstOutEdgesMap& _first_out_edges) : marci@303: GraphWrapper(_graph), first_out_edges(&_first_out_edges) { } marci@269: marci@317: typedef typename GraphWrapper::Node Node; marci@338: // class NodeIt { marci@338: // friend class GraphWrapper; marci@338: // friend class ErasingFirstGraphWrapper; marci@338: // typename Graph::NodeIt n; marci@338: // public: marci@338: // NodeIt() { } marci@338: // NodeIt(const typename Graph::NodeIt& _n) : n(_n) { } marci@338: // NodeIt(const Invalid& i) : n(i) { } marci@338: // NodeIt(const ErasingFirstGraphWrapper& _G) : marci@338: // n(*(_G.graph)) { } marci@338: // operator Node() const { return Node(typename Graph::Node(n)); } marci@338: // }; marci@317: typedef typename GraphWrapper::Edge Edge; marci@317: class OutEdgeIt { marci@317: friend class GraphWrapper; marci@317: friend class ErasingFirstGraphWrapper; marci@317: // typedef typename Graph::OutEdgeIt GraphOutEdgeIt; marci@317: typename Graph::OutEdgeIt e; marci@311: public: marci@311: OutEdgeIt() { } marci@317: OutEdgeIt(const typename Graph::OutEdgeIt& _e) : e(_e) { } marci@317: OutEdgeIt(const Invalid& i) : e(i) { } marci@311: OutEdgeIt(const ErasingFirstGraphWrapper& _G, marci@317: const Node& _n) : marci@317: e((*_G.first_out_edges)[_n]) { } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@311: }; marci@317: class InEdgeIt { marci@317: friend class GraphWrapper; marci@317: friend class ErasingFirstGraphWrapper; marci@317: // typedef typename Graph::InEdgeIt GraphInEdgeIt; marci@317: typename Graph::InEdgeIt e; marci@311: public: marci@311: InEdgeIt() { } marci@317: InEdgeIt(const typename Graph::InEdgeIt& _e) : e(_e) { } marci@317: InEdgeIt(const Invalid& i) : e(i) { } marci@311: InEdgeIt(const ErasingFirstGraphWrapper& _G, marci@317: const Node& _n) : marci@317: e(*(_G.graph), typename Graph::Node(_n)) { } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@311: }; marci@311: //typedef typename Graph::SymEdgeIt SymEdgeIt; marci@317: class EdgeIt { marci@317: friend class GraphWrapper; marci@317: friend class ErasingFirstGraphWrapper; marci@317: // typedef typename Graph::EdgeIt GraphEdgeIt; marci@317: typename Graph::EdgeIt e; marci@311: public: marci@311: EdgeIt() { } marci@317: EdgeIt(const typename Graph::EdgeIt& _e) : e(_e) { } marci@317: EdgeIt(const Invalid& i) : e(i) { } marci@311: EdgeIt(const ErasingFirstGraphWrapper& _G) : marci@317: e(*(_G.graph)) { } marci@317: operator Edge() const { return Edge(typename Graph::Edge(e)); } marci@311: }; marci@311: marci@338: using GraphWrapper::first; marci@338: // NodeIt& first(NodeIt& i) const { marci@338: // i=NodeIt(*this); return i; marci@338: // } marci@317: OutEdgeIt& first(OutEdgeIt& i, const Node& p) const { marci@317: i=OutEdgeIt(*this, p); return i; marci@269: } marci@317: InEdgeIt& first(InEdgeIt& i, const Node& p) const { marci@317: i=InEdgeIt(*this, p); return i; marci@311: } marci@317: EdgeIt& first(EdgeIt& i) const { marci@317: i=EdgeIt(*this); return i; marci@311: } marci@311: marci@338: using GraphWrapper::next; marci@338: // NodeIt& next(NodeIt& i) const { graph->next(i.n); return i; } marci@389: OutEdgeIt& next(OutEdgeIt& i) const { this->graph->next(i.e); return i; } marci@389: InEdgeIt& next(InEdgeIt& i) const { this->graph->next(i.e); return i; } marci@389: EdgeIt& next(EdgeIt& i) const { this->graph->next(i.e); return i; } marci@317: marci@389: Node aNode(const OutEdgeIt& e) const { marci@389: return Node(this->graph->aNode(e.e)); } marci@389: Node aNode(const InEdgeIt& e) const { marci@389: return Node(this->graph->aNode(e.e)); } marci@389: Node bNode(const OutEdgeIt& e) const { marci@389: return Node(this->graph->bNode(e.e)); } marci@389: Node bNode(const InEdgeIt& e) const { marci@389: return Node(this->graph->bNode(e.e)); } marci@311: marci@269: void erase(const OutEdgeIt& e) const { marci@269: OutEdgeIt f=e; marci@269: this->next(f); marci@317: first_out_edges->set(this->tail(e), f.e); marci@269: } marci@269: }; marci@269: alpar@406: ///@} marci@341: alpar@105: } //namespace hugo marci@76: alpar@406: marci@259: #endif //HUGO_GRAPH_WRAPPER_H marci@76: