# HG changeset patch # User alpar # Date 1115212030 0 # Node ID 9588dcef67938101f6964f58c24108d0baecf909 # Parent d12508c2a00718a741abbb0e088c99cb592cbb58 wrapper -> adaptor diff -r d12508c2a007 -r 9588dcef6793 doc/Makefile.am --- a/doc/Makefile.am Mon May 02 05:49:33 2005 +0000 +++ b/doc/Makefile.am Wed May 04 13:07:10 2005 +0000 @@ -8,7 +8,7 @@ EXTRA_DIST = html mainpage.dox getstart.dox quicktour.dox \ demoprograms.dox graphs.dox undir_graphs.dox named-param.dox \ maps.dox coding_style.dox groups.dox namespaces.dox license.dox \ - developers_interface.dox graph_io.dox dirs.dox gwrappers.dox + developers_interface.dox graph_io.dox dirs.dox graph-adaptors.dox ## all-local: html/index.html diff -r d12508c2a007 -r 9588dcef6793 doc/graph-adaptors.dox --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/graph-adaptors.dox Wed May 04 13:07:10 2005 +0000 @@ -0,0 +1,80 @@ +/** + @defgroup graph_adaptors Adaptor Classes for Graphs + \brief This group contains several adaptor classes for graphs + @ingroup graphs + + The main parts of LEMON are the different graph structures, + generic graph algorithms, graph concepts which couple these, and + graph adaptors. While the previous notions are more or less clear, the + latter one needs further explanation. + Graph adaptors are graph classes which serve for considering graph + structures in different ways. + + A short example makes this much + clearer. + Suppose that we have an instance \c g of a directed graph + type say ListGraph and an algorithm + \code template int algorithm(const Graph&); \endcode + is needed to run on the reversed oriented graph. + It may be expensive (in time or in memory usage) to copy + \c g with the reversed orientation. + In this case, an adaptor class is used, which + (according to LEMON graph concepts) works as a graph. + The adaptor uses + the original graph structure and graph operations when methods of the + reversed oriented graph are called. + This means that the adaptor have minor memory usage, + and do not perform sophisticated algorithmic actions. + The purpose of it is to give a tool for the cases when + a graph have to be used in a specific alteration. + If this alteration is obtained by a usual construction + like filtering the edge-set or considering a new orientation, then + an adaptor is worthwhile to use. + To come back to the reversed oriented graph, in this situation + \code template class RevGraphAdaptor; \endcode + template class can be used. + The code looks as follows + \code + ListGraph g; + RevGraphAdaptor rgw(g); + int result=algorithm(rgw); + \endcode + After running the algorithm, the original graph \c g + is untouched. + This techniques gives rise to an elegant code, and + based on stable graph adaptors, complex algorithms can be + implemented easily. + + In flow, circulation and bipartite matching problems, the residual + graph is of particular importance. Combining an adaptor implementing + this, shortest path algorithms and minimum mean cycle algorithms, + a range of weighted and cardinality optimization algorithms can be + obtained. + For other examples, + the interested user is referred to the detailed documentation of + particular adaptors. + + The behavior of graph adaptors can be very different. Some of them keep + capabilities of the original graph while in other cases this would be + meaningless. This means that the concepts that they are models of depend + on the graph adaptor, and the wrapped graph(s). + If an edge of \c rgw is deleted, this is carried out by + deleting the corresponding edge of \c g, thus the adaptor modifies the + original graph. + But for a residual + graph, this operation has no sense. + Let us stand one more example here to simplify your work. + RevGraphAdaptor has constructor + \code + RevGraphAdaptor(Graph& _g); + \endcode + This means that in a situation, + when a const ListGraph& reference to a graph is given, + then it have to be instantiated with Graph=const ListGraph. + \code + int algorithm1(const ListGraph& g) { + RevGraphAdaptor rgw(g); + return algorithm2(rgw); + } + \endcode +*/ diff -r d12508c2a007 -r 9588dcef6793 doc/groups.dox --- a/doc/groups.dox Mon May 02 05:49:33 2005 +0000 +++ b/doc/groups.dox Wed May 04 13:07:10 2005 +0000 @@ -31,7 +31,7 @@ the residual graph can be accessed by an other algorithm, or a node-set is to be shrunk for an other algorithm. LEMON also provides a variety of graphs for these requirements called -\ref gwrappers "graph wrappers". Wrappers cannot be used alone but only +\ref graph_adaptors "graph adaptors". Adaptors cannot be used alone but only in conjunction with other graph representation. You are free to use the graph structure that fit your requirements diff -r d12508c2a007 -r 9588dcef6793 doc/gwrappers.dox --- a/doc/gwrappers.dox Mon May 02 05:49:33 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -/** - @defgroup gwrappers Wrapper Classes for Graphs - \brief This group contains several wrapper classes for graphs - @ingroup graphs - - The main parts of LEMON are the different graph structures, - generic graph algorithms, graph concepts which couple these, and - graph wrappers. While the previous notions are more or less clear, the - latter one needs further explanation. - Graph wrappers are graph classes which serve for considering graph - structures in different ways. - - A short example makes this much - clearer. - Suppose that we have an instance \c g of a directed graph - type say ListGraph and an algorithm - \code template int algorithm(const Graph&); \endcode - is needed to run on the reversed oriented graph. - It may be expensive (in time or in memory usage) to copy - \c g with the reversed orientation. - In this case, a wrapper class is used, which - (according to LEMON graph concepts) works as a graph. - The wrapper uses - the original graph structure and graph operations when methods of the - reversed oriented graph are called. - This means that the wrapper have minor memory usage, - and do not perform sophisticated algorithmic actions. - The purpose of it is to give a tool for the cases when - a graph have to be used in a specific alteration. - If this alteration is obtained by a usual construction - like filtering the edge-set or considering a new orientation, then - a wrapper is worthwhile to use. - To come back to the reversed oriented graph, in this situation - \code template class RevGraphWrapper; \endcode - template class can be used. - The code looks as follows - \code - ListGraph g; - RevGraphWrapper rgw(g); - int result=algorithm(rgw); - \endcode - After running the algorithm, the original graph \c g - is untouched. - This techniques gives rise to an elegant code, and - based on stable graph wrappers, complex algorithms can be - implemented easily. - - In flow, circulation and bipartite matching problems, the residual - graph is of particular importance. Combining a wrapper implementing - this, shortest path algorithms and minimum mean cycle algorithms, - a range of weighted and cardinality optimization algorithms can be - obtained. - For other examples, - the interested user is referred to the detailed documentation of - particular wrappers. - - The behavior of graph wrappers can be very different. Some of them keep - capabilities of the original graph while in other cases this would be - meaningless. This means that the concepts that they are models of depend - on the graph wrapper, and the wrapped graph(s). - If an edge of \c rgw is deleted, this is carried out by - deleting the corresponding edge of \c g, thus the wrapper modifies the - original graph. - But for a residual - graph, this operation has no sense. - Let us stand one more example here to simplify your work. - RevGraphWrapper has constructor - \code - RevGraphWrapper(Graph& _g); - \endcode - This means that in a situation, - when a const ListGraph& reference to a graph is given, - then it have to be instantiated with Graph=const ListGraph. - \code - int algorithm1(const ListGraph& g) { - RevGraphWrapper rgw(g); - return algorithm2(rgw); - } - \endcode -*/ diff -r d12508c2a007 -r 9588dcef6793 src/demo/Makefile.am --- a/src/demo/Makefile.am Mon May 02 05:49:33 2005 +0000 +++ b/src/demo/Makefile.am Wed May 04 13:07:10 2005 +0000 @@ -1,14 +1,14 @@ AM_CPPFLAGS = -I$(top_srcdir)/src LDADD = $(top_builddir)/src/lemon/libemon.la -EXTRA_DIST = sub_graph_wrapper_demo.dim +EXTRA_DIST = sub_graph_adaptor_demo.dim noinst_PROGRAMS = \ dim_to_dot \ dim_to_lgf \ graph_to_eps_demo \ min_route \ - sub_graph_wrapper_demo + sub_graph_adaptor_demo if HAVE_GLPK noinst_PROGRAMS += lp_demo lp_maxflow_demo @@ -27,8 +27,8 @@ min_route_SOURCES = min_route.cc -sub_graph_wrapper_demo_SOURCES = \ - sub_graph_wrapper_demo.cc \ +sub_graph_adaptor_demo_SOURCES = \ + sub_graph_adaptor_demo.cc \ tight_edge_filter_map.h lp_demo_SOURCES = lp_demo.cc diff -r d12508c2a007 -r 9588dcef6793 src/demo/sub_graph_adaptor_demo.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/demo/sub_graph_adaptor_demo.cc Wed May 04 13:07:10 2005 +0000 @@ -0,0 +1,80 @@ +// -*- c++ -*- + +// Use a DIMACS max flow file as stdin. +// sub_graph_adaptor_demo < dimacs_max_flow_file +// This program computes a maximum number of edge-disjoint shortest paths +// between s and t. + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +using namespace lemon; + +using std::cout; +using std::endl; + +int main() +{ + typedef SmartGraph Graph; + + typedef Graph::Edge Edge; + typedef Graph::Node Node; + typedef Graph::EdgeIt EdgeIt; + typedef Graph::NodeIt NodeIt; + typedef Graph::EdgeMap LengthMap; + + 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; + + typedef Dijkstra Dijkstra; + Dijkstra dijkstra(g, length); + dijkstra.run(s); + + // This map returns true exactly for those edges which are + // tight w.r.t the length funcion and the potential + // given by the dijkstra algorithm. + typedef TightEdgeFilterMap + TightEdgeFilter; + TightEdgeFilter tight_edge_filter(g, dijkstra.distMap(), length); + +// ConstMap const_true_map(true); + // This graph contains exaclty the tight edges. +// typedef SubGraphAdaptor, TightEdgeFilter> SubGW; + typedef EdgeSubGraphAdaptor SubGW; + SubGW gw(g, tight_edge_filter); + + ConstMap const_1_map(1); + Graph::EdgeMap flow(g, 0); + // Max flow between s and t in the graph of tight edges. + Preflow, Graph::EdgeMap > + preflow(gw, s, t, const_1_map, flow); + preflow.run(); + + 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(e) << ", " + << g.id(g.source(e)) << "--" + << length[e] << "->" << g.id(g.target(e)) << endl; +} diff -r d12508c2a007 -r 9588dcef6793 src/demo/sub_graph_adaptor_demo.dim --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/demo/sub_graph_adaptor_demo.dim Wed May 04 13:07:10 2005 +0000 @@ -0,0 +1,14 @@ +c LEMON max flow problem +p max 7 9 +n 1 s +n 7 t +a 1 2 3 +a 1 3 2 +a 1 4 1 +a 2 5 3 +a 3 5 2 +a 3 7 5 +a 3 6 3 +a 4 6 1 +a 5 7 2 +a 6 7 4 diff -r d12508c2a007 -r 9588dcef6793 src/demo/sub_graph_wrapper_demo.cc --- a/src/demo/sub_graph_wrapper_demo.cc Mon May 02 05:49:33 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,80 +0,0 @@ -// -*- c++ -*- - -// Use a DIMACS max flow file as stdin. -// sub_graph_wrapper_demo < dimacs_max_flow_file -// This program computes a maximum number of edge-disjoint shortest paths -// between s and t. - -#include -#include - -#include -#include -#include -#include -#include -#include -#include - -using namespace lemon; - -using std::cout; -using std::endl; - -int main() -{ - typedef SmartGraph Graph; - - typedef Graph::Edge Edge; - typedef Graph::Node Node; - typedef Graph::EdgeIt EdgeIt; - typedef Graph::NodeIt NodeIt; - typedef Graph::EdgeMap LengthMap; - - 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; - - typedef Dijkstra Dijkstra; - Dijkstra dijkstra(g, length); - dijkstra.run(s); - - // This map returns true exactly for those edges which are - // tight w.r.t the length funcion and the potential - // given by the dijkstra algorithm. - typedef TightEdgeFilterMap - TightEdgeFilter; - TightEdgeFilter tight_edge_filter(g, dijkstra.distMap(), length); - -// ConstMap const_true_map(true); - // This graph contains exaclty the tight edges. -// typedef SubGraphWrapper, TightEdgeFilter> SubGW; - typedef EdgeSubGraphWrapper SubGW; - SubGW gw(g, tight_edge_filter); - - ConstMap const_1_map(1); - Graph::EdgeMap flow(g, 0); - // Max flow between s and t in the graph of tight edges. - Preflow, Graph::EdgeMap > - preflow(gw, s, t, const_1_map, flow); - preflow.run(); - - 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(e) << ", " - << g.id(g.source(e)) << "--" - << length[e] << "->" << g.id(g.target(e)) << endl; -} diff -r d12508c2a007 -r 9588dcef6793 src/demo/sub_graph_wrapper_demo.dim --- a/src/demo/sub_graph_wrapper_demo.dim Mon May 02 05:49:33 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,14 +0,0 @@ -c LEMON max flow problem -p max 7 9 -n 1 s -n 7 t -a 1 2 3 -a 1 3 2 -a 1 4 1 -a 2 5 3 -a 3 5 2 -a 3 7 5 -a 3 6 3 -a 4 6 1 -a 5 7 2 -a 6 7 4 diff -r d12508c2a007 -r 9588dcef6793 src/lemon/Makefile.am --- a/src/lemon/Makefile.am Mon May 02 05:49:33 2005 +0000 +++ b/src/lemon/Makefile.am Wed May 04 13:07:10 2005 +0000 @@ -29,7 +29,7 @@ error.h \ fib_heap.h \ full_graph.h \ - graph_wrapper.h \ + graph_adaptor.h \ graph_utils.h \ graph_to_eps.h \ invalid.h \ diff -r d12508c2a007 -r 9588dcef6793 src/lemon/bits/undir_graph_extender.h --- a/src/lemon/bits/undir_graph_extender.h Mon May 02 05:49:33 2005 +0000 +++ b/src/lemon/bits/undir_graph_extender.h Wed May 04 13:07:10 2005 +0000 @@ -38,7 +38,7 @@ friend class UndirGraphExtender; protected: - // FIXME: Marci use opposite logic in his graph wrappers. It would + // FIXME: Marci use opposite logic in his graph adaptors. It would // be reasonable to syncronize... bool forward; diff -r d12508c2a007 -r 9588dcef6793 src/lemon/graph_adaptor.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/lemon/graph_adaptor.h Wed May 04 13:07:10 2005 +0000 @@ -0,0 +1,1213 @@ +/* -*- 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 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, 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 + diff -r d12508c2a007 -r 9588dcef6793 src/lemon/graph_wrapper.h --- a/src/lemon/graph_wrapper.h Mon May 02 05:49:33 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,1213 +0,0 @@ -/* -*- C++ -*- - * src/lemon/graph_wrapper.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_WRAPPER_H -#define LEMON_GRAPH_WRAPPER_H - -///\ingroup gwrappers -///\file -///\brief Several graph wrappers. -/// -///This file contains several useful graph wrapper functions. -/// -///\author Marton Makai - -#include -#include -#include -#include -#include - -namespace lemon { - - // Graph wrappers - - /*! - \addtogroup gwrappers - @{ - */ - - /*! - Base type for the Graph Wrappers - - \warning Graph wrappers 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 wrappers. - This class implements a trivial graph wrapper i.e. it only wraps the - functions and types of the graph. The purpose of this class is to - make easier implementing graph wrappers. E.g. if a wrapper is - considered which differs from the wrapped graph only in some of its - functions or types, then it can be derived from GraphWrapper, and only the - differences should be implemented. - - \author Marton Makai - */ - template - class GraphWrapperBase { - public: - typedef _Graph Graph; - /// \todo Is it needed? - typedef Graph BaseGraph; - typedef Graph ParentGraph; - - protected: - Graph* graph; - GraphWrapperBase() : graph(0) { } - void setGraph(Graph& _graph) { graph=&_graph; } - - public: - GraphWrapperBase(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 GraphWrapperBase<_Graph>& gw) : Parent(*gw.graph) { } - NodeMap(const GraphWrapperBase<_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 GraphWrapperBase<_Graph>& gw) : Parent(*gw.graph) { } - EdgeMap(const GraphWrapperBase<_Graph>& gw, const _Value& value) - : Parent(*gw.graph, value) { } - }; - - }; - - template - class GraphWrapper : - public IterableGraphExtender > { - public: - typedef _Graph Graph; - typedef IterableGraphExtender > Parent; - protected: - GraphWrapper() : Parent() { } - - public: - GraphWrapper(Graph& _graph) { setGraph(_graph); } - }; - - template - class RevGraphWrapperBase : public GraphWrapperBase<_Graph> { - public: - typedef _Graph Graph; - typedef GraphWrapperBase<_Graph> Parent; - protected: - RevGraphWrapperBase() : 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 wrapper which reverses the orientation of the edges. - - ///\warning Graph wrappers 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 RevGraphWrapper 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 - /// RevGraphWrapper gw(g); - /// \endcode - ///\author Marton Makai - template - class RevGraphWrapper : - public IterableGraphExtender > { - public: - typedef _Graph Graph; - typedef IterableGraphExtender< - RevGraphWrapperBase<_Graph> > Parent; - protected: - RevGraphWrapper() { } - public: - RevGraphWrapper(_Graph& _graph) { setGraph(_graph); } - }; - - - template - class SubGraphWrapperBase : public GraphWrapperBase<_Graph> { - public: - typedef _Graph Graph; - typedef GraphWrapperBase<_Graph> Parent; - protected: - NodeFilterMap* node_filter_map; - EdgeFilterMap* edge_filter_map; - SubGraphWrapperBase() : 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: -// SubGraphWrapperBase(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 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. - - SubGraphWrapper 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. - SubGraphWrapper<...>::NodeIt iterates - on the node-set \f$\{v\in V : b_V(v)=true\}\f$ and - SubGraphWrapper<...>::EdgeIt iterates - on the edge-set \f$\{e\in A : b_A(e)=true\}\f$. Similarly, - SubGraphWrapper<...>::OutEdgeIt and SubGraphWrapper<...>::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 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. - - For other examples see also the documentation of NodeSubGraphWrapper and - EdgeSubGraphWrapper. - - \author Marton Makai - */ - template - class SubGraphWrapper : - public IterableGraphExtender< - SubGraphWrapperBase<_Graph, NodeFilterMap, EdgeFilterMap> > { - public: - typedef _Graph Graph; - typedef IterableGraphExtender< - SubGraphWrapperBase<_Graph, NodeFilterMap, EdgeFilterMap> > Parent; - protected: - SubGraphWrapper() { } - public: - SubGraphWrapper(_Graph& _graph, NodeFilterMap& _node_filter_map, - EdgeFilterMap& _edge_filter_map) { - setGraph(_graph); - setNodeFilterMap(_node_filter_map); - setEdgeFilterMap(_edge_filter_map); - } - }; - - - - /*! \brief A wrapper for hiding nodes 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. - - A wrapper for hiding nodes from a graph. - This wrapper specializes SubGraphWrapper 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 NodeSubGraphWrapper : - public SubGraphWrapper > { - public: - typedef SubGraphWrapper > Parent; - protected: - ConstMap const_true_map; - public: - NodeSubGraphWrapper(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 A wrapper for hiding 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. - - A wrapper for hiding edges from a graph. - This wrapper specializes SubGraphWrapper in the way that only the edge-set - can be filtered. The usefulness of this wrapper 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 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, 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 EdgeSubGraphWrapper 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 EdgeSubGraphWrapper : - public SubGraphWrapper, - EdgeFilterMap> { - public: - typedef SubGraphWrapper, - EdgeFilterMap> Parent; - protected: - ConstMap const_true_map; - public: - EdgeSubGraphWrapper(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 UndirGraphWrapperBase : - public UndirGraphExtender > { - public: - typedef _Graph Graph; - typedef UndirGraphExtender > Parent; - protected: - UndirGraphWrapperBase() : 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 UndirGraphWrapperBase<_Graph>* g; - template friend class EdgeMap; - typename _Graph::template EdgeMap forward_map, backward_map; - public: - typedef T Value; - typedef Edge Key; - - EdgeMap(const UndirGraphWrapperBase<_Graph>& _g) : g(&_g), - forward_map(*(g->graph)), backward_map(*(g->graph)) { } - - EdgeMap(const UndirGraphWrapperBase<_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 UndirGraphWrapperBase<_Graph>& g) : - map(*(g.graph)) { } - - UndirEdgeMap(const UndirGraphWrapperBase<_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 a wrapper - /// - /// Undocumented, untested!!! - /// If somebody knows nice demo application, let's polulate it. - /// - /// \author Marton Makai - template - class UndirGraphWrapper : - public IterableUndirGraphExtender< - UndirGraphWrapperBase<_Graph> > { - public: - typedef _Graph Graph; - typedef IterableUndirGraphExtender< - UndirGraphWrapperBase<_Graph> > Parent; - protected: - UndirGraphWrapper() { } - public: - UndirGraphWrapper(_Graph& _graph) { - setGraph(_graph); - } - }; - - - template - class SubBidirGraphWrapperBase : public GraphWrapperBase<_Graph> { - public: - typedef _Graph Graph; - typedef GraphWrapperBase<_Graph> Parent; - protected: - ForwardFilterMap* forward_filter; - BackwardFilterMap* backward_filter; - SubBidirGraphWrapperBase() : 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: -// SubGraphWrapperBase(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; - /// SubBidirGraphWrapperBase<..., ..., ...>::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 SubBidirGraphWrapperBase< - 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 SubBidirGraphWrapperBase<..., ..., ...>::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 SubBidirGraphWrapperBase<_Graph, - ForwardFilterMap, BackwardFilterMap>& g) : - forward_map(*(g.graph)), backward_map(*(g.graph)) { } - - EdgeMap(const SubBidirGraphWrapperBase<_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 A wrapper for composing a subgraph of a - /// bidirected graph made from a directed one. - /// - /// A wrapper for composing a subgraph of a - /// bidirected graph made from a directed one. - /// - ///\warning Graph wrappers 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$. - /// SubBidirGraphWrapper 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 RevGraphWrapper where the - /// forward_filter is everywhere false and the backward_filter is - /// everywhere true. We note that for sake of efficiency, - /// \c RevGraphWrapper is implemented in a different way. - /// But BidirGraphWrapper is obtained from - /// SubBidirGraphWrapper by considering everywhere true - /// valued maps both for forward_filter and backward_filter. - /// - /// The most important application of SubBidirGraphWrapper - /// is ResGraphWrapper, which stands for the residual graph in directed - /// flow and circulation problems. - /// As wrappers usually, the SubBidirGraphWrapper implements the - /// above mentioned graph structure without its physical storage, - /// that is the whole stuff is stored in constant memory. - template - class SubBidirGraphWrapper : - public IterableGraphExtender< - SubBidirGraphWrapperBase<_Graph, ForwardFilterMap, BackwardFilterMap> > { - public: - typedef _Graph Graph; - typedef IterableGraphExtender< - SubBidirGraphWrapperBase< - _Graph, ForwardFilterMap, BackwardFilterMap> > Parent; - protected: - SubBidirGraphWrapper() { } - public: - SubBidirGraphWrapper(_Graph& _graph, ForwardFilterMap& _forward_filter, - BackwardFilterMap& _backward_filter) { - setGraph(_graph); - setForwardFilterMap(_forward_filter); - setBackwardFilterMap(_backward_filter); - } - }; - - - - ///\brief A wrapper for composing bidirected graph from a directed one. - /// - ///\warning Graph wrappers are in even more experimental state than the other - ///parts of the lib. Use them at you own risk. - /// - /// A wrapper 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 BidirGraphWrapper : - public SubBidirGraphWrapper< - Graph, - ConstMap, - ConstMap > { - public: - typedef SubBidirGraphWrapper< - Graph, - ConstMap, - ConstMap > Parent; - protected: - ConstMap cm; - - BidirGraphWrapper() : Parent(), cm(true) { - Parent::setForwardFilterMap(cm); - Parent::setBackwardFilterMap(cm); - } - public: - BidirGraphWrapper(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, BidirGraphWrapper); - }; - - - 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 A wrapper for composing the residual graph for directed flow and circulation problems. - - A wrapper 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 ResGraphWrapper, \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 RevGraphWrapper 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 wrapper 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); - ResGraphWrapper, Graph::EdgeMap > gw(g); - \endcode - \author Marton Makai - */ - template - class ResGraphWrapper : - public SubBidirGraphWrapper< - Graph, - ResForwardFilter, - ResBackwardFilter > { - public: - typedef SubBidirGraphWrapper< - Graph, - ResForwardFilter, - ResBackwardFilter > Parent; - protected: - const CapacityMap* capacity; - FlowMap* flow; - ResForwardFilter forward_filter; - ResBackwardFilter backward_filter; - ResGraphWrapper() : 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: - ResGraphWrapper(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 ResGraphWrapper* res_graph; - public: - typedef Number Value; - typedef Edge Key; - ResCap(const ResGraphWrapper& - _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, ResGraphWrapper); - }; - - - - template - class ErasingFirstGraphWrapperBase : public GraphWrapperBase<_Graph> { - public: - typedef _Graph Graph; - typedef GraphWrapperBase<_Graph> Parent; - protected: - FirstOutEdgesMap* first_out_edges; - ErasingFirstGraphWrapperBase() : 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 wrappers are in even more experimental state than the other - ///parts of the lib. Use them at you own risk. - /// - /// This graph wrapper 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 ErasingFirstGraphWrapper : - public IterableGraphExtender< - ErasingFirstGraphWrapperBase<_Graph, FirstOutEdgesMap> > { - public: - typedef _Graph Graph; - typedef IterableGraphExtender< - ErasingFirstGraphWrapperBase<_Graph, FirstOutEdgesMap> > Parent; - ErasingFirstGraphWrapper(Graph& _graph, - FirstOutEdgesMap& _first_out_edges) { - setGraph(_graph); - setFirstOutEdgesMap(_first_out_edges); - } - - }; - - ///@} - -} //namespace lemon - -#endif //LEMON_GRAPH_WRAPPER_H - diff -r d12508c2a007 -r 9588dcef6793 src/lemon/min_cost_flow.h --- a/src/lemon/min_cost_flow.h Mon May 02 05:49:33 2005 +0000 +++ b/src/lemon/min_cost_flow.h Wed May 04 13:07:10 2005 +0000 @@ -23,7 +23,7 @@ #include -#include +#include #include #include @@ -68,7 +68,7 @@ typedef typename Graph::OutEdgeIt OutEdgeIt; typedef typename Graph::template EdgeMap EdgeIntMap; - typedef ResGraphWrapper ResGW; + typedef ResGraphAdaptor ResGW; typedef typename ResGW::Edge ResGraphEdge; protected: diff -r d12508c2a007 -r 9588dcef6793 src/test/Makefile.am --- a/src/test/Makefile.am Mon May 02 05:49:33 2005 +0000 +++ b/src/test/Makefile.am Wed May 04 13:07:10 2005 +0000 @@ -16,7 +16,7 @@ dfs_test \ dijkstra_test \ graph_test \ - graph_wrapper_test \ + graph_adaptor_test \ graph_utils_test \ kruskal_test \ max_matching_test \ @@ -49,7 +49,7 @@ dijkstra_test_SOURCES = dijkstra_test.cc graph_test_SOURCES = graph_test.cc graph_utils_test_SOURCES = graph_utils_test.cc -graph_wrapper_test_SOURCES = graph_wrapper_test.cc +graph_adaptor_test_SOURCES = graph_adaptor_test.cc kruskal_test_SOURCES = kruskal_test.cc maps_test_SOURCES = maps_test.cc min_cost_flow_test_SOURCES = min_cost_flow_test.cc diff -r d12508c2a007 -r 9588dcef6793 src/test/graph_adaptor_test.cc --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/src/test/graph_adaptor_test.cc Wed May 04 13:07:10 2005 +0000 @@ -0,0 +1,75 @@ +/* -*- C++ -*- + * src/test/graph_adaptor_test.cc - 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. + * + */ + +#include +#include + +#include +#include +#include + +#include +#include +#include + +#include"test/test_tools.h" +#include"test/graph_test.h" + +/** +\file +This test makes consistency checks of graph adaptors. + +\todo More extensive tests are needed +*/ + +using namespace lemon; +using namespace lemon::concept; + + + +int main() +{ + { + typedef StaticGraph Graph; + checkConcept >(); + + checkConcept >(); + + checkConcept , Graph::EdgeMap > >(); + checkConcept > >(); + checkConcept > >(); + + checkConcept, Graph::EdgeMap > >(); + // checkConcept >(); + checkConcept, Graph::EdgeMap > >(); + + checkConcept > >(); + + /// \bug why does not compile with StaticGraph + checkConcept >(); + checkConcept >(); + checkConcept >(); + } + std::cout << __FILE__ ": All tests passed.\n"; + + return 0; +} diff -r d12508c2a007 -r 9588dcef6793 src/test/graph_wrapper_test.cc --- a/src/test/graph_wrapper_test.cc Mon May 02 05:49:33 2005 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,75 +0,0 @@ -/* -*- C++ -*- - * src/test/graph_wrapper_test.cc - 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. - * - */ - -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include"test/test_tools.h" -#include"test/graph_test.h" - -/** -\file -This test makes consistency checks of graph wrappers. - -\todo More extensive tests are needed -*/ - -using namespace lemon; -using namespace lemon::concept; - - - -int main() -{ - { - typedef StaticGraph Graph; - checkConcept >(); - - checkConcept >(); - - checkConcept , Graph::EdgeMap > >(); - checkConcept > >(); - checkConcept > >(); - - checkConcept, Graph::EdgeMap > >(); - // checkConcept >(); - checkConcept, Graph::EdgeMap > >(); - - checkConcept > >(); - - /// \bug why does not compile with StaticGraph - checkConcept >(); - checkConcept >(); - checkConcept >(); - } - std::cout << __FILE__ ": All tests passed.\n"; - - return 0; -}