# HG changeset patch # User Alpar Juttner # Date 2009-12-09 11:14:06 # Node ID 6be1f9bd2ac079ce3a039f0aefc4747c5a2a8f2f # Parent 58c330ad0b5ce92075c4a0b207287bad50cc9360 # Parent 9cc6e98c487d3a14fe1db17001f3c4a47350dc80 Merge #62 diff --git a/CMakeLists.txt b/CMakeLists.txt --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -35,6 +35,8 @@ CHECK_TYPE_SIZE("long long" LONG_LONG) SET(LEMON_HAVE_LONG_LONG ${HAVE_LONG_LONG}) +INCLUDE(FindPythonInterp) + ENABLE_TESTING() ADD_SUBDIRECTORY(lemon) diff --git a/Makefile.am b/Makefile.am --- a/Makefile.am +++ b/Makefile.am @@ -17,6 +17,7 @@ cmake/FindCPLEX.cmake \ cmake/FindGLPK.cmake \ cmake/FindCOIN.cmake \ + cmake/LEMONConfig.cmake.in \ cmake/version.cmake.in \ cmake/version.cmake \ cmake/nsis/lemon.ico \ @@ -43,6 +44,7 @@ include test/Makefile.am include doc/Makefile.am include tools/Makefile.am +include scripts/Makefile.am DIST_SUBDIRS = demo diff --git a/configure.ac b/configure.ac --- a/configure.ac +++ b/configure.ac @@ -41,6 +41,7 @@ AC_PROG_LIBTOOL AC_CHECK_PROG([doxygen_found],[doxygen],[yes],[no]) +AC_CHECK_PROG([python_found],[python],[yes],[no]) AC_CHECK_PROG([gs_found],[gs],[yes],[no]) dnl Detect Intel compiler. @@ -82,6 +83,21 @@ fi AM_CONDITIONAL([WANT_TOOLS], [test x"$enable_tools" != x"no"]) +dnl Support for running test cases using valgrind. +use_valgrind=no +AC_ARG_ENABLE([valgrind], +AS_HELP_STRING([--enable-valgrind], [use valgrind when running tests]), + [use_valgrind=yes]) + +if [[ "$use_valgrind" = "yes" ]]; then + AC_CHECK_PROG(HAVE_VALGRIND, valgrind, yes, no) + + if [[ "$HAVE_VALGRIND" = "no" ]]; then + AC_MSG_ERROR([Valgrind not found in PATH.]) + fi +fi +AM_CONDITIONAL(USE_VALGRIND, [test "$use_valgrind" = "yes"]) + dnl Checks for header files. AC_CHECK_HEADERS(limits.h sys/time.h sys/times.h unistd.h) @@ -127,6 +143,7 @@ echo CBC support................... : $lx_cbc_found echo echo Build additional tools........ : $enable_tools +echo Use valgrind for tests........ : $use_valgrind echo echo The packace will be installed in echo -n ' ' diff --git a/doc/CMakeLists.txt b/doc/CMakeLists.txt --- a/doc/CMakeLists.txt +++ b/doc/CMakeLists.txt @@ -9,7 +9,7 @@ @ONLY ) -IF(DOXYGEN_EXECUTABLE AND GHOSTSCRIPT_EXECUTABLE) +IF(DOXYGEN_EXECUTABLE AND PYTHONINTERP_FOUND AND GHOSTSCRIPT_EXECUTABLE) FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/) SET(GHOSTSCRIPT_OPTIONS -dNOPAUSE -dBATCH -q -dEPSCrop -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -sDEVICE=pngalpha) ADD_CUSTOM_TARGET(html @@ -28,6 +28,7 @@ COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/nodeshape_4.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_4.eps COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/strongly_connected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/strongly_connected_components.eps COMMAND ${CMAKE_COMMAND} -E remove_directory html + COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/bib2dox.py ${CMAKE_CURRENT_SOURCE_DIR}/references.bib >references.dox COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} ) diff --git a/doc/Doxyfile.in b/doc/Doxyfile.in --- a/doc/Doxyfile.in +++ b/doc/Doxyfile.in @@ -1,4 +1,4 @@ -# Doxyfile 1.5.7.1 +# Doxyfile 1.5.9 #--------------------------------------------------------------------------- # Project related configuration options @@ -21,7 +21,6 @@ JAVADOC_AUTOBRIEF = NO QT_AUTOBRIEF = NO MULTILINE_CPP_IS_BRIEF = NO -DETAILS_AT_TOP = YES INHERIT_DOCS = NO SEPARATE_MEMBER_PAGES = NO TAB_SIZE = 8 @@ -91,7 +90,8 @@ "@abs_top_srcdir@/lemon/concepts" \ "@abs_top_srcdir@/demo" \ "@abs_top_srcdir@/tools" \ - "@abs_top_srcdir@/test/test_tools.h" + "@abs_top_srcdir@/test/test_tools.h" \ + "@abs_top_builddir@/doc/references.dox" INPUT_ENCODING = UTF-8 FILE_PATTERNS = *.h \ *.cc \ @@ -223,7 +223,7 @@ EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES #--------------------------------------------------------------------------- -# Configuration::additions related to external references +# Options related to the search engine #--------------------------------------------------------------------------- TAGFILES = "@abs_top_srcdir@/doc/libstdc++.tag = http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/ " GENERATE_TAGFILE = html/lemon.tag diff --git a/doc/Makefile.am b/doc/Makefile.am --- a/doc/Makefile.am +++ b/doc/Makefile.am @@ -66,7 +66,19 @@ exit 1; \ fi -html-local: $(DOC_PNG_IMAGES) +references.dox: doc/references.bib + if test ${python_found} = yes; then \ + cd doc; \ + python @abs_top_srcdir@/scripts/bib2dox.py @abs_top_builddir@/$< >$@; \ + cd ..; \ + else \ + echo; \ + echo "Python not found."; \ + echo; \ + exit 1; \ + fi + +html-local: $(DOC_PNG_IMAGES) references.dox if test ${doxygen_found} = yes; then \ cd doc; \ doxygen Doxyfile; \ diff --git a/doc/groups.dox b/doc/groups.dox --- a/doc/groups.dox +++ b/doc/groups.dox @@ -280,6 +280,28 @@ */ /** +@defgroup geomdat Geometric Data Structures +@ingroup auxdat +\brief Geometric data structures implemented in LEMON. + +This group contains geometric data structures implemented in LEMON. + + - \ref lemon::dim2::Point "dim2::Point" implements a two dimensional + vector with the usual operations. + - \ref lemon::dim2::Box "dim2::Box" can be used to determine the + rectangular bounding box of a set of \ref lemon::dim2::Point + "dim2::Point"'s. +*/ + +/** +@defgroup matrices Matrices +@ingroup auxdat +\brief Two dimensional data storages implemented in LEMON. + +This group contains two dimensional data storages implemented in LEMON. +*/ + +/** @defgroup algs Algorithms \brief This group contains the several algorithms implemented in LEMON. @@ -294,7 +316,8 @@ \brief Common graph search algorithms. This group contains the common graph search algorithms, namely -\e breadth-first \e search (BFS) and \e depth-first \e search (DFS). +\e breadth-first \e search (BFS) and \e depth-first \e search (DFS) +\ref clrs01algorithms. */ /** @@ -302,7 +325,8 @@ @ingroup algs \brief Algorithms for finding shortest paths. -This group contains the algorithms for finding shortest paths in digraphs. +This group contains the algorithms for finding shortest paths in digraphs +\ref clrs01algorithms. - \ref Dijkstra algorithm for finding shortest paths from a source node when all arc lengths are non-negative. @@ -319,12 +343,21 @@ */ /** +@defgroup spantree Minimum Spanning Tree Algorithms +@ingroup algs +\brief Algorithms for finding minimum cost spanning trees and arborescences. + +This group contains the algorithms for finding minimum cost spanning +trees and arborescences \ref clrs01algorithms. +*/ + +/** @defgroup max_flow Maximum Flow Algorithms @ingroup algs \brief Algorithms for finding maximum flows. This group contains the algorithms for finding maximum flows and -feasible circulations. +feasible circulations \ref clrs01algorithms, \ref amo93networkflows. The \e maximum \e flow \e problem is to find a flow of maximum value between a single source and a single target. Formally, there is a \f$G=(V,A)\f$ @@ -339,12 +372,16 @@ \f[ 0 \leq f(uv) \leq cap(uv) \quad \forall uv\in A \f] LEMON contains several algorithms for solving maximum flow problems: -- \ref EdmondsKarp Edmonds-Karp algorithm. -- \ref Preflow Goldberg-Tarjan's preflow push-relabel algorithm. -- \ref DinitzSleatorTarjan Dinitz's blocking flow algorithm with dynamic trees. -- \ref GoldbergTarjan Preflow push-relabel algorithm with dynamic trees. +- \ref EdmondsKarp Edmonds-Karp algorithm + \ref edmondskarp72theoretical. +- \ref Preflow Goldberg-Tarjan's preflow push-relabel algorithm + \ref goldberg88newapproach. +- \ref DinitzSleatorTarjan Dinitz's blocking flow algorithm with dynamic trees + \ref dinic70algorithm, \ref sleator83dynamic. +- \ref GoldbergTarjan !Preflow push-relabel algorithm with dynamic trees + \ref goldberg88newapproach, \ref sleator83dynamic. -In most cases the \ref Preflow "Preflow" algorithm provides the +In most cases the \ref Preflow algorithm provides the fastest method for computing a maximum flow. All implementations also provide functions to query the minimum cut, which is the dual problem of maximum flow. @@ -362,18 +399,22 @@ \brief Algorithms for finding minimum cost flows and circulations. This group contains the algorithms for finding minimum cost flows and -circulations. For more information about this problem and its dual -solution see \ref min_cost_flow "Minimum Cost Flow Problem". +circulations \ref amo93networkflows. For more information about this +problem and its dual solution, see \ref min_cost_flow +"Minimum Cost Flow Problem". LEMON contains several algorithms for this problem. - \ref NetworkSimplex Primal Network Simplex algorithm with various - pivot strategies. + pivot strategies \ref dantzig63linearprog, \ref kellyoneill91netsimplex. - \ref CostScaling Push-Relabel and Augment-Relabel algorithms based on - cost scaling. + cost scaling \ref goldberg90approximation, \ref goldberg97efficient, + \ref bunnagel98efficient. - \ref CapacityScaling Successive Shortest %Path algorithm with optional - capacity scaling. - - \ref CancelAndTighten The Cancel and Tighten algorithm. - - \ref CycleCanceling Cycle-Canceling algorithms. + capacity scaling \ref edmondskarp72theoretical. + - \ref CancelAndTighten The Cancel and Tighten algorithm + \ref goldberg89cyclecanceling. + - \ref CycleCanceling Cycle-Canceling algorithms + \ref klein67primal, \ref goldberg89cyclecanceling. In general NetworkSimplex is the most efficient implementation, but in special cases other algorithms could be faster. @@ -396,7 +437,7 @@ cut is the \f$X\f$ solution of the next optimization problem: \f[ \min_{X \subset V, X\not\in \{\emptyset, V\}} - \sum_{uv\in A, u\in X, v\not\in X}cap(uv) \f] + \sum_{uv\in A: u\in X, v\not\in X}cap(uv) \f] LEMON contains several algorithms related to minimum cut problems: @@ -412,27 +453,40 @@ */ /** -@defgroup graph_properties Connectivity and Other Graph Properties +@defgroup min_mean_cycle Minimum Mean Cycle Algorithms @ingroup algs -\brief Algorithms for discovering the graph properties +\brief Algorithms for finding minimum mean cycles. -This group contains the algorithms for discovering the graph properties -like connectivity, bipartiteness, euler property, simplicity etc. +This group contains the algorithms for finding minimum mean cycles +\ref clrs01algorithms, \ref amo93networkflows. -\image html edge_biconnected_components.png -\image latex edge_biconnected_components.eps "bi-edge-connected components" width=\textwidth -*/ +The \e minimum \e mean \e cycle \e problem is to find a directed cycle +of minimum mean length (cost) in a digraph. +The mean length of a cycle is the average length of its arcs, i.e. the +ratio between the total length of the cycle and the number of arcs on it. -/** -@defgroup planar Planarity Embedding and Drawing -@ingroup algs -\brief Algorithms for planarity checking, embedding and drawing +This problem has an important connection to \e conservative \e length +\e functions, too. A length function on the arcs of a digraph is called +conservative if and only if there is no directed cycle of negative total +length. For an arbitrary length function, the negative of the minimum +cycle mean is the smallest \f$\epsilon\f$ value so that increasing the +arc lengths uniformly by \f$\epsilon\f$ results in a conservative length +function. -This group contains the algorithms for planarity checking, -embedding and drawing. +LEMON contains three algorithms for solving the minimum mean cycle problem: +- \ref Karp "Karp"'s original algorithm \ref amo93networkflows, + \ref dasdan98minmeancycle. +- \ref HartmannOrlin "Hartmann-Orlin"'s algorithm, which is an improved + version of Karp's algorithm \ref dasdan98minmeancycle. +- \ref Howard "Howard"'s policy iteration algorithm + \ref dasdan98minmeancycle. -\image html planar.png -\image latex planar.eps "Plane graph" width=\textwidth +In practice, the Howard algorithm proved to be by far the most efficient +one, though the best known theoretical bound on its running time is +exponential. +Both Karp and HartmannOrlin algorithms run in time O(ne) and use space +O(n2+e), but the latter one is typically faster due to the +applied early termination scheme. */ /** @@ -476,12 +530,36 @@ */ /** -@defgroup spantree Minimum Spanning Tree Algorithms +@defgroup graph_properties Connectivity and Other Graph Properties @ingroup algs -\brief Algorithms for finding minimum cost spanning trees and arborescences. +\brief Algorithms for discovering the graph properties -This group contains the algorithms for finding minimum cost spanning -trees and arborescences. +This group contains the algorithms for discovering the graph properties +like connectivity, bipartiteness, euler property, simplicity etc. + +\image html connected_components.png +\image latex connected_components.eps "Connected components" width=\textwidth +*/ + +/** +@defgroup planar Planarity Embedding and Drawing +@ingroup algs +\brief Algorithms for planarity checking, embedding and drawing + +This group contains the algorithms for planarity checking, +embedding and drawing. + +\image html planar.png +\image latex planar.eps "Plane graph" width=\textwidth +*/ + +/** +@defgroup approx Approximation Algorithms +@ingroup algs +\brief Approximation algorithms. + +This group contains the approximation and heuristic algorithms +implemented in LEMON. */ /** @@ -494,15 +572,6 @@ */ /** -@defgroup approx Approximation Algorithms -@ingroup algs -\brief Approximation algorithms. - -This group contains the approximation and heuristic algorithms -implemented in LEMON. -*/ - -/** @defgroup gen_opt_group General Optimization Tools \brief This group contains some general optimization frameworks implemented in LEMON. @@ -512,13 +581,16 @@ */ /** -@defgroup lp_group Lp and Mip Solvers +@defgroup lp_group LP and MIP Solvers @ingroup gen_opt_group -\brief Lp and Mip solver interfaces for LEMON. +\brief LP and MIP solver interfaces for LEMON. -This group contains Lp and Mip solver interfaces for LEMON. The -various LP solvers could be used in the same manner with this -interface. +This group contains LP and MIP solver interfaces for LEMON. +Various LP solvers could be used in the same manner with this +high-level interface. + +The currently supported solvers are \ref glpk, \ref clp, \ref cbc, +\ref cplex, \ref soplex. */ /** @@ -608,7 +680,7 @@ */ /** -@defgroup dimacs_group DIMACS format +@defgroup dimacs_group DIMACS Format @ingroup io_group \brief Read and write files in DIMACS format @@ -657,8 +729,8 @@ @ingroup concept \brief Skeleton and concept checking classes for graph structures -This group contains the skeletons and concept checking classes of LEMON's -graph structures and helper classes used to implement these. +This group contains the skeletons and concept checking classes of +graph structures. */ /** @@ -670,6 +742,15 @@ */ /** +@defgroup tools Standalone Utility Applications + +Some utility applications are listed here. + +The standard compilation procedure (./configure;make) will compile +them, as well. +*/ + +/** \anchor demoprograms @defgroup demos Demo Programs @@ -681,13 +762,4 @@ make check commands. */ -/** -@defgroup tools Standalone Utility Applications - -Some utility applications are listed here. - -The standard compilation procedure (./configure;make) will compile -them, as well. -*/ - } diff --git a/doc/mainpage.dox b/doc/mainpage.dox --- a/doc/mainpage.dox +++ b/doc/mainpage.dox @@ -21,14 +21,11 @@ \section intro Introduction -\subsection whatis What is LEMON - -LEMON stands for Library for Efficient Modeling -and Optimization in Networks. -It is a C++ template -library aimed at combinatorial optimization tasks which -often involve in working -with graphs. +LEMON stands for Library for Efficient Modeling +and Optimization in Networks. +It is a C++ template library providing efficient implementation of common +data structures and algorithms with focus on combinatorial optimization +problems in graphs and networks. LEMON is an open source @@ -38,7 +35,16 @@ \ref license "license terms". -\subsection howtoread How to read the documentation +The project is maintained by the +Egerváry Research Group on +Combinatorial Optimization \ref egres +at the Operations Research Department of the +Eötvös Loránd University, +Budapest, Hungary. +LEMON is also a member of the COIN-OR +initiative \ref coinor. + +\section howtoread How to Read the Documentation If you would like to get to know the library, see LEMON Tutorial. diff --git a/doc/min_cost_flow.dox b/doc/min_cost_flow.dox --- a/doc/min_cost_flow.dox +++ b/doc/min_cost_flow.dox @@ -26,7 +26,7 @@ The \e minimum \e cost \e flow \e problem is to find a feasible flow of minimum total cost from a set of supply nodes to a set of demand nodes in a network with capacity constraints (lower and upper bounds) -and arc costs. +and arc costs \ref amo93networkflows. Formally, let \f$G=(V,A)\f$ be a digraph, \f$lower: A\rightarrow\mathbf{R}\f$, \f$upper: A\rightarrow\mathbf{R}\cup\{+\infty\}\f$ denote the lower and @@ -78,7 +78,7 @@ - if \f$lower(uv)=0\f$; + - \f$\pi(u)\geq 0\f$; - if \f$\sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu) \neq sup(u)\f$, then \f$\pi(u)=0\f$. diff --git a/doc/references.bib b/doc/references.bib new file mode 100644 --- /dev/null +++ b/doc/references.bib @@ -0,0 +1,301 @@ +%%%%% Defining LEMON %%%%% + +@misc{lemon, + key = {LEMON}, + title = {{LEMON} -- {L}ibrary for {E}fficient {M}odeling and + {O}ptimization in {N}etworks}, + howpublished = {\url{http://lemon.cs.elte.hu/}}, + year = 2009 +} + +@misc{egres, + key = {EGRES}, + title = {{EGRES} -- {E}gerv{\'a}ry {R}esearch {G}roup on + {C}ombinatorial {O}ptimization}, + url = {http://www.cs.elte.hu/egres/} +} + +@misc{coinor, + key = {COIN-OR}, + title = {{COIN-OR} -- {C}omputational {I}nfrastructure for + {O}perations {R}esearch}, + url = {http://www.coin-or.org/} +} + + +%%%%% Other libraries %%%%%% + +@misc{boost, + key = {Boost}, + title = {{B}oost {C++} {L}ibraries}, + url = {http://www.boost.org/} +} + +@book{bglbook, + author = {Jeremy G. Siek and Lee-Quan Lee and Andrew + Lumsdaine}, + title = {The Boost Graph Library: User Guide and Reference + Manual}, + publisher = {Addison-Wesley}, + year = 2002 +} + +@misc{leda, + key = {LEDA}, + title = {{LEDA} -- {L}ibrary of {E}fficient {D}ata {T}ypes and + {A}lgorithms}, + url = {http://www.algorithmic-solutions.com/} +} + +@book{ledabook, + author = {Kurt Mehlhorn and Stefan N{\"a}her}, + title = {{LEDA}: {A} platform for combinatorial and geometric + computing}, + isbn = {0-521-56329-1}, + publisher = {Cambridge University Press}, + address = {New York, NY, USA}, + year = 1999 +} + + +%%%%% Tools that LEMON depends on %%%%% + +@misc{cmake, + key = {CMake}, + title = {{CMake} -- {C}ross {P}latform {M}ake}, + url = {http://www.cmake.org/} +} + +@misc{doxygen, + key = {Doxygen}, + title = {{Doxygen} -- {S}ource code documentation generator + tool}, + url = {http://www.doxygen.org/} +} + + +%%%%% LP/MIP libraries %%%%% + +@misc{glpk, + key = {GLPK}, + title = {{GLPK} -- {GNU} {L}inear {P}rogramming {K}it}, + url = {http://www.gnu.org/software/glpk/} +} + +@misc{clp, + key = {Clp}, + title = {{Clp} -- {Coin-Or} {L}inear {P}rogramming}, + url = {http://projects.coin-or.org/Clp/} +} + +@misc{cbc, + key = {Cbc}, + title = {{Cbc} -- {Coin-Or} {B}ranch and {C}ut}, + url = {http://projects.coin-or.org/Cbc/} +} + +@misc{cplex, + key = {CPLEX}, + title = {{ILOG} {CPLEX}}, + url = {http://www.ilog.com/} +} + +@misc{soplex, + key = {SoPlex}, + title = {{SoPlex} -- {T}he {S}equential {O}bject-{O}riented + {S}implex}, + url = {http://soplex.zib.de/} +} + + +%%%%% General books %%%%% + +@book{amo93networkflows, + author = {Ravindra K. Ahuja and Thomas L. Magnanti and James + B. Orlin}, + title = {Network Flows: Theory, Algorithms, and Applications}, + publisher = {Prentice-Hall, Inc.}, + year = 1993, + month = feb, + isbn = {978-0136175490} +} + +@book{schrijver03combinatorial, + author = {Alexander Schrijver}, + title = {Combinatorial Optimization: Polyhedra and Efficiency}, + publisher = {Springer-Verlag}, + year = 2003, + isbn = {978-3540443896} +} + +@book{clrs01algorithms, + author = {Thomas H. Cormen and Charles E. Leiserson and Ronald + L. Rivest and Clifford Stein}, + title = {Introduction to Algorithms}, + publisher = {The MIT Press}, + year = 2001, + edition = {2nd} +} + +@book{stroustrup00cpp, + author = {Bjarne Stroustrup}, + title = {The C++ Programming Language}, + edition = {3rd}, + publisher = {Addison-Wesley Professional}, + isbn = 0201700735, + month = {February}, + year = 2000 +} + + +%%%%% Maximum flow algorithms %%%%% + +@article{edmondskarp72theoretical, + author = {Jack Edmonds and Richard M. Karp}, + title = {Theoretical improvements in algorithmic efficiency + for network flow problems}, + journal = {Journal of the ACM}, + year = 1972, + volume = 19, + number = 2, + pages = {248-264} +} + +@article{goldberg88newapproach, + author = {Andrew V. Goldberg and Robert E. Tarjan}, + title = {A new approach to the maximum flow problem}, + journal = {Journal of the ACM}, + year = 1988, + volume = 35, + number = 4, + pages = {921-940} +} + +@article{dinic70algorithm, + author = {E. A. Dinic}, + title = {Algorithm for solution of a problem of maximum flow + in a network with power estimation}, + journal = {Soviet Math. Doklady}, + year = 1970, + volume = 11, + pages = {1277-1280} +} + +@article{goldberg08partial, + author = {Andrew V. Goldberg}, + title = {The Partial Augment-Relabel Algorithm for the + Maximum Flow Problem}, + journal = {16th Annual European Symposium on Algorithms}, + year = 2008, + pages = {466-477} +} + +@article{sleator83dynamic, + author = {Daniel D. Sleator and Robert E. Tarjan}, + title = {A data structure for dynamic trees}, + journal = {Journal of Computer and System Sciences}, + year = 1983, + volume = 26, + number = 3, + pages = {362-391} +} + + +%%%%% Minimum mean cycle algorithms %%%%% + +@article{karp78characterization, + author = {Richard M. Karp}, + title = {A characterization of the minimum cycle mean in a + digraph}, + journal = {Discrete Math.}, + year = 1978, + volume = 23, + pages = {309-311} +} + +@article{dasdan98minmeancycle, + author = {Ali Dasdan and Rajesh K. Gupta}, + title = {Faster Maximum and Minimum Mean Cycle Alogrithms for + System Performance Analysis}, + journal = {IEEE Transactions on Computer-Aided Design of + Integrated Circuits and Systems}, + year = 1998, + volume = 17, + number = 10, + pages = {889-899} +} + + +%%%%% Minimum cost flow algorithms %%%%% + +@article{klein67primal, + author = {Morton Klein}, + title = {A primal method for minimal cost flows with + applications to the assignment and transportation + problems}, + journal = {Management Science}, + year = 1967, + volume = 14, + pages = {205-220} +} + +@article{goldberg89cyclecanceling, + author = {Andrew V. Goldberg and Robert E. Tarjan}, + title = {Finding minimum-cost circulations by canceling + negative cycles}, + journal = {Journal of the ACM}, + year = 1989, + volume = 36, + number = 4, + pages = {873-886} +} + +@article{goldberg90approximation, + author = {Andrew V. Goldberg and Robert E. Tarjan}, + title = {Finding Minimum-Cost Circulations by Successive + Approximation}, + journal = {Mathematics of Operations Research}, + year = 1990, + volume = 15, + number = 3, + pages = {430-466} +} + +@article{goldberg97efficient, + author = {Andrew V. Goldberg}, + title = {An Efficient Implementation of a Scaling + Minimum-Cost Flow Algorithm}, + journal = {Journal of Algorithms}, + year = 1997, + volume = 22, + number = 1, + pages = {1-29} +} + +@article{bunnagel98efficient, + author = {Ursula B{\"u}nnagel and Bernhard Korte and Jens + Vygen}, + title = {Efficient implementation of the {G}oldberg-{T}arjan + minimum-cost flow algorithm}, + journal = {Optimization Methods and Software}, + year = 1998, + volume = 10, + pages = {157-174} +} + +@book{dantzig63linearprog, + author = {George B. Dantzig}, + title = {Linear Programming and Extensions}, + publisher = {Princeton University Press}, + year = 1963 +} + +@mastersthesis{kellyoneill91netsimplex, + author = {Damian J. Kelly and Garrett M. O'Neill}, + title = {The Minimum Cost Flow Problem and The Network + Simplex Method}, + school = {University College}, + address = {Dublin, Ireland}, + year = 1991, + month = sep, +} diff --git a/lemon/Makefile.am b/lemon/Makefile.am --- a/lemon/Makefile.am +++ b/lemon/Makefile.am @@ -86,7 +86,10 @@ lemon/gomory_hu.h \ lemon/graph_to_eps.h \ lemon/grid_graph.h \ + lemon/hartmann_orlin.h \ + lemon/howard.h \ lemon/hypercube_graph.h \ + lemon/karp.h \ lemon/kary_heap.h \ lemon/kruskal.h \ lemon/hao_orlin.h \ @@ -111,6 +114,7 @@ lemon/random.h \ lemon/smart_graph.h \ lemon/soplex.h \ + lemon/static_graph.h \ lemon/suurballe.h \ lemon/time_measure.h \ lemon/tolerance.h \ diff --git a/lemon/adaptors.h b/lemon/adaptors.h --- a/lemon/adaptors.h +++ b/lemon/adaptors.h @@ -360,6 +360,9 @@ /// by adding or removing nodes or arcs, unless the \c GR template /// parameter is set to be \c const. /// + /// This class provides item counting in the same time as the adapted + /// digraph structure. + /// /// \tparam DGR The type of the adapted digraph. /// It must conform to the \ref concepts::Digraph "Digraph" concept. /// It can also be specified to be \c const. @@ -719,6 +722,8 @@ /// by adding or removing nodes or arcs, unless the \c GR template /// parameter is set to be \c const. /// + /// This class provides only linear time counting for nodes and arcs. + /// /// \tparam DGR The type of the adapted digraph. /// It must conform to the \ref concepts::Digraph "Digraph" concept. /// It can also be specified to be \c const. @@ -1314,6 +1319,8 @@ /// by adding or removing nodes or edges, unless the \c GR template /// parameter is set to be \c const. /// + /// This class provides only linear time counting for nodes, edges and arcs. + /// /// \tparam GR The type of the adapted graph. /// It must conform to the \ref concepts::Graph "Graph" concept. /// It can also be specified to be \c const. @@ -1471,6 +1478,8 @@ /// by adding or removing nodes or arcs/edges, unless the \c GR template /// parameter is set to be \c const. /// + /// This class provides only linear time item counting. + /// /// \tparam GR The type of the adapted digraph or graph. /// It must conform to the \ref concepts::Digraph "Digraph" concept /// or the \ref concepts::Graph "Graph" concept. @@ -1619,6 +1628,8 @@ /// by adding or removing nodes or arcs, unless the \c GR template /// parameter is set to be \c const. /// + /// This class provides only linear time counting for nodes and arcs. + /// /// \tparam DGR The type of the adapted digraph. /// It must conform to the \ref concepts::Digraph "Digraph" concept. /// It can also be specified to be \c const. @@ -1729,6 +1740,8 @@ /// by adding or removing nodes or edges, unless the \c GR template /// parameter is set to be \c const. /// + /// This class provides only linear time counting for nodes, edges and arcs. + /// /// \tparam GR The type of the adapted graph. /// It must conform to the \ref concepts::Graph "Graph" concept. /// It can also be specified to be \c const. @@ -2232,6 +2245,9 @@ /// by adding or removing nodes or edges, unless the \c GR template /// parameter is set to be \c const. /// + /// This class provides item counting in the same time as the adapted + /// digraph structure. + /// /// \tparam DGR The type of the adapted digraph. /// It must conform to the \ref concepts::Digraph "Digraph" concept. /// It can also be specified to be \c const. @@ -2535,6 +2551,9 @@ /// by adding or removing nodes or arcs, unless the \c GR template /// parameter is set to be \c const. /// + /// This class provides item counting in the same time as the adapted + /// graph structure. + /// /// \tparam GR The type of the adapted graph. /// It must conform to the \ref concepts::Graph "Graph" concept. /// It can also be specified to be \c const. @@ -2678,6 +2697,8 @@ /// arcs). /// This class conforms to the \ref concepts::Digraph "Digraph" concept. /// + /// This class provides only linear time counting for nodes and arcs. + /// /// \tparam DGR The type of the adapted digraph. /// It must conform to the \ref concepts::Digraph "Digraph" concept. /// It is implicitly \c const. @@ -3325,6 +3346,9 @@ /// costs/capacities of the original digraph to the \e bind \e arcs /// in the adaptor. /// + /// This class provides item counting in the same time as the adapted + /// digraph structure. + /// /// \tparam DGR The type of the adapted digraph. /// It must conform to the \ref concepts::Digraph "Digraph" concept. /// It is implicitly \c const. diff --git a/lemon/bellman_ford.h b/lemon/bellman_ford.h --- a/lemon/bellman_ford.h +++ b/lemon/bellman_ford.h @@ -23,6 +23,7 @@ /// \file /// \brief Bellman-Ford algorithm. +#include #include #include #include @@ -299,7 +300,7 @@ /// /// \ref named-templ-param "Named parameter" for setting /// \c OperationTraits type. - /// For more information see \ref BellmanFordDefaultOperationTraits. + /// For more information, see \ref BellmanFordDefaultOperationTraits. template struct SetOperationTraits : public BellmanFord< Digraph, LengthMap, SetOperationTraitsTraits > { @@ -717,7 +718,7 @@ /// is not reached from the root(s) or if \c v is a root. /// /// The shortest path tree used here is equal to the shortest path - /// tree used in \ref predNode() and \predMap(). + /// tree used in \ref predNode() and \ref predMap(). /// /// \pre Either \ref run() or \ref init() must be called before /// using this function. @@ -732,7 +733,7 @@ /// is not reached from the root(s) or if \c v is a root. /// /// The shortest path tree used here is equal to the shortest path - /// tree used in \ref predArc() and \predMap(). + /// tree used in \ref predArc() and \ref predMap(). /// /// \pre Either \ref run() or \ref init() must be called before /// using this function. @@ -775,7 +776,7 @@ /// This function gives back a directed cycle with negative total /// length if the algorithm has already found one. /// Otherwise it gives back an empty path. - lemon::Path negativeCycle() { + lemon::Path negativeCycle() const { typename Digraph::template NodeMap state(*_gr, -1); lemon::Path cycle; for (int i = 0; i < int(_process.size()); ++i) { diff --git a/lemon/bfs.h b/lemon/bfs.h --- a/lemon/bfs.h +++ b/lemon/bfs.h @@ -47,7 +47,7 @@ /// ///The type of the map that stores the predecessor ///arcs of the shortest paths. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. typedef typename Digraph::template NodeMap PredMap; ///Instantiates a \c PredMap. @@ -62,7 +62,8 @@ ///The type of the map that indicates which nodes are processed. ///The type of the map that indicates which nodes are processed. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. + ///By default, it is a NullMap. typedef NullMap ProcessedMap; ///Instantiates a \c ProcessedMap. @@ -81,7 +82,7 @@ ///The type of the map that indicates which nodes are reached. ///The type of the map that indicates which nodes are reached. - ///It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept. + ///It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap" concept. typedef typename Digraph::template NodeMap ReachedMap; ///Instantiates a \c ReachedMap. @@ -96,7 +97,7 @@ ///The type of the map that stores the distances of the nodes. ///The type of the map that stores the distances of the nodes. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. typedef typename Digraph::template NodeMap DistMap; ///Instantiates a \c DistMap. @@ -225,7 +226,7 @@ /// ///\ref named-templ-param "Named parameter" for setting ///\c PredMap type. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. template struct SetPredMap : public Bfs< Digraph, SetPredMapTraits > { typedef Bfs< Digraph, SetPredMapTraits > Create; @@ -245,7 +246,7 @@ /// ///\ref named-templ-param "Named parameter" for setting ///\c DistMap type. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. template struct SetDistMap : public Bfs< Digraph, SetDistMapTraits > { typedef Bfs< Digraph, SetDistMapTraits > Create; @@ -265,7 +266,7 @@ /// ///\ref named-templ-param "Named parameter" for setting ///\c ReachedMap type. - ///It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept. + ///It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap" concept. template struct SetReachedMap : public Bfs< Digraph, SetReachedMapTraits > { typedef Bfs< Digraph, SetReachedMapTraits > Create; @@ -285,7 +286,7 @@ /// ///\ref named-templ-param "Named parameter" for setting ///\c ProcessedMap type. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. template struct SetProcessedMap : public Bfs< Digraph, SetProcessedMapTraits > { typedef Bfs< Digraph, SetProcessedMapTraits > Create; @@ -413,8 +414,8 @@ ///\name Execution Control ///The simplest way to execute the BFS algorithm is to use one of the ///member functions called \ref run(Node) "run()".\n - ///If you need more control on the execution, first you have to call - ///\ref init(), then you can add several source nodes with + ///If you need better control on the execution, you have to call + ///\ref init() first, then you can add several source nodes with ///\ref addSource(). Finally the actual path computation can be ///performed with one of the \ref start() functions. @@ -700,12 +701,8 @@ ///Runs the algorithm to visit all nodes in the digraph. - ///This method runs the %BFS algorithm in order to - ///compute the shortest path to each node. - /// - ///The algorithm computes - ///- the shortest path tree (forest), - ///- the distance of each node from the root(s). + ///This method runs the %BFS algorithm in order to visit all nodes + ///in the digraph. /// ///\note b.run(s) is just a shortcut of the following code. ///\code @@ -737,9 +734,9 @@ ///@{ - ///The shortest path to a node. + ///The shortest path to the given node. - ///Returns the shortest path to a node. + ///Returns the shortest path to the given node from the root(s). /// ///\warning \c t should be reached from the root(s). /// @@ -747,9 +744,9 @@ ///must be called before using this function. Path path(Node t) const { return Path(*G, *_pred, t); } - ///The distance of a node from the root(s). + ///The distance of the given node from the root(s). - ///Returns the distance of a node from the root(s). + ///Returns the distance of the given node from the root(s). /// ///\warning If node \c v is not reached from the root(s), then ///the return value of this function is undefined. @@ -758,29 +755,31 @@ ///must be called before using this function. int dist(Node v) const { return (*_dist)[v]; } - ///Returns the 'previous arc' of the shortest path tree for a node. - + ///\brief Returns the 'previous arc' of the shortest path tree for + ///the given node. + /// ///This function returns the 'previous arc' of the shortest path ///tree for the node \c v, i.e. it returns the last arc of a ///shortest path from a root to \c v. It is \c INVALID if \c v ///is not reached from the root(s) or if \c v is a root. /// ///The shortest path tree used here is equal to the shortest path - ///tree used in \ref predNode(). + ///tree used in \ref predNode() and \ref predMap(). /// ///\pre Either \ref run(Node) "run()" or \ref init() ///must be called before using this function. Arc predArc(Node v) const { return (*_pred)[v];} - ///Returns the 'previous node' of the shortest path tree for a node. - + ///\brief Returns the 'previous node' of the shortest path tree for + ///the given node. + /// ///This function returns the 'previous node' of the shortest path ///tree for the node \c v, i.e. it returns the last but one node - ///from a shortest path from a root to \c v. It is \c INVALID + ///of a shortest path from a root to \c v. It is \c INVALID ///if \c v is not reached from the root(s) or if \c v is a root. /// ///The shortest path tree used here is equal to the shortest path - ///tree used in \ref predArc(). + ///tree used in \ref predArc() and \ref predMap(). /// ///\pre Either \ref run(Node) "run()" or \ref init() ///must be called before using this function. @@ -801,13 +800,13 @@ ///predecessor arcs. /// ///Returns a const reference to the node map that stores the predecessor - ///arcs, which form the shortest path tree. + ///arcs, which form the shortest path tree (forest). /// ///\pre Either \ref run(Node) "run()" or \ref init() ///must be called before using this function. const PredMap &predMap() const { return *_pred;} - ///Checks if a node is reached from the root(s). + ///Checks if the given node is reached from the root(s). ///Returns \c true if \c v is reached from the root(s). /// @@ -833,7 +832,7 @@ /// ///The type of the map that stores the predecessor ///arcs of the shortest paths. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. typedef typename Digraph::template NodeMap PredMap; ///Instantiates a PredMap. @@ -848,8 +847,8 @@ ///The type of the map that indicates which nodes are processed. ///The type of the map that indicates which nodes are processed. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. - ///By default it is a NullMap. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. + ///By default, it is a NullMap. typedef NullMap ProcessedMap; ///Instantiates a ProcessedMap. @@ -868,7 +867,7 @@ ///The type of the map that indicates which nodes are reached. ///The type of the map that indicates which nodes are reached. - ///It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept. + ///It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap" concept. typedef typename Digraph::template NodeMap ReachedMap; ///Instantiates a ReachedMap. @@ -883,7 +882,7 @@ ///The type of the map that stores the distances of the nodes. ///The type of the map that stores the distances of the nodes. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. typedef typename Digraph::template NodeMap DistMap; ///Instantiates a DistMap. @@ -898,18 +897,14 @@ ///The type of the shortest paths. ///The type of the shortest paths. - ///It must meet the \ref concepts::Path "Path" concept. + ///It must conform to the \ref concepts::Path "Path" concept. typedef lemon::Path Path; }; /// Default traits class used by BfsWizard - /// To make it easier to use Bfs algorithm - /// we have created a wizard class. - /// This \ref BfsWizard class needs default traits, - /// as well as the \ref Bfs class. - /// The \ref BfsWizardBase is a class to be the default traits of the - /// \ref BfsWizard class. + /// Default traits class used by BfsWizard. + /// \tparam GR The type of the digraph. template class BfsWizardBase : public BfsWizardDefaultTraits { @@ -937,7 +932,7 @@ public: /// Constructor. - /// This constructor does not require parameters, therefore it initiates + /// This constructor does not require parameters, it initiates /// all of the attributes to \c 0. BfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0), _dist(0), _path(0), _di(0) {} @@ -967,7 +962,6 @@ { typedef TR Base; - ///The type of the digraph the algorithm runs on. typedef typename TR::Digraph Digraph; typedef typename Digraph::Node Node; @@ -975,16 +969,10 @@ typedef typename Digraph::Arc Arc; typedef typename Digraph::OutArcIt OutArcIt; - ///\brief The type of the map that stores the predecessor - ///arcs of the shortest paths. typedef typename TR::PredMap PredMap; - ///\brief The type of the map that stores the distances of the nodes. typedef typename TR::DistMap DistMap; - ///\brief The type of the map that indicates which nodes are reached. typedef typename TR::ReachedMap ReachedMap; - ///\brief The type of the map that indicates which nodes are processed. typedef typename TR::ProcessedMap ProcessedMap; - ///The type of the shortest paths typedef typename TR::Path Path; public: @@ -1054,8 +1042,8 @@ ///Runs BFS algorithm to visit all nodes in the digraph. - ///This method runs BFS algorithm in order to compute - ///the shortest path to each node. + ///This method runs BFS algorithm in order to visit all nodes + ///in the digraph. void run() { run(INVALID); @@ -1067,11 +1055,12 @@ static PredMap *createPredMap(const Digraph &) { return 0; }; SetPredMapBase(const TR &b) : TR(b) {} }; - ///\brief \ref named-func-param "Named parameter" - ///for setting PredMap object. + + ///\brief \ref named-templ-param "Named parameter" for setting + ///the predecessor map. /// - ///\ref named-func-param "Named parameter" - ///for setting PredMap object. + ///\ref named-templ-param "Named parameter" function for setting + ///the map that stores the predecessor arcs of the nodes. template BfsWizard > predMap(const T &t) { @@ -1085,11 +1074,12 @@ static ReachedMap *createReachedMap(const Digraph &) { return 0; }; SetReachedMapBase(const TR &b) : TR(b) {} }; - ///\brief \ref named-func-param "Named parameter" - ///for setting ReachedMap object. + + ///\brief \ref named-templ-param "Named parameter" for setting + ///the reached map. /// - /// \ref named-func-param "Named parameter" - ///for setting ReachedMap object. + ///\ref named-templ-param "Named parameter" function for setting + ///the map that indicates which nodes are reached. template BfsWizard > reachedMap(const T &t) { @@ -1103,11 +1093,13 @@ static DistMap *createDistMap(const Digraph &) { return 0; }; SetDistMapBase(const TR &b) : TR(b) {} }; - ///\brief \ref named-func-param "Named parameter" - ///for setting DistMap object. + + ///\brief \ref named-templ-param "Named parameter" for setting + ///the distance map. /// - /// \ref named-func-param "Named parameter" - ///for setting DistMap object. + ///\ref named-templ-param "Named parameter" function for setting + ///the map that stores the distances of the nodes calculated + ///by the algorithm. template BfsWizard > distMap(const T &t) { @@ -1121,11 +1113,12 @@ static ProcessedMap *createProcessedMap(const Digraph &) { return 0; }; SetProcessedMapBase(const TR &b) : TR(b) {} }; - ///\brief \ref named-func-param "Named parameter" - ///for setting ProcessedMap object. + + ///\brief \ref named-func-param "Named parameter" for setting + ///the processed map. /// - /// \ref named-func-param "Named parameter" - ///for setting ProcessedMap object. + ///\ref named-templ-param "Named parameter" function for setting + ///the map that indicates which nodes are processed. template BfsWizard > processedMap(const T &t) { @@ -1264,7 +1257,7 @@ /// \brief The type of the map that indicates which nodes are reached. /// /// The type of the map that indicates which nodes are reached. - /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept. + /// It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap" concept. typedef typename Digraph::template NodeMap ReachedMap; /// \brief Instantiates a ReachedMap. @@ -1425,8 +1418,8 @@ /// \name Execution Control /// The simplest way to execute the BFS algorithm is to use one of the /// member functions called \ref run(Node) "run()".\n - /// If you need more control on the execution, first you have to call - /// \ref init(), then you can add several source nodes with + /// If you need better control on the execution, you have to call + /// \ref init() first, then you can add several source nodes with /// \ref addSource(). Finally the actual path computation can be /// performed with one of the \ref start() functions. @@ -1698,12 +1691,8 @@ /// \brief Runs the algorithm to visit all nodes in the digraph. /// - /// This method runs the %BFS algorithm in order to - /// compute the shortest path to each node. - /// - /// The algorithm computes - /// - the shortest path tree (forest), - /// - the distance of each node from the root(s). + /// This method runs the %BFS algorithm in order to visit all nodes + /// in the digraph. /// /// \note b.run(s) is just a shortcut of the following code. ///\code @@ -1735,7 +1724,7 @@ ///@{ - /// \brief Checks if a node is reached from the root(s). + /// \brief Checks if the given node is reached from the root(s). /// /// Returns \c true if \c v is reached from the root(s). /// diff --git a/lemon/bits/graph_extender.h b/lemon/bits/graph_extender.h --- a/lemon/bits/graph_extender.h +++ b/lemon/bits/graph_extender.h @@ -56,11 +56,11 @@ return Parent::maxArcId(); } - Node fromId(int id, Node) const { + static Node fromId(int id, Node) { return Parent::nodeFromId(id); } - Arc fromId(int id, Arc) const { + static Arc fromId(int id, Arc) { return Parent::arcFromId(id); } @@ -355,15 +355,15 @@ return Parent::maxEdgeId(); } - Node fromId(int id, Node) const { + static Node fromId(int id, Node) { return Parent::nodeFromId(id); } - Arc fromId(int id, Arc) const { + static Arc fromId(int id, Arc) { return Parent::arcFromId(id); } - Edge fromId(int id, Edge) const { + static Edge fromId(int id, Edge) { return Parent::edgeFromId(id); } diff --git a/lemon/bits/map_extender.h b/lemon/bits/map_extender.h --- a/lemon/bits/map_extender.h +++ b/lemon/bits/map_extender.h @@ -49,6 +49,8 @@ typedef typename Parent::Reference Reference; typedef typename Parent::ConstReference ConstReference; + typedef typename Parent::ReferenceMapTag ReferenceMapTag; + class MapIt; class ConstMapIt; @@ -191,6 +193,8 @@ typedef typename Parent::Reference Reference; typedef typename Parent::ConstReference ConstReference; + typedef typename Parent::ReferenceMapTag ReferenceMapTag; + class MapIt; class ConstMapIt; diff --git a/lemon/cbc.cc b/lemon/cbc.cc --- a/lemon/cbc.cc +++ b/lemon/cbc.cc @@ -94,6 +94,18 @@ return _prob->numberRows() - 1; } + int CbcMip::_addRow(Value l, ExprIterator b, ExprIterator e, Value u) { + std::vector indexes; + std::vector values; + + for(ExprIterator it = b; it != e; ++it) { + indexes.push_back(it->first); + values.push_back(it->second); + } + + _prob->addRow(values.size(), &indexes.front(), &values.front(), l, u); + return _prob->numberRows() - 1; + } void CbcMip::_eraseCol(int i) { _prob->deleteColumn(i); diff --git a/lemon/cbc.h b/lemon/cbc.h --- a/lemon/cbc.h +++ b/lemon/cbc.h @@ -62,6 +62,7 @@ virtual int _addCol(); virtual int _addRow(); + virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u); virtual void _eraseCol(int i); virtual void _eraseRow(int i); diff --git a/lemon/circulation.h b/lemon/circulation.h --- a/lemon/circulation.h +++ b/lemon/circulation.h @@ -72,7 +72,11 @@ /// The type of the map that stores the flow values. /// It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap" /// concept. +#ifdef DOXYGEN + typedef GR::ArcMap FlowMap; +#else typedef typename Digraph::template ArcMap FlowMap; +#endif /// \brief Instantiates a FlowMap. /// @@ -87,9 +91,12 @@ /// /// The elevator type used by the algorithm. /// - /// \sa Elevator - /// \sa LinkedElevator + /// \sa Elevator, LinkedElevator +#ifdef DOXYGEN + typedef lemon::Elevator Elevator; +#else typedef lemon::Elevator Elevator; +#endif /// \brief Instantiates an Elevator. /// @@ -299,7 +306,7 @@ /// The Elevator should have standard constructor interface to be /// able to automatically created by the algorithm (i.e. the /// digraph and the maximum level should be passed to it). - /// However an external elevator object could also be passed to the + /// However, an external elevator object could also be passed to the /// algorithm with the \ref elevator(Elevator&) "elevator()" function /// before calling \ref run() or \ref init(). /// \sa SetElevator @@ -469,8 +476,8 @@ /// \name Execution Control /// The simplest way to execute the algorithm is to call \ref run().\n - /// If you need more control on the initial solution or the execution, - /// first you have to call one of the \ref init() functions, then + /// If you need better control on the initial solution or the execution, + /// you have to call one of the \ref init() functions first, then /// the \ref start() function. ///@{ diff --git a/lemon/clp.cc b/lemon/clp.cc --- a/lemon/clp.cc +++ b/lemon/clp.cc @@ -78,6 +78,19 @@ return _prob->numberRows() - 1; } + int ClpLp::_addRow(Value l, ExprIterator b, ExprIterator e, Value u) { + std::vector indexes; + std::vector values; + + for(ExprIterator it = b; it != e; ++it) { + indexes.push_back(it->first); + values.push_back(it->second); + } + + _prob->addRow(values.size(), &indexes.front(), &values.front(), l, u); + return _prob->numberRows() - 1; + } + void ClpLp::_eraseCol(int c) { _col_names_ref.erase(_prob->getColumnName(c)); diff --git a/lemon/clp.h b/lemon/clp.h --- a/lemon/clp.h +++ b/lemon/clp.h @@ -75,6 +75,7 @@ virtual int _addCol(); virtual int _addRow(); + virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u); virtual void _eraseCol(int i); virtual void _eraseRow(int i); diff --git a/lemon/concepts/digraph.h b/lemon/concepts/digraph.h --- a/lemon/concepts/digraph.h +++ b/lemon/concepts/digraph.h @@ -35,46 +35,40 @@ /// /// \brief Class describing the concept of directed graphs. /// - /// This class describes the \ref concept "concept" of the - /// immutable directed digraphs. + /// This class describes the common interface of all directed + /// graphs (digraphs). /// - /// Note that actual digraph implementation like @ref ListDigraph or - /// @ref SmartDigraph may have several additional functionality. + /// Like all concept classes, it only provides an interface + /// without any sensible implementation. So any general algorithm for + /// directed graphs should compile with this class, but it will not + /// run properly, of course. + /// An actual digraph implementation like \ref ListDigraph or + /// \ref SmartDigraph may have additional functionality. /// - /// \sa concept + /// \sa Graph class Digraph { private: - ///Digraphs are \e not copy constructible. Use DigraphCopy() instead. + /// Diraphs are \e not copy constructible. Use DigraphCopy instead. + Digraph(const Digraph &) {} + /// \brief Assignment of a digraph to another one is \e not allowed. + /// Use DigraphCopy instead. + void operator=(const Digraph &) {} - ///Digraphs are \e not copy constructible. Use DigraphCopy() instead. - /// - Digraph(const Digraph &) {}; - ///\brief Assignment of \ref Digraph "Digraph"s to another ones are - ///\e not allowed. Use DigraphCopy() instead. + public: + /// Default constructor. + Digraph() { } - ///Assignment of \ref Digraph "Digraph"s to another ones are - ///\e not allowed. Use DigraphCopy() instead. - - void operator=(const Digraph &) {} - public: - ///\e - - /// Defalult constructor. - - /// Defalult constructor. - /// - Digraph() { } - /// Class for identifying a node of the digraph + /// The node type of the digraph /// This class identifies a node of the digraph. It also serves /// as a base class of the node iterators, - /// thus they will convert to this type. + /// thus they convert to this type. class Node { public: /// Default constructor - /// @warning The default constructor sets the iterator - /// to an undefined value. + /// Default constructor. + /// \warning It sets the object to an undefined value. Node() { } /// Copy constructor. @@ -82,40 +76,39 @@ /// Node(const Node&) { } - /// Invalid constructor \& conversion. + /// %Invalid constructor \& conversion. - /// This constructor initializes the iterator to be invalid. + /// Initializes the object to be invalid. /// \sa Invalid for more details. Node(Invalid) { } /// Equality operator + /// Equality operator. + /// /// Two iterators are equal if and only if they point to the - /// same object or both are invalid. + /// same object or both are \c INVALID. bool operator==(Node) const { return true; } /// Inequality operator - /// \sa operator==(Node n) - /// + /// Inequality operator. bool operator!=(Node) const { return true; } /// Artificial ordering operator. - /// To allow the use of digraph descriptors as key type in std::map or - /// similar associative container we require this. + /// Artificial ordering operator. /// - /// \note This operator only have to define some strict ordering of - /// the items; this order has nothing to do with the iteration - /// ordering of the items. + /// \note This operator only has to define some strict ordering of + /// the nodes; this order has nothing to do with the iteration + /// ordering of the nodes. bool operator<(Node) const { return false; } - }; - /// This iterator goes through each node. + /// Iterator class for the nodes. - /// This iterator goes through each node. - /// Its usage is quite simple, for example you can count the number - /// of nodes in digraph \c g of type \c Digraph like this: + /// This iterator goes through each node of the digraph. + /// Its usage is quite simple, for example, you can count the number + /// of nodes in a digraph \c g of type \c %Digraph like this: ///\code /// int count=0; /// for (Digraph::NodeIt n(g); n!=INVALID; ++n) ++count; @@ -124,30 +117,28 @@ public: /// Default constructor - /// @warning The default constructor sets the iterator - /// to an undefined value. + /// Default constructor. + /// \warning It sets the iterator to an undefined value. NodeIt() { } /// Copy constructor. /// Copy constructor. /// NodeIt(const NodeIt& n) : Node(n) { } - /// Invalid constructor \& conversion. + /// %Invalid constructor \& conversion. - /// Initialize the iterator to be invalid. + /// Initializes the iterator to be invalid. /// \sa Invalid for more details. NodeIt(Invalid) { } /// Sets the iterator to the first node. - /// Sets the iterator to the first node of \c g. + /// Sets the iterator to the first node of the given digraph. /// - NodeIt(const Digraph&) { } - /// Node -> NodeIt conversion. + explicit NodeIt(const Digraph&) { } + /// Sets the iterator to the given node. - /// Sets the iterator to the node of \c the digraph pointed by - /// the trivial iterator. - /// This feature necessitates that each time we - /// iterate the arc-set, the iteration order is the same. + /// Sets the iterator to the given node of the given digraph. + /// NodeIt(const Digraph&, const Node&) { } /// Next node. @@ -157,7 +148,7 @@ }; - /// Class for identifying an arc of the digraph + /// The arc type of the digraph /// This class identifies an arc of the digraph. It also serves /// as a base class of the arc iterators, @@ -166,207 +157,214 @@ public: /// Default constructor - /// @warning The default constructor sets the iterator - /// to an undefined value. + /// Default constructor. + /// \warning It sets the object to an undefined value. Arc() { } /// Copy constructor. /// Copy constructor. /// Arc(const Arc&) { } - /// Initialize the iterator to be invalid. + /// %Invalid constructor \& conversion. - /// Initialize the iterator to be invalid. - /// + /// Initializes the object to be invalid. + /// \sa Invalid for more details. Arc(Invalid) { } /// Equality operator + /// Equality operator. + /// /// Two iterators are equal if and only if they point to the - /// same object or both are invalid. + /// same object or both are \c INVALID. bool operator==(Arc) const { return true; } /// Inequality operator - /// \sa operator==(Arc n) - /// + /// Inequality operator. bool operator!=(Arc) const { return true; } /// Artificial ordering operator. - /// To allow the use of digraph descriptors as key type in std::map or - /// similar associative container we require this. + /// Artificial ordering operator. /// - /// \note This operator only have to define some strict ordering of - /// the items; this order has nothing to do with the iteration - /// ordering of the items. + /// \note This operator only has to define some strict ordering of + /// the arcs; this order has nothing to do with the iteration + /// ordering of the arcs. bool operator<(Arc) const { return false; } }; - /// This iterator goes trough the outgoing arcs of a node. + /// Iterator class for the outgoing arcs of a node. /// This iterator goes trough the \e outgoing arcs of a certain node /// of a digraph. - /// Its usage is quite simple, for example you can count the number + /// Its usage is quite simple, for example, you can count the number /// of outgoing arcs of a node \c n - /// in digraph \c g of type \c Digraph as follows. + /// in a digraph \c g of type \c %Digraph as follows. ///\code /// int count=0; - /// for (Digraph::OutArcIt e(g, n); e!=INVALID; ++e) ++count; + /// for (Digraph::OutArcIt a(g, n); a!=INVALID; ++a) ++count; ///\endcode - class OutArcIt : public Arc { public: /// Default constructor - /// @warning The default constructor sets the iterator - /// to an undefined value. + /// Default constructor. + /// \warning It sets the iterator to an undefined value. OutArcIt() { } /// Copy constructor. /// Copy constructor. /// OutArcIt(const OutArcIt& e) : Arc(e) { } - /// Initialize the iterator to be invalid. + /// %Invalid constructor \& conversion. - /// Initialize the iterator to be invalid. + /// Initializes the iterator to be invalid. + /// \sa Invalid for more details. + OutArcIt(Invalid) { } + /// Sets the iterator to the first outgoing arc. + + /// Sets the iterator to the first outgoing arc of the given node. /// - OutArcIt(Invalid) { } - /// This constructor sets the iterator to the first outgoing arc. + OutArcIt(const Digraph&, const Node&) { } + /// Sets the iterator to the given arc. - /// This constructor sets the iterator to the first outgoing arc of - /// the node. - OutArcIt(const Digraph&, const Node&) { } - /// Arc -> OutArcIt conversion - - /// Sets the iterator to the value of the trivial iterator. - /// This feature necessitates that each time we - /// iterate the arc-set, the iteration order is the same. + /// Sets the iterator to the given arc of the given digraph. + /// OutArcIt(const Digraph&, const Arc&) { } - ///Next outgoing arc + /// Next outgoing arc /// Assign the iterator to the next /// outgoing arc of the corresponding node. OutArcIt& operator++() { return *this; } }; - /// This iterator goes trough the incoming arcs of a node. + /// Iterator class for the incoming arcs of a node. /// This iterator goes trough the \e incoming arcs of a certain node /// of a digraph. - /// Its usage is quite simple, for example you can count the number - /// of outgoing arcs of a node \c n - /// in digraph \c g of type \c Digraph as follows. + /// Its usage is quite simple, for example, you can count the number + /// of incoming arcs of a node \c n + /// in a digraph \c g of type \c %Digraph as follows. ///\code /// int count=0; - /// for(Digraph::InArcIt e(g, n); e!=INVALID; ++e) ++count; + /// for(Digraph::InArcIt a(g, n); a!=INVALID; ++a) ++count; ///\endcode - class InArcIt : public Arc { public: /// Default constructor - /// @warning The default constructor sets the iterator - /// to an undefined value. + /// Default constructor. + /// \warning It sets the iterator to an undefined value. InArcIt() { } /// Copy constructor. /// Copy constructor. /// InArcIt(const InArcIt& e) : Arc(e) { } - /// Initialize the iterator to be invalid. + /// %Invalid constructor \& conversion. - /// Initialize the iterator to be invalid. + /// Initializes the iterator to be invalid. + /// \sa Invalid for more details. + InArcIt(Invalid) { } + /// Sets the iterator to the first incoming arc. + + /// Sets the iterator to the first incoming arc of the given node. /// - InArcIt(Invalid) { } - /// This constructor sets the iterator to first incoming arc. + InArcIt(const Digraph&, const Node&) { } + /// Sets the iterator to the given arc. - /// This constructor set the iterator to the first incoming arc of - /// the node. - InArcIt(const Digraph&, const Node&) { } - /// Arc -> InArcIt conversion - - /// Sets the iterator to the value of the trivial iterator \c e. - /// This feature necessitates that each time we - /// iterate the arc-set, the iteration order is the same. + /// Sets the iterator to the given arc of the given digraph. + /// InArcIt(const Digraph&, const Arc&) { } /// Next incoming arc - /// Assign the iterator to the next inarc of the corresponding node. - /// + /// Assign the iterator to the next + /// incoming arc of the corresponding node. InArcIt& operator++() { return *this; } }; - /// This iterator goes through each arc. - /// This iterator goes through each arc of a digraph. - /// Its usage is quite simple, for example you can count the number - /// of arcs in a digraph \c g of type \c Digraph as follows: + /// Iterator class for the arcs. + + /// This iterator goes through each arc of the digraph. + /// Its usage is quite simple, for example, you can count the number + /// of arcs in a digraph \c g of type \c %Digraph as follows: ///\code /// int count=0; - /// for(Digraph::ArcIt e(g); e!=INVALID; ++e) ++count; + /// for(Digraph::ArcIt a(g); a!=INVALID; ++a) ++count; ///\endcode class ArcIt : public Arc { public: /// Default constructor - /// @warning The default constructor sets the iterator - /// to an undefined value. + /// Default constructor. + /// \warning It sets the iterator to an undefined value. ArcIt() { } /// Copy constructor. /// Copy constructor. /// ArcIt(const ArcIt& e) : Arc(e) { } - /// Initialize the iterator to be invalid. + /// %Invalid constructor \& conversion. - /// Initialize the iterator to be invalid. + /// Initializes the iterator to be invalid. + /// \sa Invalid for more details. + ArcIt(Invalid) { } + /// Sets the iterator to the first arc. + + /// Sets the iterator to the first arc of the given digraph. /// - ArcIt(Invalid) { } - /// This constructor sets the iterator to the first arc. + explicit ArcIt(const Digraph& g) { ignore_unused_variable_warning(g); } + /// Sets the iterator to the given arc. - /// This constructor sets the iterator to the first arc of \c g. - ///@param g the digraph - ArcIt(const Digraph& g) { ignore_unused_variable_warning(g); } - /// Arc -> ArcIt conversion - - /// Sets the iterator to the value of the trivial iterator \c e. - /// This feature necessitates that each time we - /// iterate the arc-set, the iteration order is the same. + /// Sets the iterator to the given arc of the given digraph. + /// ArcIt(const Digraph&, const Arc&) { } - ///Next arc + /// Next arc /// Assign the iterator to the next arc. + /// ArcIt& operator++() { return *this; } }; - ///Gives back the target node of an arc. - ///Gives back the target node of an arc. + /// \brief The source node of the arc. /// - Node target(Arc) const { return INVALID; } - ///Gives back the source node of an arc. - - ///Gives back the source node of an arc. - /// + /// Returns the source node of the given arc. Node source(Arc) const { return INVALID; } - /// \brief Returns the ID of the node. + /// \brief The target node of the arc. + /// + /// Returns the target node of the given arc. + Node target(Arc) const { return INVALID; } + + /// \brief The ID of the node. + /// + /// Returns the ID of the given node. int id(Node) const { return -1; } - /// \brief Returns the ID of the arc. + /// \brief The ID of the arc. + /// + /// Returns the ID of the given arc. int id(Arc) const { return -1; } - /// \brief Returns the node with the given ID. + /// \brief The node with the given ID. /// - /// \pre The argument should be a valid node ID in the graph. + /// Returns the node with the given ID. + /// \pre The argument should be a valid node ID in the digraph. Node nodeFromId(int) const { return INVALID; } - /// \brief Returns the arc with the given ID. + /// \brief The arc with the given ID. /// - /// \pre The argument should be a valid arc ID in the graph. + /// Returns the arc with the given ID. + /// \pre The argument should be a valid arc ID in the digraph. Arc arcFromId(int) const { return INVALID; } - /// \brief Returns an upper bound on the node IDs. + /// \brief An upper bound on the node IDs. + /// + /// Returns an upper bound on the node IDs. int maxNodeId() const { return -1; } - /// \brief Returns an upper bound on the arc IDs. + /// \brief An upper bound on the arc IDs. + /// + /// Returns an upper bound on the arc IDs. int maxArcId() const { return -1; } void first(Node&) const {} @@ -392,45 +390,46 @@ // Dummy parameter. int maxId(Arc) const { return -1; } + /// \brief The opposite node on the arc. + /// + /// Returns the opposite node on the given arc. + Node oppositeNode(Node, Arc) const { return INVALID; } + /// \brief The base node of the iterator. /// - /// Gives back the base node of the iterator. - /// It is always the target of the pointed arc. - Node baseNode(const InArcIt&) const { return INVALID; } + /// Returns the base node of the given outgoing arc iterator + /// (i.e. the source node of the corresponding arc). + Node baseNode(OutArcIt) const { return INVALID; } /// \brief The running node of the iterator. /// - /// Gives back the running node of the iterator. - /// It is always the source of the pointed arc. - Node runningNode(const InArcIt&) const { return INVALID; } + /// Returns the running node of the given outgoing arc iterator + /// (i.e. the target node of the corresponding arc). + Node runningNode(OutArcIt) const { return INVALID; } /// \brief The base node of the iterator. /// - /// Gives back the base node of the iterator. - /// It is always the source of the pointed arc. - Node baseNode(const OutArcIt&) const { return INVALID; } + /// Returns the base node of the given incomming arc iterator + /// (i.e. the target node of the corresponding arc). + Node baseNode(InArcIt) const { return INVALID; } /// \brief The running node of the iterator. /// - /// Gives back the running node of the iterator. - /// It is always the target of the pointed arc. - Node runningNode(const OutArcIt&) const { return INVALID; } + /// Returns the running node of the given incomming arc iterator + /// (i.e. the source node of the corresponding arc). + Node runningNode(InArcIt) const { return INVALID; } - /// \brief The opposite node on the given arc. + /// \brief Standard graph map type for the nodes. /// - /// Gives back the opposite node on the given arc. - Node oppositeNode(const Node&, const Arc&) const { return INVALID; } - - /// \brief Reference map of the nodes to type \c T. - /// - /// Reference map of the nodes to type \c T. + /// Standard graph map type for the nodes. + /// It conforms to the ReferenceMap concept. template class NodeMap : public ReferenceMap { public: - ///\e - NodeMap(const Digraph&) { } - ///\e + /// Constructor + explicit NodeMap(const Digraph&) { } + /// Constructor with given initial value NodeMap(const Digraph&, T) { } private: @@ -445,17 +444,19 @@ } }; - /// \brief Reference map of the arcs to type \c T. + /// \brief Standard graph map type for the arcs. /// - /// Reference map of the arcs to type \c T. + /// Standard graph map type for the arcs. + /// It conforms to the ReferenceMap concept. template class ArcMap : public ReferenceMap { public: - ///\e - ArcMap(const Digraph&) { } - ///\e + /// Constructor + explicit ArcMap(const Digraph&) { } + /// Constructor with given initial value ArcMap(const Digraph&, T) { } + private: ///Copy constructor ArcMap(const ArcMap& em) : diff --git a/lemon/concepts/graph.h b/lemon/concepts/graph.h --- a/lemon/concepts/graph.h +++ b/lemon/concepts/graph.h @@ -18,12 +18,14 @@ ///\ingroup graph_concepts ///\file -///\brief The concept of Undirected Graphs. +///\brief The concept of undirected graphs. #ifndef LEMON_CONCEPTS_GRAPH_H #define LEMON_CONCEPTS_GRAPH_H #include +#include +#include #include namespace lemon { @@ -31,63 +33,74 @@ /// \ingroup graph_concepts /// - /// \brief Class describing the concept of Undirected Graphs. + /// \brief Class describing the concept of undirected graphs. /// - /// This class describes the common interface of all Undirected - /// Graphs. + /// This class describes the common interface of all undirected + /// graphs. /// - /// As all concept describing classes it provides only interface - /// without any sensible implementation. So any algorithm for - /// undirected graph should compile with this class, but it will not + /// Like all concept classes, it only provides an interface + /// without any sensible implementation. So any general algorithm for + /// undirected graphs should compile with this class, but it will not /// run properly, of course. + /// An actual graph implementation like \ref ListGraph or + /// \ref SmartGraph may have additional functionality. /// - /// The LEMON undirected graphs also fulfill the concept of - /// directed graphs (\ref lemon::concepts::Digraph "Digraph - /// Concept"). Each edges can be seen as two opposite - /// directed arc and consequently the undirected graph can be - /// seen as the direceted graph of these directed arcs. The - /// Graph has the Edge inner class for the edges and - /// the Arc type for the directed arcs. The Arc type is - /// convertible to Edge or inherited from it so from a directed - /// arc we can get the represented edge. + /// The undirected graphs also fulfill the concept of \ref Digraph + /// "directed graphs", since each edge can also be regarded as two + /// oppositely directed arcs. + /// Undirected graphs provide an Edge type for the undirected edges and + /// an Arc type for the directed arcs. The Arc type is convertible to + /// Edge or inherited from it, i.e. the corresponding edge can be + /// obtained from an arc. + /// EdgeIt and EdgeMap classes can be used for the edges, while ArcIt + /// and ArcMap classes can be used for the arcs (just like in digraphs). + /// Both InArcIt and OutArcIt iterates on the same edges but with + /// opposite direction. IncEdgeIt also iterates on the same edges + /// as OutArcIt and InArcIt, but it is not convertible to Arc, + /// only to Edge. /// - /// In the sense of the LEMON each edge has a default - /// direction (it should be in every computer implementation, - /// because the order of edge's nodes defines an - /// orientation). With the default orientation we can define that - /// the directed arc is forward or backward directed. With the \c - /// direction() and \c direct() function we can get the direction - /// of the directed arc and we can direct an edge. + /// In LEMON, each undirected edge has an inherent orientation. + /// Thus it can defined if an arc is forward or backward oriented in + /// an undirected graph with respect to this default oriantation of + /// the represented edge. + /// With the direction() and direct() functions the direction + /// of an arc can be obtained and set, respectively. /// - /// The EdgeIt is an iterator for the edges. We can use - /// the EdgeMap to map values for the edges. The InArcIt and - /// OutArcIt iterates on the same edges but with opposite - /// direction. The IncEdgeIt iterates also on the same edges - /// as the OutArcIt and InArcIt but it is not convertible to Arc just - /// to Edge. + /// Only nodes and edges can be added to or removed from an undirected + /// graph and the corresponding arcs are added or removed automatically. + /// + /// \sa Digraph class Graph { + private: + /// Graphs are \e not copy constructible. Use DigraphCopy instead. + Graph(const Graph&) {} + /// \brief Assignment of a graph to another one is \e not allowed. + /// Use DigraphCopy instead. + void operator=(const Graph&) {} + public: - /// \brief The undirected graph should be tagged by the - /// UndirectedTag. + /// Default constructor. + Graph() {} + + /// \brief Undirected graphs should be tagged with \c UndirectedTag. /// - /// The undirected graph should be tagged by the UndirectedTag. This - /// tag helps the enable_if technics to make compile time + /// Undirected graphs should be tagged with \c UndirectedTag. + /// + /// This tag helps the \c enable_if technics to make compile time /// specializations for undirected graphs. typedef True UndirectedTag; - /// \brief The base type of node iterators, - /// or in other words, the trivial node iterator. - /// - /// This is the base type of each node iterator, - /// thus each kind of node iterator converts to this. - /// More precisely each kind of node iterator should be inherited - /// from the trivial node iterator. + /// The node type of the graph + + /// This class identifies a node of the graph. It also serves + /// as a base class of the node iterators, + /// thus they convert to this type. class Node { public: /// Default constructor - /// @warning The default constructor sets the iterator - /// to an undefined value. + /// Default constructor. + /// \warning It sets the object to an undefined value. Node() { } /// Copy constructor. @@ -95,40 +108,40 @@ /// Node(const Node&) { } - /// Invalid constructor \& conversion. + /// %Invalid constructor \& conversion. - /// This constructor initializes the iterator to be invalid. + /// Initializes the object to be invalid. /// \sa Invalid for more details. Node(Invalid) { } /// Equality operator + /// Equality operator. + /// /// Two iterators are equal if and only if they point to the - /// same object or both are invalid. + /// same object or both are \c INVALID. bool operator==(Node) const { return true; } /// Inequality operator - /// \sa operator==(Node n) - /// + /// Inequality operator. bool operator!=(Node) const { return true; } /// Artificial ordering operator. - /// To allow the use of graph descriptors as key type in std::map or - /// similar associative container we require this. + /// Artificial ordering operator. /// - /// \note This operator only have to define some strict ordering of + /// \note This operator only has to define some strict ordering of /// the items; this order has nothing to do with the iteration /// ordering of the items. bool operator<(Node) const { return false; } }; - /// This iterator goes through each node. + /// Iterator class for the nodes. - /// This iterator goes through each node. - /// Its usage is quite simple, for example you can count the number - /// of nodes in graph \c g of type \c Graph like this: + /// This iterator goes through each node of the graph. + /// Its usage is quite simple, for example, you can count the number + /// of nodes in a graph \c g of type \c %Graph like this: ///\code /// int count=0; /// for (Graph::NodeIt n(g); n!=INVALID; ++n) ++count; @@ -137,30 +150,28 @@ public: /// Default constructor - /// @warning The default constructor sets the iterator - /// to an undefined value. + /// Default constructor. + /// \warning It sets the iterator to an undefined value. NodeIt() { } /// Copy constructor. /// Copy constructor. /// NodeIt(const NodeIt& n) : Node(n) { } - /// Invalid constructor \& conversion. + /// %Invalid constructor \& conversion. - /// Initialize the iterator to be invalid. + /// Initializes the iterator to be invalid. /// \sa Invalid for more details. NodeIt(Invalid) { } /// Sets the iterator to the first node. - /// Sets the iterator to the first node of \c g. + /// Sets the iterator to the first node of the given digraph. /// - NodeIt(const Graph&) { } - /// Node -> NodeIt conversion. + explicit NodeIt(const Graph&) { } + /// Sets the iterator to the given node. - /// Sets the iterator to the node of \c the graph pointed by - /// the trivial iterator. - /// This feature necessitates that each time we - /// iterate the arc-set, the iteration order is the same. + /// Sets the iterator to the given node of the given digraph. + /// NodeIt(const Graph&, const Node&) { } /// Next node. @@ -170,54 +181,55 @@ }; - /// The base type of the edge iterators. + /// The edge type of the graph - /// The base type of the edge iterators. - /// + /// This class identifies an edge of the graph. It also serves + /// as a base class of the edge iterators, + /// thus they will convert to this type. class Edge { public: /// Default constructor - /// @warning The default constructor sets the iterator - /// to an undefined value. + /// Default constructor. + /// \warning It sets the object to an undefined value. Edge() { } /// Copy constructor. /// Copy constructor. /// Edge(const Edge&) { } - /// Initialize the iterator to be invalid. + /// %Invalid constructor \& conversion. - /// Initialize the iterator to be invalid. - /// + /// Initializes the object to be invalid. + /// \sa Invalid for more details. Edge(Invalid) { } /// Equality operator + /// Equality operator. + /// /// Two iterators are equal if and only if they point to the - /// same object or both are invalid. + /// same object or both are \c INVALID. bool operator==(Edge) const { return true; } /// Inequality operator - /// \sa operator==(Edge n) - /// + /// Inequality operator. bool operator!=(Edge) const { return true; } /// Artificial ordering operator. - /// To allow the use of graph descriptors as key type in std::map or - /// similar associative container we require this. + /// Artificial ordering operator. /// - /// \note This operator only have to define some strict ordering of - /// the items; this order has nothing to do with the iteration - /// ordering of the items. + /// \note This operator only has to define some strict ordering of + /// the edges; this order has nothing to do with the iteration + /// ordering of the edges. bool operator<(Edge) const { return false; } }; - /// This iterator goes through each edge. + /// Iterator class for the edges. - /// This iterator goes through each edge of a graph. - /// Its usage is quite simple, for example you can count the number - /// of edges in a graph \c g of type \c Graph as follows: + /// This iterator goes through each edge of the graph. + /// Its usage is quite simple, for example, you can count the number + /// of edges in a graph \c g of type \c %Graph as follows: ///\code /// int count=0; /// for(Graph::EdgeIt e(g); e!=INVALID; ++e) ++count; @@ -226,290 +238,285 @@ public: /// Default constructor - /// @warning The default constructor sets the iterator - /// to an undefined value. + /// Default constructor. + /// \warning It sets the iterator to an undefined value. EdgeIt() { } /// Copy constructor. /// Copy constructor. /// EdgeIt(const EdgeIt& e) : Edge(e) { } - /// Initialize the iterator to be invalid. + /// %Invalid constructor \& conversion. - /// Initialize the iterator to be invalid. + /// Initializes the iterator to be invalid. + /// \sa Invalid for more details. + EdgeIt(Invalid) { } + /// Sets the iterator to the first edge. + + /// Sets the iterator to the first edge of the given graph. /// - EdgeIt(Invalid) { } - /// This constructor sets the iterator to the first edge. + explicit EdgeIt(const Graph&) { } + /// Sets the iterator to the given edge. - /// This constructor sets the iterator to the first edge. - EdgeIt(const Graph&) { } - /// Edge -> EdgeIt conversion - - /// Sets the iterator to the value of the trivial iterator. - /// This feature necessitates that each time we - /// iterate the edge-set, the iteration order is the - /// same. + /// Sets the iterator to the given edge of the given graph. + /// EdgeIt(const Graph&, const Edge&) { } /// Next edge /// Assign the iterator to the next edge. + /// EdgeIt& operator++() { return *this; } }; - /// \brief This iterator goes trough the incident undirected - /// arcs of a node. - /// - /// This iterator goes trough the incident edges - /// of a certain node of a graph. You should assume that the - /// loop arcs will be iterated twice. - /// - /// Its usage is quite simple, for example you can compute the - /// degree (i.e. count the number of incident arcs of a node \c n - /// in graph \c g of type \c Graph as follows. + /// Iterator class for the incident edges of a node. + + /// This iterator goes trough the incident undirected edges + /// of a certain node of a graph. + /// Its usage is quite simple, for example, you can compute the + /// degree (i.e. the number of incident edges) of a node \c n + /// in a graph \c g of type \c %Graph as follows. /// ///\code /// int count=0; /// for(Graph::IncEdgeIt e(g, n); e!=INVALID; ++e) ++count; ///\endcode + /// + /// \warning Loop edges will be iterated twice. class IncEdgeIt : public Edge { public: /// Default constructor - /// @warning The default constructor sets the iterator - /// to an undefined value. + /// Default constructor. + /// \warning It sets the iterator to an undefined value. IncEdgeIt() { } /// Copy constructor. /// Copy constructor. /// IncEdgeIt(const IncEdgeIt& e) : Edge(e) { } - /// Initialize the iterator to be invalid. + /// %Invalid constructor \& conversion. - /// Initialize the iterator to be invalid. + /// Initializes the iterator to be invalid. + /// \sa Invalid for more details. + IncEdgeIt(Invalid) { } + /// Sets the iterator to the first incident edge. + + /// Sets the iterator to the first incident edge of the given node. /// - IncEdgeIt(Invalid) { } - /// This constructor sets the iterator to first incident arc. + IncEdgeIt(const Graph&, const Node&) { } + /// Sets the iterator to the given edge. - /// This constructor set the iterator to the first incident arc of - /// the node. - IncEdgeIt(const Graph&, const Node&) { } - /// Edge -> IncEdgeIt conversion + /// Sets the iterator to the given edge of the given graph. + /// + IncEdgeIt(const Graph&, const Edge&) { } + /// Next incident edge - /// Sets the iterator to the value of the trivial iterator \c e. - /// This feature necessitates that each time we - /// iterate the arc-set, the iteration order is the same. - IncEdgeIt(const Graph&, const Edge&) { } - /// Next incident arc - - /// Assign the iterator to the next incident arc + /// Assign the iterator to the next incident edge /// of the corresponding node. IncEdgeIt& operator++() { return *this; } }; - /// The directed arc type. + /// The arc type of the graph - /// The directed arc type. It can be converted to the - /// edge or it should be inherited from the undirected - /// edge. + /// This class identifies a directed arc of the graph. It also serves + /// as a base class of the arc iterators, + /// thus they will convert to this type. class Arc { public: /// Default constructor - /// @warning The default constructor sets the iterator - /// to an undefined value. + /// Default constructor. + /// \warning It sets the object to an undefined value. Arc() { } /// Copy constructor. /// Copy constructor. /// Arc(const Arc&) { } - /// Initialize the iterator to be invalid. + /// %Invalid constructor \& conversion. - /// Initialize the iterator to be invalid. - /// + /// Initializes the object to be invalid. + /// \sa Invalid for more details. Arc(Invalid) { } /// Equality operator + /// Equality operator. + /// /// Two iterators are equal if and only if they point to the - /// same object or both are invalid. + /// same object or both are \c INVALID. bool operator==(Arc) const { return true; } /// Inequality operator - /// \sa operator==(Arc n) - /// + /// Inequality operator. bool operator!=(Arc) const { return true; } /// Artificial ordering operator. - /// To allow the use of graph descriptors as key type in std::map or - /// similar associative container we require this. + /// Artificial ordering operator. /// - /// \note This operator only have to define some strict ordering of - /// the items; this order has nothing to do with the iteration - /// ordering of the items. + /// \note This operator only has to define some strict ordering of + /// the arcs; this order has nothing to do with the iteration + /// ordering of the arcs. bool operator<(Arc) const { return false; } - /// Converison to Edge + /// Converison to \c Edge + + /// Converison to \c Edge. + /// operator Edge() const { return Edge(); } }; - /// This iterator goes through each directed arc. - /// This iterator goes through each arc of a graph. - /// Its usage is quite simple, for example you can count the number - /// of arcs in a graph \c g of type \c Graph as follows: + /// Iterator class for the arcs. + + /// This iterator goes through each directed arc of the graph. + /// Its usage is quite simple, for example, you can count the number + /// of arcs in a graph \c g of type \c %Graph as follows: ///\code /// int count=0; - /// for(Graph::ArcIt e(g); e!=INVALID; ++e) ++count; + /// for(Graph::ArcIt a(g); a!=INVALID; ++a) ++count; ///\endcode class ArcIt : public Arc { public: /// Default constructor - /// @warning The default constructor sets the iterator - /// to an undefined value. + /// Default constructor. + /// \warning It sets the iterator to an undefined value. ArcIt() { } /// Copy constructor. /// Copy constructor. /// ArcIt(const ArcIt& e) : Arc(e) { } - /// Initialize the iterator to be invalid. + /// %Invalid constructor \& conversion. - /// Initialize the iterator to be invalid. + /// Initializes the iterator to be invalid. + /// \sa Invalid for more details. + ArcIt(Invalid) { } + /// Sets the iterator to the first arc. + + /// Sets the iterator to the first arc of the given graph. /// - ArcIt(Invalid) { } - /// This constructor sets the iterator to the first arc. + explicit ArcIt(const Graph &g) { ignore_unused_variable_warning(g); } + /// Sets the iterator to the given arc. - /// This constructor sets the iterator to the first arc of \c g. - ///@param g the graph - ArcIt(const Graph &g) { ignore_unused_variable_warning(g); } - /// Arc -> ArcIt conversion - - /// Sets the iterator to the value of the trivial iterator \c e. - /// This feature necessitates that each time we - /// iterate the arc-set, the iteration order is the same. + /// Sets the iterator to the given arc of the given graph. + /// ArcIt(const Graph&, const Arc&) { } - ///Next arc + /// Next arc /// Assign the iterator to the next arc. + /// ArcIt& operator++() { return *this; } }; - /// This iterator goes trough the outgoing directed arcs of a node. + /// Iterator class for the outgoing arcs of a node. - /// This iterator goes trough the \e outgoing arcs of a certain node - /// of a graph. - /// Its usage is quite simple, for example you can count the number + /// This iterator goes trough the \e outgoing directed arcs of a + /// certain node of a graph. + /// Its usage is quite simple, for example, you can count the number /// of outgoing arcs of a node \c n - /// in graph \c g of type \c Graph as follows. + /// in a graph \c g of type \c %Graph as follows. ///\code /// int count=0; - /// for (Graph::OutArcIt e(g, n); e!=INVALID; ++e) ++count; + /// for (Digraph::OutArcIt a(g, n); a!=INVALID; ++a) ++count; ///\endcode - class OutArcIt : public Arc { public: /// Default constructor - /// @warning The default constructor sets the iterator - /// to an undefined value. + /// Default constructor. + /// \warning It sets the iterator to an undefined value. OutArcIt() { } /// Copy constructor. /// Copy constructor. /// OutArcIt(const OutArcIt& e) : Arc(e) { } - /// Initialize the iterator to be invalid. + /// %Invalid constructor \& conversion. - /// Initialize the iterator to be invalid. + /// Initializes the iterator to be invalid. + /// \sa Invalid for more details. + OutArcIt(Invalid) { } + /// Sets the iterator to the first outgoing arc. + + /// Sets the iterator to the first outgoing arc of the given node. /// - OutArcIt(Invalid) { } - /// This constructor sets the iterator to the first outgoing arc. - - /// This constructor sets the iterator to the first outgoing arc of - /// the node. - ///@param n the node - ///@param g the graph OutArcIt(const Graph& n, const Node& g) { ignore_unused_variable_warning(n); ignore_unused_variable_warning(g); } - /// Arc -> OutArcIt conversion + /// Sets the iterator to the given arc. - /// Sets the iterator to the value of the trivial iterator. - /// This feature necessitates that each time we - /// iterate the arc-set, the iteration order is the same. + /// Sets the iterator to the given arc of the given graph. + /// OutArcIt(const Graph&, const Arc&) { } - ///Next outgoing arc + /// Next outgoing arc /// Assign the iterator to the next /// outgoing arc of the corresponding node. OutArcIt& operator++() { return *this; } }; - /// This iterator goes trough the incoming directed arcs of a node. + /// Iterator class for the incoming arcs of a node. - /// This iterator goes trough the \e incoming arcs of a certain node - /// of a graph. - /// Its usage is quite simple, for example you can count the number - /// of outgoing arcs of a node \c n - /// in graph \c g of type \c Graph as follows. + /// This iterator goes trough the \e incoming directed arcs of a + /// certain node of a graph. + /// Its usage is quite simple, for example, you can count the number + /// of incoming arcs of a node \c n + /// in a graph \c g of type \c %Graph as follows. ///\code /// int count=0; - /// for(Graph::InArcIt e(g, n); e!=INVALID; ++e) ++count; + /// for (Digraph::InArcIt a(g, n); a!=INVALID; ++a) ++count; ///\endcode - class InArcIt : public Arc { public: /// Default constructor - /// @warning The default constructor sets the iterator - /// to an undefined value. + /// Default constructor. + /// \warning It sets the iterator to an undefined value. InArcIt() { } /// Copy constructor. /// Copy constructor. /// InArcIt(const InArcIt& e) : Arc(e) { } - /// Initialize the iterator to be invalid. + /// %Invalid constructor \& conversion. - /// Initialize the iterator to be invalid. + /// Initializes the iterator to be invalid. + /// \sa Invalid for more details. + InArcIt(Invalid) { } + /// Sets the iterator to the first incoming arc. + + /// Sets the iterator to the first incoming arc of the given node. /// - InArcIt(Invalid) { } - /// This constructor sets the iterator to first incoming arc. - - /// This constructor set the iterator to the first incoming arc of - /// the node. - ///@param n the node - ///@param g the graph InArcIt(const Graph& g, const Node& n) { ignore_unused_variable_warning(n); ignore_unused_variable_warning(g); } - /// Arc -> InArcIt conversion + /// Sets the iterator to the given arc. - /// Sets the iterator to the value of the trivial iterator \c e. - /// This feature necessitates that each time we - /// iterate the arc-set, the iteration order is the same. + /// Sets the iterator to the given arc of the given graph. + /// InArcIt(const Graph&, const Arc&) { } /// Next incoming arc - /// Assign the iterator to the next inarc of the corresponding node. - /// + /// Assign the iterator to the next + /// incoming arc of the corresponding node. InArcIt& operator++() { return *this; } }; - /// \brief Reference map of the nodes to type \c T. + /// \brief Standard graph map type for the nodes. /// - /// Reference map of the nodes to type \c T. + /// Standard graph map type for the nodes. + /// It conforms to the ReferenceMap concept. template class NodeMap : public ReferenceMap { public: - ///\e - NodeMap(const Graph&) { } - ///\e + /// Constructor + explicit NodeMap(const Graph&) { } + /// Constructor with given initial value NodeMap(const Graph&, T) { } private: @@ -524,18 +531,20 @@ } }; - /// \brief Reference map of the arcs to type \c T. + /// \brief Standard graph map type for the arcs. /// - /// Reference map of the arcs to type \c T. + /// Standard graph map type for the arcs. + /// It conforms to the ReferenceMap concept. template class ArcMap : public ReferenceMap { public: - ///\e - ArcMap(const Graph&) { } - ///\e + /// Constructor + explicit ArcMap(const Graph&) { } + /// Constructor with given initial value ArcMap(const Graph&, T) { } + private: ///Copy constructor ArcMap(const ArcMap& em) : @@ -548,18 +557,20 @@ } }; - /// Reference map of the edges to type \c T. - - /// Reference map of the edges to type \c T. + /// \brief Standard graph map type for the edges. + /// + /// Standard graph map type for the edges. + /// It conforms to the ReferenceMap concept. template class EdgeMap : public ReferenceMap { public: - ///\e - EdgeMap(const Graph&) { } - ///\e + /// Constructor + explicit EdgeMap(const Graph&) { } + /// Constructor with given initial value EdgeMap(const Graph&, T) { } + private: ///Copy constructor EdgeMap(const EdgeMap& em) : @@ -572,107 +583,124 @@ } }; - /// \brief Direct the given edge. + /// \brief The first node of the edge. /// - /// Direct the given edge. The returned arc source - /// will be the given node. - Arc direct(const Edge&, const Node&) const { - return INVALID; - } - - /// \brief Direct the given edge. + /// Returns the first node of the given edge. /// - /// Direct the given edge. The returned arc - /// represents the given edge and the direction comes - /// from the bool parameter. The source of the edge and - /// the directed arc is the same when the given bool is true. - Arc direct(const Edge&, bool) const { - return INVALID; - } - - /// \brief Returns true if the arc has default orientation. - /// - /// Returns whether the given directed arc is same orientation as - /// the corresponding edge's default orientation. - bool direction(Arc) const { return true; } - - /// \brief Returns the opposite directed arc. - /// - /// Returns the opposite directed arc. - Arc oppositeArc(Arc) const { return INVALID; } - - /// \brief Opposite node on an arc - /// - /// \return The opposite of the given node on the given edge. - Node oppositeNode(Node, Edge) const { return INVALID; } - - /// \brief First node of the edge. - /// - /// \return The first node of the given edge. - /// - /// Naturally edges don't have direction and thus - /// don't have source and target node. However we use \c u() and \c v() - /// methods to query the two nodes of the arc. The direction of the - /// arc which arises this way is called the inherent direction of the - /// edge, and is used to define the "default" direction - /// of the directed versions of the arcs. + /// Edges don't have source and target nodes, however, methods + /// u() and v() are used to query the two end-nodes of an edge. + /// The orientation of an edge that arises this way is called + /// the inherent direction, it is used to define the default + /// direction for the corresponding arcs. /// \sa v() /// \sa direction() Node u(Edge) const { return INVALID; } - /// \brief Second node of the edge. + /// \brief The second node of the edge. /// - /// \return The second node of the given edge. + /// Returns the second node of the given edge. /// - /// Naturally edges don't have direction and thus - /// don't have source and target node. However we use \c u() and \c v() - /// methods to query the two nodes of the arc. The direction of the - /// arc which arises this way is called the inherent direction of the - /// edge, and is used to define the "default" direction - /// of the directed versions of the arcs. + /// Edges don't have source and target nodes, however, methods + /// u() and v() are used to query the two end-nodes of an edge. + /// The orientation of an edge that arises this way is called + /// the inherent direction, it is used to define the default + /// direction for the corresponding arcs. /// \sa u() /// \sa direction() Node v(Edge) const { return INVALID; } - /// \brief Source node of the directed arc. + /// \brief The source node of the arc. + /// + /// Returns the source node of the given arc. Node source(Arc) const { return INVALID; } - /// \brief Target node of the directed arc. + /// \brief The target node of the arc. + /// + /// Returns the target node of the given arc. Node target(Arc) const { return INVALID; } - /// \brief Returns the id of the node. + /// \brief The ID of the node. + /// + /// Returns the ID of the given node. int id(Node) const { return -1; } - /// \brief Returns the id of the edge. + /// \brief The ID of the edge. + /// + /// Returns the ID of the given edge. int id(Edge) const { return -1; } - /// \brief Returns the id of the arc. + /// \brief The ID of the arc. + /// + /// Returns the ID of the given arc. int id(Arc) const { return -1; } - /// \brief Returns the node with the given id. + /// \brief The node with the given ID. /// - /// \pre The argument should be a valid node id in the graph. + /// Returns the node with the given ID. + /// \pre The argument should be a valid node ID in the graph. Node nodeFromId(int) const { return INVALID; } - /// \brief Returns the edge with the given id. + /// \brief The edge with the given ID. /// - /// \pre The argument should be a valid edge id in the graph. + /// Returns the edge with the given ID. + /// \pre The argument should be a valid edge ID in the graph. Edge edgeFromId(int) const { return INVALID; } - /// \brief Returns the arc with the given id. + /// \brief The arc with the given ID. /// - /// \pre The argument should be a valid arc id in the graph. + /// Returns the arc with the given ID. + /// \pre The argument should be a valid arc ID in the graph. Arc arcFromId(int) const { return INVALID; } - /// \brief Returns an upper bound on the node IDs. + /// \brief An upper bound on the node IDs. + /// + /// Returns an upper bound on the node IDs. int maxNodeId() const { return -1; } - /// \brief Returns an upper bound on the edge IDs. + /// \brief An upper bound on the edge IDs. + /// + /// Returns an upper bound on the edge IDs. int maxEdgeId() const { return -1; } - /// \brief Returns an upper bound on the arc IDs. + /// \brief An upper bound on the arc IDs. + /// + /// Returns an upper bound on the arc IDs. int maxArcId() const { return -1; } + /// \brief The direction of the arc. + /// + /// Returns \c true if the direction of the given arc is the same as + /// the inherent orientation of the represented edge. + bool direction(Arc) const { return true; } + + /// \brief Direct the edge. + /// + /// Direct the given edge. The returned arc + /// represents the given edge and its direction comes + /// from the bool parameter. If it is \c true, then the direction + /// of the arc is the same as the inherent orientation of the edge. + Arc direct(Edge, bool) const { + return INVALID; + } + + /// \brief Direct the edge. + /// + /// Direct the given edge. The returned arc represents the given + /// edge and its source node is the given node. + Arc direct(Edge, Node) const { + return INVALID; + } + + /// \brief The oppositely directed arc. + /// + /// Returns the oppositely directed arc representing the same edge. + Arc oppositeArc(Arc) const { return INVALID; } + + /// \brief The opposite node on the edge. + /// + /// Returns the opposite node on the given edge. + Node oppositeNode(Node, Edge) const { return INVALID; } + void first(Node&) const {} void next(Node&) const {} @@ -705,47 +733,39 @@ // Dummy parameter. int maxId(Arc) const { return -1; } - /// \brief Base node of the iterator + /// \brief The base node of the iterator. /// - /// Returns the base node (the source in this case) of the iterator - Node baseNode(OutArcIt e) const { - return source(e); - } - /// \brief Running node of the iterator + /// Returns the base node of the given incident edge iterator. + Node baseNode(IncEdgeIt) const { return INVALID; } + + /// \brief The running node of the iterator. /// - /// Returns the running node (the target in this case) of the - /// iterator - Node runningNode(OutArcIt e) const { - return target(e); - } + /// Returns the running node of the given incident edge iterator. + Node runningNode(IncEdgeIt) const { return INVALID; } - /// \brief Base node of the iterator + /// \brief The base node of the iterator. /// - /// Returns the base node (the target in this case) of the iterator - Node baseNode(InArcIt e) const { - return target(e); - } - /// \brief Running node of the iterator + /// Returns the base node of the given outgoing arc iterator + /// (i.e. the source node of the corresponding arc). + Node baseNode(OutArcIt) const { return INVALID; } + + /// \brief The running node of the iterator. /// - /// Returns the running node (the source in this case) of the - /// iterator - Node runningNode(InArcIt e) const { - return source(e); - } + /// Returns the running node of the given outgoing arc iterator + /// (i.e. the target node of the corresponding arc). + Node runningNode(OutArcIt) const { return INVALID; } - /// \brief Base node of the iterator + /// \brief The base node of the iterator. /// - /// Returns the base node of the iterator - Node baseNode(IncEdgeIt) const { - return INVALID; - } + /// Returns the base node of the given incomming arc iterator + /// (i.e. the target node of the corresponding arc). + Node baseNode(InArcIt) const { return INVALID; } - /// \brief Running node of the iterator + /// \brief The running node of the iterator. /// - /// Returns the running node of the iterator - Node runningNode(IncEdgeIt) const { - return INVALID; - } + /// Returns the running node of the given incomming arc iterator + /// (i.e. the source node of the corresponding arc). + Node runningNode(InArcIt) const { return INVALID; } template struct Constraints { diff --git a/lemon/concepts/graph_components.h b/lemon/concepts/graph_components.h --- a/lemon/concepts/graph_components.h +++ b/lemon/concepts/graph_components.h @@ -18,7 +18,7 @@ ///\ingroup graph_concepts ///\file -///\brief The concept of graph components. +///\brief The concepts of graph components. #ifndef LEMON_CONCEPTS_GRAPH_COMPONENTS_H #define LEMON_CONCEPTS_GRAPH_COMPONENTS_H @@ -92,7 +92,7 @@ /// It makes possible to use graph item types as key types in /// associative containers (e.g. \c std::map). /// - /// \note This operator only have to define some strict ordering of + /// \note This operator only has to define some strict ordering of /// the items; this order has nothing to do with the iteration /// ordering of the items. bool operator<(const GraphItem&) const { return false; } diff --git a/lemon/concepts/maps.h b/lemon/concepts/maps.h --- a/lemon/concepts/maps.h +++ b/lemon/concepts/maps.h @@ -182,7 +182,8 @@ template struct Constraints { - void constraints() { + typename enable_if::type + constraints() { checkConcept, _ReferenceMap >(); ref = m[key]; m[key] = val; diff --git a/lemon/concepts/path.h b/lemon/concepts/path.h --- a/lemon/concepts/path.h +++ b/lemon/concepts/path.h @@ -18,7 +18,7 @@ ///\ingroup concept ///\file -///\brief Classes for representing paths in digraphs. +///\brief The concept of paths /// #ifndef LEMON_CONCEPTS_PATH_H @@ -38,13 +38,22 @@ /// /// A skeleton structure for representing directed paths in a /// digraph. + /// In a sense, a path can be treated as a list of arcs. + /// LEMON path types just store this list. As a consequence, they cannot + /// enumerate the nodes on the path directly and a zero length path + /// cannot store its source node. + /// + /// The arcs of a path should be stored in the order of their directions, + /// i.e. the target node of each arc should be the same as the source + /// node of the next arc. This consistency could be checked using + /// \ref checkPath(). + /// The source and target nodes of a (consistent) path can be obtained + /// using \ref pathSource() and \ref pathTarget(). + /// + /// A path can be constructed from another path of any type using the + /// copy constructor or the assignment operator. + /// /// \tparam GR The digraph type in which the path is. - /// - /// In a sense, the path can be treated as a list of arcs. The - /// lemon path type stores just this list. As a consequence it - /// cannot enumerate the nodes in the path and the zero length - /// paths cannot store the source. - /// template class Path { public: @@ -59,18 +68,18 @@ /// \brief Default constructor Path() {} - /// \brief Template constructor + /// \brief Template copy constructor template Path(const CPath& cpath) {} - /// \brief Template assigment + /// \brief Template assigment operator template Path& operator=(const CPath& cpath) { ignore_unused_variable_warning(cpath); return *this; } - /// Length of the path ie. the number of arcs in the path. + /// Length of the path, i.e. the number of arcs on the path. int length() const { return 0;} /// Returns whether the path is empty. @@ -79,19 +88,19 @@ /// Resets the path to an empty path. void clear() {} - /// \brief LEMON style iterator for path arcs + /// \brief LEMON style iterator for enumerating the arcs of a path. /// - /// This class is used to iterate on the arcs of the paths. + /// LEMON style iterator class for enumerating the arcs of a path. class ArcIt { public: /// Default constructor ArcIt() {} /// Invalid constructor ArcIt(Invalid) {} - /// Constructor for first arc + /// Sets the iterator to the first arc of the given path ArcIt(const Path &) {} - /// Conversion to Arc + /// Conversion to \c Arc operator Arc() const { return INVALID; } /// Next arc @@ -192,24 +201,18 @@ /// \brief A skeleton structure for path dumpers. /// /// A skeleton structure for path dumpers. The path dumpers are - /// the generalization of the paths. The path dumpers can - /// enumerate the arcs of the path wheter in forward or in - /// backward order. In most time these classes are not used - /// directly rather it used to assign a dumped class to a real - /// path type. + /// the generalization of the paths, they can enumerate the arcs + /// of the path either in forward or in backward order. + /// These classes are typically not used directly, they are rather + /// used to be assigned to a real path type. /// /// The main purpose of this concept is that the shortest path - /// algorithms can enumerate easily the arcs in reverse order. - /// If we would like to give back a real path from these - /// algorithms then we should create a temporarly path object. In - /// LEMON such algorithms gives back a path dumper what can - /// assigned to a real path and the dumpers can be implemented as + /// algorithms can enumerate the arcs easily in reverse order. + /// In LEMON, such algorithms give back a (reverse) path dumper that + /// can be assigned to a real path. The dumpers can be implemented as /// an adaptor class to the predecessor map. /// /// \tparam GR The digraph type in which the path is. - /// - /// The paths can be constructed from any path type by a - /// template constructor or a template assignment operator. template class PathDumper { public: @@ -219,7 +222,7 @@ /// Arc type of the underlying digraph. typedef typename Digraph::Arc Arc; - /// Length of the path ie. the number of arcs in the path. + /// Length of the path, i.e. the number of arcs on the path. int length() const { return 0;} /// Returns whether the path is empty. @@ -227,25 +230,24 @@ /// \brief Forward or reverse dumping /// - /// If the RevPathTag is defined and true then reverse dumping - /// is provided in the path dumper. In this case instead of the - /// ArcIt the RevArcIt iterator should be implemented in the - /// dumper. + /// If this tag is defined to be \c True, then reverse dumping + /// is provided in the path dumper. In this case, \c RevArcIt + /// iterator should be implemented instead of \c ArcIt iterator. typedef False RevPathTag; - /// \brief LEMON style iterator for path arcs + /// \brief LEMON style iterator for enumerating the arcs of a path. /// - /// This class is used to iterate on the arcs of the paths. + /// LEMON style iterator class for enumerating the arcs of a path. class ArcIt { public: /// Default constructor ArcIt() {} /// Invalid constructor ArcIt(Invalid) {} - /// Constructor for first arc + /// Sets the iterator to the first arc of the given path ArcIt(const PathDumper&) {} - /// Conversion to Arc + /// Conversion to \c Arc operator Arc() const { return INVALID; } /// Next arc @@ -260,20 +262,21 @@ }; - /// \brief LEMON style iterator for path arcs + /// \brief LEMON style iterator for enumerating the arcs of a path + /// in reverse direction. /// - /// This class is used to iterate on the arcs of the paths in - /// reverse direction. + /// LEMON style iterator class for enumerating the arcs of a path + /// in reverse direction. class RevArcIt { public: /// Default constructor RevArcIt() {} /// Invalid constructor RevArcIt(Invalid) {} - /// Constructor for first arc + /// Sets the iterator to the last arc of the given path RevArcIt(const PathDumper &) {} - /// Conversion to Arc + /// Conversion to \c Arc operator Arc() const { return INVALID; } /// Next arc diff --git a/lemon/counter.h b/lemon/counter.h --- a/lemon/counter.h +++ b/lemon/counter.h @@ -212,7 +212,7 @@ /// 'Do nothing' version of Counter. - /// This class can be used in the same way as \ref Counter however it + /// This class can be used in the same way as \ref Counter, but it /// does not count at all and does not print report on destruction. /// /// Replacing a \ref Counter with a \ref NoCounter makes it possible diff --git a/lemon/cplex.cc b/lemon/cplex.cc --- a/lemon/cplex.cc +++ b/lemon/cplex.cc @@ -111,6 +111,39 @@ return i; } + int CplexBase::_addRow(Value lb, ExprIterator b, + ExprIterator e, Value ub) { + int i = CPXgetnumrows(cplexEnv(), _prob); + if (lb == -INF) { + const char s = 'L'; + CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0); + } else if (ub == INF) { + const char s = 'G'; + CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, 0, 0); + } else if (lb == ub){ + const char s = 'E'; + CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, 0, 0); + } else { + const char s = 'R'; + double len = ub - lb; + CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, &len, 0); + } + + std::vector indices; + std::vector rowlist; + std::vector values; + + for(ExprIterator it=b; it!=e; ++it) { + indices.push_back(it->first); + values.push_back(it->second); + rowlist.push_back(i); + } + + CPXchgcoeflist(cplexEnv(), _prob, values.size(), + &rowlist.front(), &indices.front(), &values.front()); + + return i; + } void CplexBase::_eraseCol(int i) { CPXdelcols(cplexEnv(), _prob, i, i); diff --git a/lemon/cplex.h b/lemon/cplex.h --- a/lemon/cplex.h +++ b/lemon/cplex.h @@ -93,6 +93,7 @@ virtual int _addCol(); virtual int _addRow(); + virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u); virtual void _eraseCol(int i); virtual void _eraseRow(int i); diff --git a/lemon/dfs.h b/lemon/dfs.h --- a/lemon/dfs.h +++ b/lemon/dfs.h @@ -47,7 +47,7 @@ /// ///The type of the map that stores the predecessor ///arcs of the %DFS paths. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. typedef typename Digraph::template NodeMap PredMap; ///Instantiates a \c PredMap. @@ -62,7 +62,8 @@ ///The type of the map that indicates which nodes are processed. ///The type of the map that indicates which nodes are processed. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. + ///By default, it is a NullMap. typedef NullMap ProcessedMap; ///Instantiates a \c ProcessedMap. @@ -81,7 +82,7 @@ ///The type of the map that indicates which nodes are reached. ///The type of the map that indicates which nodes are reached. - ///It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept. + ///It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap" concept. typedef typename Digraph::template NodeMap ReachedMap; ///Instantiates a \c ReachedMap. @@ -96,7 +97,7 @@ ///The type of the map that stores the distances of the nodes. ///The type of the map that stores the distances of the nodes. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. typedef typename Digraph::template NodeMap DistMap; ///Instantiates a \c DistMap. @@ -224,7 +225,7 @@ /// ///\ref named-templ-param "Named parameter" for setting ///\c PredMap type. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. template struct SetPredMap : public Dfs > { typedef Dfs > Create; @@ -244,7 +245,7 @@ /// ///\ref named-templ-param "Named parameter" for setting ///\c DistMap type. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. template struct SetDistMap : public Dfs< Digraph, SetDistMapTraits > { typedef Dfs > Create; @@ -264,7 +265,7 @@ /// ///\ref named-templ-param "Named parameter" for setting ///\c ReachedMap type. - ///It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept. + ///It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap" concept. template struct SetReachedMap : public Dfs< Digraph, SetReachedMapTraits > { typedef Dfs< Digraph, SetReachedMapTraits > Create; @@ -284,7 +285,7 @@ /// ///\ref named-templ-param "Named parameter" for setting ///\c ProcessedMap type. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. template struct SetProcessedMap : public Dfs< Digraph, SetProcessedMapTraits > { typedef Dfs< Digraph, SetProcessedMapTraits > Create; @@ -411,8 +412,8 @@ ///\name Execution Control ///The simplest way to execute the DFS algorithm is to use one of the ///member functions called \ref run(Node) "run()".\n - ///If you need more control on the execution, first you have to call - ///\ref init(), then you can add a source node with \ref addSource() + ///If you need better control on the execution, you have to call + ///\ref init() first, then you can add a source node with \ref addSource() ///and perform the actual computation with \ref start(). ///This procedure can be repeated if there are nodes that have not ///been reached. @@ -632,12 +633,8 @@ ///Runs the algorithm to visit all nodes in the digraph. - ///This method runs the %DFS algorithm in order to compute the - ///%DFS path to each node. - /// - ///The algorithm computes - ///- the %DFS tree (forest), - ///- the distance of each node from the root(s) in the %DFS tree. + ///This method runs the %DFS algorithm in order to visit all nodes + ///in the digraph. /// ///\note d.run() is just a shortcut of the following code. ///\code @@ -669,9 +666,9 @@ ///@{ - ///The DFS path to a node. + ///The DFS path to the given node. - ///Returns the DFS path to a node. + ///Returns the DFS path to the given node from the root(s). /// ///\warning \c t should be reached from the root(s). /// @@ -679,9 +676,9 @@ ///must be called before using this function. Path path(Node t) const { return Path(*G, *_pred, t); } - ///The distance of a node from the root(s). + ///The distance of the given node from the root(s). - ///Returns the distance of a node from the root(s). + ///Returns the distance of the given node from the root(s). /// ///\warning If node \c v is not reached from the root(s), then ///the return value of this function is undefined. @@ -690,7 +687,7 @@ ///must be called before using this function. int dist(Node v) const { return (*_dist)[v]; } - ///Returns the 'previous arc' of the %DFS tree for a node. + ///Returns the 'previous arc' of the %DFS tree for the given node. ///This function returns the 'previous arc' of the %DFS tree for the ///node \c v, i.e. it returns the last arc of a %DFS path from a @@ -698,21 +695,21 @@ ///root(s) or if \c v is a root. /// ///The %DFS tree used here is equal to the %DFS tree used in - ///\ref predNode(). + ///\ref predNode() and \ref predMap(). /// ///\pre Either \ref run(Node) "run()" or \ref init() ///must be called before using this function. Arc predArc(Node v) const { return (*_pred)[v];} - ///Returns the 'previous node' of the %DFS tree. + ///Returns the 'previous node' of the %DFS tree for the given node. ///This function returns the 'previous node' of the %DFS ///tree for the node \c v, i.e. it returns the last but one node - ///from a %DFS path from a root to \c v. It is \c INVALID + ///of a %DFS path from a root to \c v. It is \c INVALID ///if \c v is not reached from the root(s) or if \c v is a root. /// ///The %DFS tree used here is equal to the %DFS tree used in - ///\ref predArc(). + ///\ref predArc() and \ref predMap(). /// ///\pre Either \ref run(Node) "run()" or \ref init() ///must be called before using this function. @@ -733,13 +730,13 @@ ///predecessor arcs. /// ///Returns a const reference to the node map that stores the predecessor - ///arcs, which form the DFS tree. + ///arcs, which form the DFS tree (forest). /// ///\pre Either \ref run(Node) "run()" or \ref init() ///must be called before using this function. const PredMap &predMap() const { return *_pred;} - ///Checks if a node is reached from the root(s). + ///Checks if the given node. node is reached from the root(s). ///Returns \c true if \c v is reached from the root(s). /// @@ -765,7 +762,7 @@ /// ///The type of the map that stores the predecessor ///arcs of the %DFS paths. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. typedef typename Digraph::template NodeMap PredMap; ///Instantiates a PredMap. @@ -780,8 +777,8 @@ ///The type of the map that indicates which nodes are processed. ///The type of the map that indicates which nodes are processed. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. - ///By default it is a NullMap. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. + ///By default, it is a NullMap. typedef NullMap ProcessedMap; ///Instantiates a ProcessedMap. @@ -800,7 +797,7 @@ ///The type of the map that indicates which nodes are reached. ///The type of the map that indicates which nodes are reached. - ///It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept. + ///It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap" concept. typedef typename Digraph::template NodeMap ReachedMap; ///Instantiates a ReachedMap. @@ -815,7 +812,7 @@ ///The type of the map that stores the distances of the nodes. ///The type of the map that stores the distances of the nodes. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. typedef typename Digraph::template NodeMap DistMap; ///Instantiates a DistMap. @@ -830,18 +827,14 @@ ///The type of the DFS paths. ///The type of the DFS paths. - ///It must meet the \ref concepts::Path "Path" concept. + ///It must conform to the \ref concepts::Path "Path" concept. typedef lemon::Path Path; }; /// Default traits class used by DfsWizard - /// To make it easier to use Dfs algorithm - /// we have created a wizard class. - /// This \ref DfsWizard class needs default traits, - /// as well as the \ref Dfs class. - /// The \ref DfsWizardBase is a class to be the default traits of the - /// \ref DfsWizard class. + /// Default traits class used by DfsWizard. + /// \tparam GR The type of the digraph. template class DfsWizardBase : public DfsWizardDefaultTraits { @@ -869,7 +862,7 @@ public: /// Constructor. - /// This constructor does not require parameters, therefore it initiates + /// This constructor does not require parameters, it initiates /// all of the attributes to \c 0. DfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0), _dist(0), _path(0), _di(0) {} @@ -899,7 +892,6 @@ { typedef TR Base; - ///The type of the digraph the algorithm runs on. typedef typename TR::Digraph Digraph; typedef typename Digraph::Node Node; @@ -907,16 +899,10 @@ typedef typename Digraph::Arc Arc; typedef typename Digraph::OutArcIt OutArcIt; - ///\brief The type of the map that stores the predecessor - ///arcs of the DFS paths. typedef typename TR::PredMap PredMap; - ///\brief The type of the map that stores the distances of the nodes. typedef typename TR::DistMap DistMap; - ///\brief The type of the map that indicates which nodes are reached. typedef typename TR::ReachedMap ReachedMap; - ///\brief The type of the map that indicates which nodes are processed. typedef typename TR::ProcessedMap ProcessedMap; - ///The type of the DFS paths typedef typename TR::Path Path; public: @@ -986,8 +972,8 @@ ///Runs DFS algorithm to visit all nodes in the digraph. - ///This method runs DFS algorithm in order to compute - ///the DFS path to each node. + ///This method runs DFS algorithm in order to visit all nodes + ///in the digraph. void run() { run(INVALID); @@ -999,11 +985,12 @@ static PredMap *createPredMap(const Digraph &) { return 0; }; SetPredMapBase(const TR &b) : TR(b) {} }; - ///\brief \ref named-func-param "Named parameter" - ///for setting PredMap object. + + ///\brief \ref named-templ-param "Named parameter" for setting + ///the predecessor map. /// - ///\ref named-func-param "Named parameter" - ///for setting PredMap object. + ///\ref named-templ-param "Named parameter" function for setting + ///the map that stores the predecessor arcs of the nodes. template DfsWizard > predMap(const T &t) { @@ -1017,11 +1004,12 @@ static ReachedMap *createReachedMap(const Digraph &) { return 0; }; SetReachedMapBase(const TR &b) : TR(b) {} }; - ///\brief \ref named-func-param "Named parameter" - ///for setting ReachedMap object. + + ///\brief \ref named-templ-param "Named parameter" for setting + ///the reached map. /// - /// \ref named-func-param "Named parameter" - ///for setting ReachedMap object. + ///\ref named-templ-param "Named parameter" function for setting + ///the map that indicates which nodes are reached. template DfsWizard > reachedMap(const T &t) { @@ -1035,11 +1023,13 @@ static DistMap *createDistMap(const Digraph &) { return 0; }; SetDistMapBase(const TR &b) : TR(b) {} }; - ///\brief \ref named-func-param "Named parameter" - ///for setting DistMap object. + + ///\brief \ref named-templ-param "Named parameter" for setting + ///the distance map. /// - /// \ref named-func-param "Named parameter" - ///for setting DistMap object. + ///\ref named-templ-param "Named parameter" function for setting + ///the map that stores the distances of the nodes calculated + ///by the algorithm. template DfsWizard > distMap(const T &t) { @@ -1053,11 +1043,12 @@ static ProcessedMap *createProcessedMap(const Digraph &) { return 0; }; SetProcessedMapBase(const TR &b) : TR(b) {} }; - ///\brief \ref named-func-param "Named parameter" - ///for setting ProcessedMap object. + + ///\brief \ref named-func-param "Named parameter" for setting + ///the processed map. /// - /// \ref named-func-param "Named parameter" - ///for setting ProcessedMap object. + ///\ref named-templ-param "Named parameter" function for setting + ///the map that indicates which nodes are processed. template DfsWizard > processedMap(const T &t) { @@ -1208,7 +1199,7 @@ /// \brief The type of the map that indicates which nodes are reached. /// /// The type of the map that indicates which nodes are reached. - /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept. + /// It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap" concept. typedef typename Digraph::template NodeMap ReachedMap; /// \brief Instantiates a ReachedMap. @@ -1369,8 +1360,8 @@ /// \name Execution Control /// The simplest way to execute the DFS algorithm is to use one of the /// member functions called \ref run(Node) "run()".\n - /// If you need more control on the execution, first you have to call - /// \ref init(), then you can add a source node with \ref addSource() + /// If you need better control on the execution, you have to call + /// \ref init() first, then you can add a source node with \ref addSource() /// and perform the actual computation with \ref start(). /// This procedure can be repeated if there are nodes that have not /// been reached. @@ -1583,12 +1574,8 @@ /// \brief Runs the algorithm to visit all nodes in the digraph. - /// This method runs the %DFS algorithm in order to - /// compute the %DFS path to each node. - /// - /// The algorithm computes - /// - the %DFS tree (forest), - /// - the distance of each node from the root(s) in the %DFS tree. + /// This method runs the %DFS algorithm in order to visit all nodes + /// in the digraph. /// /// \note d.run() is just a shortcut of the following code. ///\code @@ -1620,7 +1607,7 @@ ///@{ - /// \brief Checks if a node is reached from the root(s). + /// \brief Checks if the given node is reached from the root(s). /// /// Returns \c true if \c v is reached from the root(s). /// diff --git a/lemon/dijkstra.h b/lemon/dijkstra.h --- a/lemon/dijkstra.h +++ b/lemon/dijkstra.h @@ -70,9 +70,9 @@ ///The type of the map that stores the arc lengths. ///The type of the map that stores the arc lengths. - ///It must meet the \ref concepts::ReadMap "ReadMap" concept. + ///It must conform to the \ref concepts::ReadMap "ReadMap" concept. typedef LEN LengthMap; - ///The type of the length of the arcs. + ///The type of the arc lengths. typedef typename LEN::Value Value; /// Operation traits for %Dijkstra algorithm. @@ -116,7 +116,7 @@ /// ///The type of the map that stores the predecessor ///arcs of the shortest paths. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. typedef typename Digraph::template NodeMap PredMap; ///Instantiates a \c PredMap. @@ -131,8 +131,8 @@ ///The type of the map that indicates which nodes are processed. ///The type of the map that indicates which nodes are processed. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. - ///By default it is a NullMap. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. + ///By default, it is a NullMap. typedef NullMap ProcessedMap; ///Instantiates a \c ProcessedMap. @@ -151,7 +151,7 @@ ///The type of the map that stores the distances of the nodes. ///The type of the map that stores the distances of the nodes. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. typedef typename Digraph::template NodeMap DistMap; ///Instantiates a \c DistMap. @@ -169,6 +169,10 @@ /// \ingroup shortest_path ///This class provides an efficient implementation of the %Dijkstra algorithm. /// + ///The %Dijkstra algorithm solves the single-source shortest path problem + ///when all arc lengths are non-negative. If there are negative lengths, + ///the BellmanFord algorithm should be used instead. + /// ///The arc lengths are passed to the algorithm using a ///\ref concepts::ReadMap "ReadMap", ///so it is easy to change it to any kind of length. @@ -201,8 +205,8 @@ ///The type of the digraph the algorithm runs on. typedef typename TR::Digraph Digraph; - ///The type of the length of the arcs. - typedef typename TR::LengthMap::Value Value; + ///The type of the arc lengths. + typedef typename TR::Value Value; ///The type of the map that stores the arc lengths. typedef typename TR::LengthMap LengthMap; ///\brief The type of the map that stores the predecessor arcs of the @@ -304,7 +308,7 @@ /// ///\ref named-templ-param "Named parameter" for setting ///\c PredMap type. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. template struct SetPredMap : public Dijkstra< Digraph, LengthMap, SetPredMapTraits > { @@ -325,7 +329,7 @@ /// ///\ref named-templ-param "Named parameter" for setting ///\c DistMap type. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. template struct SetDistMap : public Dijkstra< Digraph, LengthMap, SetDistMapTraits > { @@ -346,7 +350,7 @@ /// ///\ref named-templ-param "Named parameter" for setting ///\c ProcessedMap type. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. template struct SetProcessedMap : public Dijkstra< Digraph, LengthMap, SetProcessedMapTraits > { @@ -422,7 +426,7 @@ ///automatically created by the algorithm (i.e. the digraph should be ///passed to the constructor of the cross reference and the cross ///reference should be passed to the constructor of the heap). - ///However external heap and cross reference objects could also be + ///However, external heap and cross reference objects could also be ///passed to the algorithm using the \ref heap() function before ///calling \ref run(Node) "run()" or \ref init(). ///\sa SetHeap @@ -443,6 +447,7 @@ /// ///\ref named-templ-param "Named parameter" for setting ///\c OperationTraits type. + /// For more information, see \ref DijkstraDefaultOperationTraits. template struct SetOperationTraits : public Dijkstra > { @@ -584,8 +589,8 @@ ///\name Execution Control ///The simplest way to execute the %Dijkstra algorithm is to use ///one of the member functions called \ref run(Node) "run()".\n - ///If you need more control on the execution, first you have to call - ///\ref init(), then you can add several source nodes with + ///If you need better control on the execution, you have to call + ///\ref init() first, then you can add several source nodes with ///\ref addSource(). Finally the actual path computation can be ///performed with one of the \ref start() functions. @@ -801,14 +806,14 @@ ///\name Query Functions ///The results of the %Dijkstra algorithm can be obtained using these ///functions.\n - ///Either \ref run(Node) "run()" or \ref start() should be called + ///Either \ref run(Node) "run()" or \ref init() should be called ///before using them. ///@{ - ///The shortest path to a node. + ///The shortest path to the given node. - ///Returns the shortest path to a node. + ///Returns the shortest path to the given node from the root(s). /// ///\warning \c t should be reached from the root(s). /// @@ -816,9 +821,9 @@ ///must be called before using this function. Path path(Node t) const { return Path(*G, *_pred, t); } - ///The distance of a node from the root(s). + ///The distance of the given node from the root(s). - ///Returns the distance of a node from the root(s). + ///Returns the distance of the given node from the root(s). /// ///\warning If node \c v is not reached from the root(s), then ///the return value of this function is undefined. @@ -827,29 +832,31 @@ ///must be called before using this function. Value dist(Node v) const { return (*_dist)[v]; } - ///Returns the 'previous arc' of the shortest path tree for a node. - + ///\brief Returns the 'previous arc' of the shortest path tree for + ///the given node. + /// ///This function returns the 'previous arc' of the shortest path ///tree for the node \c v, i.e. it returns the last arc of a ///shortest path from a root to \c v. It is \c INVALID if \c v ///is not reached from the root(s) or if \c v is a root. /// ///The shortest path tree used here is equal to the shortest path - ///tree used in \ref predNode(). + ///tree used in \ref predNode() and \ref predMap(). /// ///\pre Either \ref run(Node) "run()" or \ref init() ///must be called before using this function. Arc predArc(Node v) const { return (*_pred)[v]; } - ///Returns the 'previous node' of the shortest path tree for a node. - + ///\brief Returns the 'previous node' of the shortest path tree for + ///the given node. + /// ///This function returns the 'previous node' of the shortest path ///tree for the node \c v, i.e. it returns the last but one node - ///from a shortest path from a root to \c v. It is \c INVALID + ///of a shortest path from a root to \c v. It is \c INVALID ///if \c v is not reached from the root(s) or if \c v is a root. /// ///The shortest path tree used here is equal to the shortest path - ///tree used in \ref predArc(). + ///tree used in \ref predArc() and \ref predMap(). /// ///\pre Either \ref run(Node) "run()" or \ref init() ///must be called before using this function. @@ -870,13 +877,13 @@ ///predecessor arcs. /// ///Returns a const reference to the node map that stores the predecessor - ///arcs, which form the shortest path tree. + ///arcs, which form the shortest path tree (forest). /// ///\pre Either \ref run(Node) "run()" or \ref init() ///must be called before using this function. const PredMap &predMap() const { return *_pred;} - ///Checks if a node is reached from the root(s). + ///Checks if the given node is reached from the root(s). ///Returns \c true if \c v is reached from the root(s). /// @@ -895,9 +902,9 @@ bool processed(Node v) const { return (*_heap_cross_ref)[v] == Heap::POST_HEAP; } - ///The current distance of a node from the root(s). + ///The current distance of the given node from the root(s). - ///Returns the current distance of a node from the root(s). + ///Returns the current distance of the given node from the root(s). ///It may be decreased in the following processes. /// ///\pre Either \ref run(Node) "run()" or \ref init() @@ -924,9 +931,9 @@ ///The type of the map that stores the arc lengths. ///The type of the map that stores the arc lengths. - ///It must meet the \ref concepts::ReadMap "ReadMap" concept. + ///It must conform to the \ref concepts::ReadMap "ReadMap" concept. typedef LEN LengthMap; - ///The type of the length of the arcs. + ///The type of the arc lengths. typedef typename LEN::Value Value; /// Operation traits for Dijkstra algorithm. @@ -973,7 +980,7 @@ /// ///The type of the map that stores the predecessor ///arcs of the shortest paths. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. typedef typename Digraph::template NodeMap PredMap; ///Instantiates a PredMap. @@ -988,8 +995,8 @@ ///The type of the map that indicates which nodes are processed. ///The type of the map that indicates which nodes are processed. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. - ///By default it is a NullMap. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. + ///By default, it is a NullMap. typedef NullMap ProcessedMap; ///Instantiates a ProcessedMap. @@ -1008,7 +1015,7 @@ ///The type of the map that stores the distances of the nodes. ///The type of the map that stores the distances of the nodes. - ///It must meet the \ref concepts::WriteMap "WriteMap" concept. + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept. typedef typename Digraph::template NodeMap DistMap; ///Instantiates a DistMap. @@ -1023,18 +1030,15 @@ ///The type of the shortest paths. ///The type of the shortest paths. - ///It must meet the \ref concepts::Path "Path" concept. + ///It must conform to the \ref concepts::Path "Path" concept. typedef lemon::Path Path; }; /// Default traits class used by DijkstraWizard - /// To make it easier to use Dijkstra algorithm - /// we have created a wizard class. - /// This \ref DijkstraWizard class needs default traits, - /// as well as the \ref Dijkstra class. - /// The \ref DijkstraWizardBase is a class to be the default traits of the - /// \ref DijkstraWizard class. + /// Default traits class used by DijkstraWizard. + /// \tparam GR The type of the digraph. + /// \tparam LEN The type of the length map. template class DijkstraWizardBase : public DijkstraWizardDefaultTraits { @@ -1093,7 +1097,6 @@ { typedef TR Base; - ///The type of the digraph the algorithm runs on. typedef typename TR::Digraph Digraph; typedef typename Digraph::Node Node; @@ -1101,20 +1104,12 @@ typedef typename Digraph::Arc Arc; typedef typename Digraph::OutArcIt OutArcIt; - ///The type of the map that stores the arc lengths. typedef typename TR::LengthMap LengthMap; - ///The type of the length of the arcs. typedef typename LengthMap::Value Value; - ///\brief The type of the map that stores the predecessor - ///arcs of the shortest paths. typedef typename TR::PredMap PredMap; - ///The type of the map that stores the distances of the nodes. typedef typename TR::DistMap DistMap; - ///The type of the map that indicates which nodes are processed. typedef typename TR::ProcessedMap ProcessedMap; - ///The type of the shortest paths typedef typename TR::Path Path; - ///The heap type used by the dijkstra algorithm. typedef typename TR::Heap Heap; public: @@ -1186,11 +1181,12 @@ static PredMap *createPredMap(const Digraph &) { return 0; }; SetPredMapBase(const TR &b) : TR(b) {} }; - ///\brief \ref named-func-param "Named parameter" - ///for setting PredMap object. + + ///\brief \ref named-templ-param "Named parameter" for setting + ///the predecessor map. /// - ///\ref named-func-param "Named parameter" - ///for setting PredMap object. + ///\ref named-templ-param "Named parameter" function for setting + ///the map that stores the predecessor arcs of the nodes. template DijkstraWizard > predMap(const T &t) { @@ -1204,11 +1200,13 @@ static DistMap *createDistMap(const Digraph &) { return 0; }; SetDistMapBase(const TR &b) : TR(b) {} }; - ///\brief \ref named-func-param "Named parameter" - ///for setting DistMap object. + + ///\brief \ref named-templ-param "Named parameter" for setting + ///the distance map. /// - ///\ref named-func-param "Named parameter" - ///for setting DistMap object. + ///\ref named-templ-param "Named parameter" function for setting + ///the map that stores the distances of the nodes calculated + ///by the algorithm. template DijkstraWizard > distMap(const T &t) { @@ -1222,11 +1220,12 @@ static ProcessedMap *createProcessedMap(const Digraph &) { return 0; }; SetProcessedMapBase(const TR &b) : TR(b) {} }; - ///\brief \ref named-func-param "Named parameter" - ///for setting ProcessedMap object. + + ///\brief \ref named-func-param "Named parameter" for setting + ///the processed map. /// - /// \ref named-func-param "Named parameter" - ///for setting ProcessedMap object. + ///\ref named-templ-param "Named parameter" function for setting + ///the map that indicates which nodes are processed. template DijkstraWizard > processedMap(const T &t) { @@ -1239,6 +1238,7 @@ typedef T Path; SetPathBase(const TR &b) : TR(b) {} }; + ///\brief \ref named-func-param "Named parameter" ///for getting the shortest path to the target node. /// diff --git a/lemon/dim2.h b/lemon/dim2.h --- a/lemon/dim2.h +++ b/lemon/dim2.h @@ -21,16 +21,9 @@ #include -///\ingroup misc +///\ingroup geomdat ///\file ///\brief A simple two dimensional vector and a bounding box implementation -/// -/// The class \ref lemon::dim2::Point "dim2::Point" implements -/// a two dimensional vector with the usual operations. -/// -/// The class \ref lemon::dim2::Box "dim2::Box" can be used to determine -/// the rectangular bounding box of a set of -/// \ref lemon::dim2::Point "dim2::Point"'s. namespace lemon { @@ -40,7 +33,7 @@ ///tools for handling two dimensional coordinates namespace dim2 { - /// \addtogroup misc + /// \addtogroup geomdat /// @{ /// Two dimensional vector (plain vector) diff --git a/lemon/edge_set.h b/lemon/edge_set.h --- a/lemon/edge_set.h +++ b/lemon/edge_set.h @@ -255,13 +255,14 @@ /// that node can be removed from the underlying graph, in this case /// all arcs incident to the given node is erased from the arc set. /// + /// This class fully conforms to the \ref concepts::Digraph + /// "Digraph" concept. + /// It provides only linear time counting for nodes and arcs. + /// /// \param GR The type of the graph which shares its node set with /// this class. Its interface must conform to the /// \ref concepts::Digraph "Digraph" or \ref concepts::Graph "Graph" /// concept. - /// - /// This class fully conforms to the \ref concepts::Digraph - /// "Digraph" concept. template class ListArcSet : public ArcSetExtender > { typedef ArcSetExtender > Parent; @@ -685,13 +686,14 @@ /// be removed from the underlying graph, in this case all edges /// incident to the given node is erased from the arc set. /// + /// This class fully conforms to the \ref concepts::Graph "Graph" + /// concept. + /// It provides only linear time counting for nodes, edges and arcs. + /// /// \param GR The type of the graph which shares its node set /// with this class. Its interface must conform to the /// \ref concepts::Digraph "Digraph" or \ref concepts::Graph "Graph" /// concept. - /// - /// This class fully conforms to the \ref concepts::Graph "Graph" - /// concept. template class ListEdgeSet : public EdgeSetExtender > { typedef EdgeSetExtender > Parent; @@ -867,7 +869,7 @@ arc.id = arcs.size() - 1; } - void next(Arc& arc) const { + static void next(Arc& arc) { --arc.id; } @@ -954,13 +956,14 @@ /// single-linked lists for enumerate outgoing and incoming /// arcs. Therefore the arcs cannot be erased from the arc sets. /// + /// This class fully conforms to the \ref concepts::Digraph "Digraph" + /// concept. + /// It provides only linear time counting for nodes and arcs. + /// /// \warning If a node is erased from the underlying graph and this /// node is the source or target of one arc in the arc set, then /// the arc set is invalidated, and it cannot be used anymore. The /// validity can be checked with the \c valid() member function. - /// - /// This class fully conforms to the \ref concepts::Digraph - /// "Digraph" concept. template class SmartArcSet : public ArcSetExtender > { typedef ArcSetExtender > Parent; @@ -1173,7 +1176,7 @@ arc.id = arcs.size() - 1; } - void next(Arc& arc) const { + static void next(Arc& arc) { --arc.id; } @@ -1181,7 +1184,7 @@ arc.id = arcs.size() / 2 - 1; } - void next(Edge& arc) const { + static void next(Edge& arc) { --arc.id; } @@ -1304,13 +1307,14 @@ /// single-linked lists for enumerate incident edges. Therefore the /// edges cannot be erased from the edge sets. /// + /// This class fully conforms to the \ref concepts::Graph "Graph" + /// concept. + /// It provides only linear time counting for nodes, edges and arcs. + /// /// \warning If a node is erased from the underlying graph and this /// node is incident to one edge in the edge set, then the edge set /// is invalidated, and it cannot be used anymore. The validity can /// be checked with the \c valid() member function. - /// - /// This class fully conforms to the \ref concepts::Graph - /// "Graph" concept. template class SmartEdgeSet : public EdgeSetExtender > { typedef EdgeSetExtender > Parent; diff --git a/lemon/full_graph.h b/lemon/full_graph.h --- a/lemon/full_graph.h +++ b/lemon/full_graph.h @@ -24,7 +24,7 @@ ///\ingroup graphs ///\file -///\brief FullGraph and FullDigraph classes. +///\brief FullDigraph and FullGraph classes. namespace lemon { @@ -51,7 +51,7 @@ typedef True ArcNumTag; Node operator()(int ix) const { return Node(ix); } - int index(const Node& node) const { return node._id; } + static int index(const Node& node) { return node._id; } Arc arc(const Node& s, const Node& t) const { return Arc(s._id * _node_num + t._id); @@ -148,24 +148,28 @@ /// \ingroup graphs /// - /// \brief A full digraph class. + /// \brief A directed full graph class. /// - /// This is a simple and fast directed full graph implementation. - /// From each node go arcs to each node (including the source node), - /// therefore the number of the arcs in the digraph is the square of - /// the node number. This digraph type is completely static, so you - /// can neither add nor delete either arcs or nodes, and it needs - /// constant space in memory. + /// FullDigraph is a simple and fast implmenetation of directed full + /// (complete) graphs. It contains an arc from each node to each node + /// (including a loop for each node), therefore the number of arcs + /// is the square of the number of nodes. + /// This class is completely static and it needs constant memory space. + /// Thus you can neither add nor delete nodes or arcs, however + /// the structure can be resized using resize(). /// - /// This class fully conforms to the \ref concepts::Digraph - /// "Digraph concept". + /// This type fully conforms to the \ref concepts::Digraph "Digraph concept". + /// Most of its member functions and nested classes are documented + /// only in the concept class. /// - /// The \c FullDigraph and \c FullGraph classes are very similar, + /// This class provides constant time counting for nodes and arcs. + /// + /// \note FullDigraph and FullGraph classes are very similar, /// but there are two differences. While this class conforms only - /// to the \ref concepts::Digraph "Digraph" concept, the \c FullGraph - /// class conforms to the \ref concepts::Graph "Graph" concept, - /// moreover \c FullGraph does not contain a loop arc for each - /// node as \c FullDigraph does. + /// to the \ref concepts::Digraph "Digraph" concept, FullGraph + /// conforms to the \ref concepts::Graph "Graph" concept, + /// moreover FullGraph does not contain a loop for each + /// node as this class does. /// /// \sa FullGraph class FullDigraph : public ExtendedFullDigraphBase { @@ -173,7 +177,9 @@ public: - /// \brief Constructor + /// \brief Default constructor. + /// + /// Default constructor. The number of nodes and arcs will be zero. FullDigraph() { construct(0); } /// \brief Constructor @@ -184,8 +190,8 @@ /// \brief Resizes the digraph /// - /// Resizes the digraph. The function will fully destroy and - /// rebuild the digraph. This cause that the maps of the digraph will + /// This function resizes the digraph. It fully destroys and + /// rebuilds the structure, therefore the maps of the digraph will be /// reallocated automatically and the previous values will be lost. void resize(int n) { Parent::notifier(Arc()).clear(); @@ -197,24 +203,26 @@ /// \brief Returns the node with the given index. /// - /// Returns the node with the given index. Since it is a static - /// digraph its nodes can be indexed with integers from the range - /// [0..nodeNum()-1]. + /// Returns the node with the given index. Since this structure is + /// completely static, the nodes can be indexed with integers from + /// the range [0..nodeNum()-1]. + /// The index of a node is the same as its ID. /// \sa index() Node operator()(int ix) const { return Parent::operator()(ix); } /// \brief Returns the index of the given node. /// - /// Returns the index of the given node. Since it is a static - /// digraph its nodes can be indexed with integers from the range - /// [0..nodeNum()-1]. - /// \sa operator() - int index(const Node& node) const { return Parent::index(node); } + /// Returns the index of the given node. Since this structure is + /// completely static, the nodes can be indexed with integers from + /// the range [0..nodeNum()-1]. + /// The index of a node is the same as its ID. + /// \sa operator()() + static int index(const Node& node) { return Parent::index(node); } /// \brief Returns the arc connecting the given nodes. /// /// Returns the arc connecting the given nodes. - Arc arc(const Node& u, const Node& v) const { + Arc arc(Node u, Node v) const { return Parent::arc(u, v); } @@ -283,7 +291,7 @@ public: Node operator()(int ix) const { return Node(ix); } - int index(const Node& node) const { return node._id; } + static int index(const Node& node) { return node._id; } Edge edge(const Node& u, const Node& v) const { if (u._id < v._id) { @@ -520,21 +528,25 @@ /// /// \brief An undirected full graph class. /// - /// This is a simple and fast undirected full graph - /// implementation. From each node go edge to each other node, - /// therefore the number of edges in the graph is \f$n(n-1)/2\f$. - /// This graph type is completely static, so you can neither - /// add nor delete either edges or nodes, and it needs constant - /// space in memory. + /// FullGraph is a simple and fast implmenetation of undirected full + /// (complete) graphs. It contains an edge between every distinct pair + /// of nodes, therefore the number of edges is n(n-1)/2. + /// This class is completely static and it needs constant memory space. + /// Thus you can neither add nor delete nodes or edges, however + /// the structure can be resized using resize(). /// - /// This class fully conforms to the \ref concepts::Graph "Graph concept". + /// This type fully conforms to the \ref concepts::Graph "Graph concept". + /// Most of its member functions and nested classes are documented + /// only in the concept class. /// - /// The \c FullGraph and \c FullDigraph classes are very similar, - /// but there are two differences. While the \c FullDigraph class + /// This class provides constant time counting for nodes, edges and arcs. + /// + /// \note FullDigraph and FullGraph classes are very similar, + /// but there are two differences. While FullDigraph /// conforms only to the \ref concepts::Digraph "Digraph" concept, /// this class conforms to the \ref concepts::Graph "Graph" concept, - /// moreover \c FullGraph does not contain a loop arc for each - /// node as \c FullDigraph does. + /// moreover this class does not contain a loop for each + /// node as FullDigraph does. /// /// \sa FullDigraph class FullGraph : public ExtendedFullGraphBase { @@ -542,7 +554,9 @@ public: - /// \brief Constructor + /// \brief Default constructor. + /// + /// Default constructor. The number of nodes and edges will be zero. FullGraph() { construct(0); } /// \brief Constructor @@ -553,8 +567,8 @@ /// \brief Resizes the graph /// - /// Resizes the graph. The function will fully destroy and - /// rebuild the graph. This cause that the maps of the graph will + /// This function resizes the graph. It fully destroys and + /// rebuilds the structure, therefore the maps of the graph will be /// reallocated automatically and the previous values will be lost. void resize(int n) { Parent::notifier(Arc()).clear(); @@ -568,31 +582,33 @@ /// \brief Returns the node with the given index. /// - /// Returns the node with the given index. Since it is a static - /// graph its nodes can be indexed with integers from the range - /// [0..nodeNum()-1]. + /// Returns the node with the given index. Since this structure is + /// completely static, the nodes can be indexed with integers from + /// the range [0..nodeNum()-1]. + /// The index of a node is the same as its ID. /// \sa index() Node operator()(int ix) const { return Parent::operator()(ix); } /// \brief Returns the index of the given node. /// - /// Returns the index of the given node. Since it is a static - /// graph its nodes can be indexed with integers from the range - /// [0..nodeNum()-1]. - /// \sa operator() - int index(const Node& node) const { return Parent::index(node); } + /// Returns the index of the given node. Since this structure is + /// completely static, the nodes can be indexed with integers from + /// the range [0..nodeNum()-1]. + /// The index of a node is the same as its ID. + /// \sa operator()() + static int index(const Node& node) { return Parent::index(node); } /// \brief Returns the arc connecting the given nodes. /// /// Returns the arc connecting the given nodes. - Arc arc(const Node& s, const Node& t) const { + Arc arc(Node s, Node t) const { return Parent::arc(s, t); } - /// \brief Returns the edge connects the given nodes. + /// \brief Returns the edge connecting the given nodes. /// - /// Returns the edge connects the given nodes. - Edge edge(const Node& u, const Node& v) const { + /// Returns the edge connecting the given nodes. + Edge edge(Node u, Node v) const { return Parent::edge(u, v); } diff --git a/lemon/glpk.cc b/lemon/glpk.cc --- a/lemon/glpk.cc +++ b/lemon/glpk.cc @@ -59,6 +59,42 @@ return i; } + int GlpkBase::_addRow(Value lo, ExprIterator b, + ExprIterator e, Value up) { + int i = glp_add_rows(lp, 1); + + if (lo == -INF) { + if (up == INF) { + glp_set_row_bnds(lp, i, GLP_FR, lo, up); + } else { + glp_set_row_bnds(lp, i, GLP_UP, lo, up); + } + } else { + if (up == INF) { + glp_set_row_bnds(lp, i, GLP_LO, lo, up); + } else if (lo != up) { + glp_set_row_bnds(lp, i, GLP_DB, lo, up); + } else { + glp_set_row_bnds(lp, i, GLP_FX, lo, up); + } + } + + std::vector indexes; + std::vector values; + + indexes.push_back(0); + values.push_back(0); + + for(ExprIterator it = b; it != e; ++it) { + indexes.push_back(it->first); + values.push_back(it->second); + } + + glp_set_mat_row(lp, i, values.size() - 1, + &indexes.front(), &values.front()); + return i; + } + void GlpkBase::_eraseCol(int i) { int ca[2]; ca[1] = i; diff --git a/lemon/glpk.h b/lemon/glpk.h --- a/lemon/glpk.h +++ b/lemon/glpk.h @@ -54,6 +54,7 @@ virtual int _addCol(); virtual int _addRow(); + virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u); virtual void _eraseCol(int i); virtual void _eraseRow(int i); diff --git a/lemon/gomory_hu.h b/lemon/gomory_hu.h --- a/lemon/gomory_hu.h +++ b/lemon/gomory_hu.h @@ -294,11 +294,9 @@ /// /// \pre \ref run() must be called before using this function. template - Value minCutMap(const Node& s, ///< + Value minCutMap(const Node& s, const Node& t, - ///< CutMap& cutMap - ///< ) const { Node sn = s, tn = t; bool s_root=false; @@ -359,10 +357,10 @@ /// This example counts the nodes in the minimum cut separating \c s from /// \c t. /// \code - /// GomoruHu gom(g, capacities); + /// GomoryHu gom(g, capacities); /// gom.run(); /// int cnt=0; - /// for(GomoruHu::MinCutNodeIt n(gom,s,t); n!=INVALID; ++n) ++cnt; + /// for(GomoryHu::MinCutNodeIt n(gom,s,t); n!=INVALID; ++n) ++cnt; /// \endcode class MinCutNodeIt { @@ -394,7 +392,7 @@ /// MinCutNodeIt(gomory, t, s, false); /// \endcode /// does not necessarily give the same set of nodes. - /// However it is ensured that + /// However, it is ensured that /// \code /// MinCutNodeIt(gomory, s, t, true); /// \endcode @@ -456,10 +454,10 @@ /// This example computes the value of the minimum cut separating \c s from /// \c t. /// \code - /// GomoruHu gom(g, capacities); + /// GomoryHu gom(g, capacities); /// gom.run(); /// int value=0; - /// for(GomoruHu::MinCutEdgeIt e(gom,s,t); e!=INVALID; ++e) + /// for(GomoryHu::MinCutEdgeIt e(gom,s,t); e!=INVALID; ++e) /// value+=capacities[e]; /// \endcode /// The result will be the same as the value returned by diff --git a/lemon/graph_to_eps.h b/lemon/graph_to_eps.h --- a/lemon/graph_to_eps.h +++ b/lemon/graph_to_eps.h @@ -142,7 +142,7 @@ ///Constructor ///\param gr Reference to the graph to be printed. ///\param ost Reference to the output stream. - ///By default it is std::cout. + ///By default, it is std::cout. ///\param pros If it is \c true, then the \c ostream referenced by \c os ///will be explicitly deallocated by the destructor. DefaultGraphToEpsTraits(const GR &gr, std::ostream& ost = std::cout, @@ -512,7 +512,7 @@ ///Turn on/off pre-scaling - ///By default graphToEps() rescales the whole image in order to avoid + ///By default, graphToEps() rescales the whole image in order to avoid ///very big or very small bounding boxes. /// ///This (p)rescaling can be turned off with this function. @@ -1114,7 +1114,7 @@ ///Generates an EPS file from a graph. ///\param g Reference to the graph to be printed. ///\param os Reference to the output stream. -///By default it is std::cout. +///By default, it is std::cout. /// ///This function also has a lot of ///\ref named-templ-func-param "named parameters", @@ -1126,7 +1126,7 @@ /// .arcWidthScale(.4).run(); ///\endcode /// -///For more detailed examples see the \ref graph_to_eps_demo.cc demo file. +///For more detailed examples, see the \ref graph_to_eps_demo.cc demo file. /// ///\warning Don't forget to put the \ref GraphToEps::run() "run()" ///to the end of the parameter list. diff --git a/lemon/grid_graph.h b/lemon/grid_graph.h --- a/lemon/grid_graph.h +++ b/lemon/grid_graph.h @@ -470,18 +470,22 @@ /// /// \brief Grid graph class /// - /// This class implements a special graph type. The nodes of the - /// graph can be indexed by two integer \c (i,j) value where \c i is - /// in the \c [0..width()-1] range and j is in the \c - /// [0..height()-1] range. Two nodes are connected in the graph if - /// the indexes differ exactly on one position and exactly one is - /// the difference. The nodes of the graph can be indexed by position - /// with the \c operator()() function. The positions of the nodes can be - /// get with \c pos(), \c col() and \c row() members. The outgoing + /// GridGraph implements a special graph type. The nodes of the + /// graph can be indexed by two integer values \c (i,j) where \c i is + /// in the range [0..width()-1] and j is in the range + /// [0..height()-1]. Two nodes are connected in the graph if + /// the indices differ exactly on one position and the difference is + /// also exactly one. The nodes of the graph can be obtained by position + /// using the \c operator()() function and the indices of the nodes can + /// be obtained using \c pos(), \c col() and \c row() members. The outgoing /// arcs can be retrieved with the \c right(), \c up(), \c left() /// and \c down() functions, where the bottom-left corner is the /// origin. /// + /// This class is completely static and it needs constant memory space. + /// Thus you can neither add nor delete nodes or edges, however + /// the structure can be resized using resize(). + /// /// \image html grid_graph.png /// \image latex grid_graph.eps "Grid graph" width=\textwidth /// @@ -496,16 +500,21 @@ /// } ///\endcode /// - /// This graph type fully conforms to the \ref concepts::Graph - /// "Graph concept". + /// This type fully conforms to the \ref concepts::Graph "Graph concept". + /// Most of its member functions and nested classes are documented + /// only in the concept class. + /// + /// This class provides constant time counting for nodes, edges and arcs. class GridGraph : public ExtendedGridGraphBase { typedef ExtendedGridGraphBase Parent; public: - /// \brief Map to get the indices of the nodes as dim2::Point. + /// \brief Map to get the indices of the nodes as \ref dim2::Point + /// "dim2::Point". /// - /// Map to get the indices of the nodes as dim2::Point. + /// Map to get the indices of the nodes as \ref dim2::Point + /// "dim2::Point". class IndexMap { public: /// \brief The key type of the map @@ -514,13 +523,9 @@ typedef dim2::Point Value; /// \brief Constructor - /// - /// Constructor IndexMap(const GridGraph& graph) : _graph(graph) {} /// \brief The subscript operator - /// - /// The subscript operator. Value operator[](Key key) const { return _graph.pos(key); } @@ -540,13 +545,9 @@ typedef int Value; /// \brief Constructor - /// - /// Constructor ColMap(const GridGraph& graph) : _graph(graph) {} /// \brief The subscript operator - /// - /// The subscript operator. Value operator[](Key key) const { return _graph.col(key); } @@ -566,13 +567,9 @@ typedef int Value; /// \brief Constructor - /// - /// Constructor RowMap(const GridGraph& graph) : _graph(graph) {} /// \brief The subscript operator - /// - /// The subscript operator. Value operator[](Key key) const { return _graph.row(key); } @@ -583,15 +580,14 @@ /// \brief Constructor /// - /// Construct a grid graph with given size. + /// Construct a grid graph with the given size. GridGraph(int width, int height) { construct(width, height); } - /// \brief Resize the graph + /// \brief Resizes the graph /// - /// Resize the graph. The function will fully destroy and rebuild - /// the graph. This cause that the maps of the graph will - /// reallocated automatically and the previous values will be - /// lost. + /// This function resizes the graph. It fully destroys and + /// rebuilds the structure, therefore the maps of the graph will be + /// reallocated automatically and the previous values will be lost. void resize(int width, int height) { Parent::notifier(Arc()).clear(); Parent::notifier(Edge()).clear(); @@ -609,42 +605,42 @@ return Parent::operator()(i, j); } - /// \brief Gives back the column index of the node. + /// \brief The column index of the node. /// /// Gives back the column index of the node. int col(Node n) const { return Parent::col(n); } - /// \brief Gives back the row index of the node. + /// \brief The row index of the node. /// /// Gives back the row index of the node. int row(Node n) const { return Parent::row(n); } - /// \brief Gives back the position of the node. + /// \brief The position of the node. /// /// Gives back the position of the node, ie. the (col,row) pair. dim2::Point pos(Node n) const { return Parent::pos(n); } - /// \brief Gives back the number of the columns. + /// \brief The number of the columns. /// /// Gives back the number of the columns. int width() const { return Parent::width(); } - /// \brief Gives back the number of the rows. + /// \brief The number of the rows. /// /// Gives back the number of the rows. int height() const { return Parent::height(); } - /// \brief Gives back the arc goes right from the node. + /// \brief The arc goes right from the node. /// /// Gives back the arc goes right from the node. If there is not /// outgoing arc then it gives back INVALID. @@ -652,7 +648,7 @@ return Parent::right(n); } - /// \brief Gives back the arc goes left from the node. + /// \brief The arc goes left from the node. /// /// Gives back the arc goes left from the node. If there is not /// outgoing arc then it gives back INVALID. @@ -660,7 +656,7 @@ return Parent::left(n); } - /// \brief Gives back the arc goes up from the node. + /// \brief The arc goes up from the node. /// /// Gives back the arc goes up from the node. If there is not /// outgoing arc then it gives back INVALID. @@ -668,7 +664,7 @@ return Parent::up(n); } - /// \brief Gives back the arc goes down from the node. + /// \brief The arc goes down from the node. /// /// Gives back the arc goes down from the node. If there is not /// outgoing arc then it gives back INVALID. diff --git a/lemon/hartmann_orlin.h b/lemon/hartmann_orlin.h new file mode 100644 --- /dev/null +++ b/lemon/hartmann_orlin.h @@ -0,0 +1,642 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2008 + * 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_HARTMANN_ORLIN_H +#define LEMON_HARTMANN_ORLIN_H + +/// \ingroup min_mean_cycle +/// +/// \file +/// \brief Hartmann-Orlin's algorithm for finding a minimum mean cycle. + +#include +#include +#include +#include +#include +#include + +namespace lemon { + + /// \brief Default traits class of HartmannOrlin algorithm. + /// + /// Default traits class of HartmannOrlin algorithm. + /// \tparam GR The type of the digraph. + /// \tparam LEN The type of the length map. + /// It must conform to the \ref concepts::Rea_data "Rea_data" concept. +#ifdef DOXYGEN + template +#else + template ::is_integer> +#endif + struct HartmannOrlinDefaultTraits + { + /// The type of the digraph + typedef GR Digraph; + /// The type of the length map + typedef LEN LengthMap; + /// The type of the arc lengths + typedef typename LengthMap::Value Value; + + /// \brief The large value type used for internal computations + /// + /// The large value type used for internal computations. + /// It is \c long \c long if the \c Value type is integer, + /// otherwise it is \c double. + /// \c Value must be convertible to \c LargeValue. + typedef double LargeValue; + + /// The tolerance type used for internal computations + typedef lemon::Tolerance Tolerance; + + /// \brief The path type of the found cycles + /// + /// The path type of the found cycles. + /// It must conform to the \ref lemon::concepts::Path "Path" concept + /// and it must have an \c addFront() function. + typedef lemon::Path Path; + }; + + // Default traits class for integer value types + template + struct HartmannOrlinDefaultTraits + { + typedef GR Digraph; + typedef LEN LengthMap; + typedef typename LengthMap::Value Value; +#ifdef LEMON_HAVE_LONG_LONG + typedef long long LargeValue; +#else + typedef long LargeValue; +#endif + typedef lemon::Tolerance Tolerance; + typedef lemon::Path Path; + }; + + + /// \addtogroup min_mean_cycle + /// @{ + + /// \brief Implementation of the Hartmann-Orlin algorithm for finding + /// a minimum mean cycle. + /// + /// This class implements the Hartmann-Orlin algorithm for finding + /// a directed cycle of minimum mean length (cost) in a digraph + /// \ref amo93networkflows, \ref dasdan98minmeancycle. + /// It is an improved version of \ref Karp "Karp"'s original algorithm, + /// it applies an efficient early termination scheme. + /// It runs in time O(ne) and uses space O(n2+e). + /// + /// \tparam GR The type of the digraph the algorithm runs on. + /// \tparam LEN The type of the length map. The default + /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap". +#ifdef DOXYGEN + template +#else + template < typename GR, + typename LEN = typename GR::template ArcMap, + typename TR = HartmannOrlinDefaultTraits > +#endif + class HartmannOrlin + { + public: + + /// The type of the digraph + typedef typename TR::Digraph Digraph; + /// The type of the length map + typedef typename TR::LengthMap LengthMap; + /// The type of the arc lengths + typedef typename TR::Value Value; + + /// \brief The large value type + /// + /// The large value type used for internal computations. + /// Using the \ref HartmannOrlinDefaultTraits "default traits class", + /// it is \c long \c long if the \c Value type is integer, + /// otherwise it is \c double. + typedef typename TR::LargeValue LargeValue; + + /// The tolerance type + typedef typename TR::Tolerance Tolerance; + + /// \brief The path type of the found cycles + /// + /// The path type of the found cycles. + /// Using the \ref HartmannOrlinDefaultTraits "default traits class", + /// it is \ref lemon::Path "Path". + typedef typename TR::Path Path; + + /// The \ref HartmannOrlinDefaultTraits "traits class" of the algorithm + typedef TR Traits; + + private: + + TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); + + // Data sturcture for path data + struct PathData + { + LargeValue dist; + Arc pred; + PathData(LargeValue d, Arc p = INVALID) : + dist(d), pred(p) {} + }; + + typedef typename Digraph::template NodeMap > + PathDataNodeMap; + + private: + + // The digraph the algorithm runs on + const Digraph &_gr; + // The length of the arcs + const LengthMap &_length; + + // Data for storing the strongly connected components + int _comp_num; + typename Digraph::template NodeMap _comp; + std::vector > _comp_nodes; + std::vector* _nodes; + typename Digraph::template NodeMap > _out_arcs; + + // Data for the found cycles + bool _curr_found, _best_found; + LargeValue _curr_length, _best_length; + int _curr_size, _best_size; + Node _curr_node, _best_node; + int _curr_level, _best_level; + + Path *_cycle_path; + bool _local_path; + + // Node map for storing path data + PathDataNodeMap _data; + // The processed nodes in the last round + std::vector _process; + + Tolerance _tolerance; + + // Infinite constant + const LargeValue INF; + + public: + + /// \name Named Template Parameters + /// @{ + + template + struct SetLargeValueTraits : public Traits { + typedef T LargeValue; + typedef lemon::Tolerance Tolerance; + }; + + /// \brief \ref named-templ-param "Named parameter" for setting + /// \c LargeValue type. + /// + /// \ref named-templ-param "Named parameter" for setting \c LargeValue + /// type. It is used for internal computations in the algorithm. + template + struct SetLargeValue + : public HartmannOrlin > { + typedef HartmannOrlin > Create; + }; + + template + struct SetPathTraits : public Traits { + typedef T Path; + }; + + /// \brief \ref named-templ-param "Named parameter" for setting + /// \c %Path type. + /// + /// \ref named-templ-param "Named parameter" for setting the \c %Path + /// type of the found cycles. + /// It must conform to the \ref lemon::concepts::Path "Path" concept + /// and it must have an \c addFront() function. + template + struct SetPath + : public HartmannOrlin > { + typedef HartmannOrlin > Create; + }; + + /// @} + + public: + + /// \brief Constructor. + /// + /// The constructor of the class. + /// + /// \param digraph The digraph the algorithm runs on. + /// \param length The lengths (costs) of the arcs. + HartmannOrlin( const Digraph &digraph, + const LengthMap &length ) : + _gr(digraph), _length(length), _comp(digraph), _out_arcs(digraph), + _best_found(false), _best_length(0), _best_size(1), + _cycle_path(NULL), _local_path(false), _data(digraph), + INF(std::numeric_limits::has_infinity ? + std::numeric_limits::infinity() : + std::numeric_limits::max()) + {} + + /// Destructor. + ~HartmannOrlin() { + if (_local_path) delete _cycle_path; + } + + /// \brief Set the path structure for storing the found cycle. + /// + /// This function sets an external path structure for storing the + /// found cycle. + /// + /// If you don't call this function before calling \ref run() or + /// \ref findMinMean(), it will allocate a local \ref Path "path" + /// structure. The destuctor deallocates this automatically + /// allocated object, of course. + /// + /// \note The algorithm calls only the \ref lemon::Path::addFront() + /// "addFront()" function of the given path structure. + /// + /// \return (*this) + HartmannOrlin& cycle(Path &path) { + if (_local_path) { + delete _cycle_path; + _local_path = false; + } + _cycle_path = &path; + return *this; + } + + /// \brief Set the tolerance used by the algorithm. + /// + /// This function sets the tolerance object used by the algorithm. + /// + /// \return (*this) + HartmannOrlin& tolerance(const Tolerance& tolerance) { + _tolerance = tolerance; + return *this; + } + + /// \brief Return a const reference to the tolerance. + /// + /// This function returns a const reference to the tolerance object + /// used by the algorithm. + const Tolerance& tolerance() const { + return _tolerance; + } + + /// \name Execution control + /// The simplest way to execute the algorithm is to call the \ref run() + /// function.\n + /// If you only need the minimum mean length, you may call + /// \ref findMinMean(). + + /// @{ + + /// \brief Run the algorithm. + /// + /// This function runs the algorithm. + /// It can be called more than once (e.g. if the underlying digraph + /// and/or the arc lengths have been modified). + /// + /// \return \c true if a directed cycle exists in the digraph. + /// + /// \note mmc.run() is just a shortcut of the following code. + /// \code + /// return mmc.findMinMean() && mmc.findCycle(); + /// \endcode + bool run() { + return findMinMean() && findCycle(); + } + + /// \brief Find the minimum cycle mean. + /// + /// This function finds the minimum mean length of the directed + /// cycles in the digraph. + /// + /// \return \c true if a directed cycle exists in the digraph. + bool findMinMean() { + // Initialization and find strongly connected components + init(); + findComponents(); + + // Find the minimum cycle mean in the components + for (int comp = 0; comp < _comp_num; ++comp) { + if (!initComponent(comp)) continue; + processRounds(); + + // Update the best cycle (global minimum mean cycle) + if ( _curr_found && (!_best_found || + _curr_length * _best_size < _best_length * _curr_size) ) { + _best_found = true; + _best_length = _curr_length; + _best_size = _curr_size; + _best_node = _curr_node; + _best_level = _curr_level; + } + } + return _best_found; + } + + /// \brief Find a minimum mean directed cycle. + /// + /// This function finds a directed cycle of minimum mean length + /// in the digraph using the data computed by findMinMean(). + /// + /// \return \c true if a directed cycle exists in the digraph. + /// + /// \pre \ref findMinMean() must be called before using this function. + bool findCycle() { + if (!_best_found) return false; + IntNodeMap reached(_gr, -1); + int r = _best_level + 1; + Node u = _best_node; + while (reached[u] < 0) { + reached[u] = --r; + u = _gr.source(_data[u][r].pred); + } + r = reached[u]; + Arc e = _data[u][r].pred; + _cycle_path->addFront(e); + _best_length = _length[e]; + _best_size = 1; + Node v; + while ((v = _gr.source(e)) != u) { + e = _data[v][--r].pred; + _cycle_path->addFront(e); + _best_length += _length[e]; + ++_best_size; + } + return true; + } + + /// @} + + /// \name Query Functions + /// The results of the algorithm can be obtained using these + /// functions.\n + /// The algorithm should be executed before using them. + + /// @{ + + /// \brief Return the total length of the found cycle. + /// + /// This function returns the total length of the found cycle. + /// + /// \pre \ref run() or \ref findMinMean() must be called before + /// using this function. + LargeValue cycleLength() const { + return _best_length; + } + + /// \brief Return the number of arcs on the found cycle. + /// + /// This function returns the number of arcs on the found cycle. + /// + /// \pre \ref run() or \ref findMinMean() must be called before + /// using this function. + int cycleArcNum() const { + return _best_size; + } + + /// \brief Return the mean length of the found cycle. + /// + /// This function returns the mean length of the found cycle. + /// + /// \note alg.cycleMean() is just a shortcut of the + /// following code. + /// \code + /// return static_cast(alg.cycleLength()) / alg.cycleArcNum(); + /// \endcode + /// + /// \pre \ref run() or \ref findMinMean() must be called before + /// using this function. + double cycleMean() const { + return static_cast(_best_length) / _best_size; + } + + /// \brief Return the found cycle. + /// + /// This function returns a const reference to the path structure + /// storing the found cycle. + /// + /// \pre \ref run() or \ref findCycle() must be called before using + /// this function. + const Path& cycle() const { + return *_cycle_path; + } + + ///@} + + private: + + // Initialization + void init() { + if (!_cycle_path) { + _local_path = true; + _cycle_path = new Path; + } + _cycle_path->clear(); + _best_found = false; + _best_length = 0; + _best_size = 1; + _cycle_path->clear(); + for (NodeIt u(_gr); u != INVALID; ++u) + _data[u].clear(); + } + + // Find strongly connected components and initialize _comp_nodes + // and _out_arcs + void findComponents() { + _comp_num = stronglyConnectedComponents(_gr, _comp); + _comp_nodes.resize(_comp_num); + if (_comp_num == 1) { + _comp_nodes[0].clear(); + for (NodeIt n(_gr); n != INVALID; ++n) { + _comp_nodes[0].push_back(n); + _out_arcs[n].clear(); + for (OutArcIt a(_gr, n); a != INVALID; ++a) { + _out_arcs[n].push_back(a); + } + } + } else { + for (int i = 0; i < _comp_num; ++i) + _comp_nodes[i].clear(); + for (NodeIt n(_gr); n != INVALID; ++n) { + int k = _comp[n]; + _comp_nodes[k].push_back(n); + _out_arcs[n].clear(); + for (OutArcIt a(_gr, n); a != INVALID; ++a) { + if (_comp[_gr.target(a)] == k) _out_arcs[n].push_back(a); + } + } + } + } + + // Initialize path data for the current component + bool initComponent(int comp) { + _nodes = &(_comp_nodes[comp]); + int n = _nodes->size(); + if (n < 1 || (n == 1 && _out_arcs[(*_nodes)[0]].size() == 0)) { + return false; + } + for (int i = 0; i < n; ++i) { + _data[(*_nodes)[i]].resize(n + 1, PathData(INF)); + } + return true; + } + + // Process all rounds of computing path data for the current component. + // _data[v][k] is the length of a shortest directed walk from the root + // node to node v containing exactly k arcs. + void processRounds() { + Node start = (*_nodes)[0]; + _data[start][0] = PathData(0); + _process.clear(); + _process.push_back(start); + + int k, n = _nodes->size(); + int next_check = 4; + bool terminate = false; + for (k = 1; k <= n && int(_process.size()) < n && !terminate; ++k) { + processNextBuildRound(k); + if (k == next_check || k == n) { + terminate = checkTermination(k); + next_check = next_check * 3 / 2; + } + } + for ( ; k <= n && !terminate; ++k) { + processNextFullRound(k); + if (k == next_check || k == n) { + terminate = checkTermination(k); + next_check = next_check * 3 / 2; + } + } + } + + // Process one round and rebuild _process + void processNextBuildRound(int k) { + std::vector next; + Node u, v; + Arc e; + LargeValue d; + for (int i = 0; i < int(_process.size()); ++i) { + u = _process[i]; + for (int j = 0; j < int(_out_arcs[u].size()); ++j) { + e = _out_arcs[u][j]; + v = _gr.target(e); + d = _data[u][k-1].dist + _length[e]; + if (_tolerance.less(d, _data[v][k].dist)) { + if (_data[v][k].dist == INF) next.push_back(v); + _data[v][k] = PathData(d, e); + } + } + } + _process.swap(next); + } + + // Process one round using _nodes instead of _process + void processNextFullRound(int k) { + Node u, v; + Arc e; + LargeValue d; + for (int i = 0; i < int(_nodes->size()); ++i) { + u = (*_nodes)[i]; + for (int j = 0; j < int(_out_arcs[u].size()); ++j) { + e = _out_arcs[u][j]; + v = _gr.target(e); + d = _data[u][k-1].dist + _length[e]; + if (_tolerance.less(d, _data[v][k].dist)) { + _data[v][k] = PathData(d, e); + } + } + } + } + + // Check early termination + bool checkTermination(int k) { + typedef std::pair Pair; + typename GR::template NodeMap level(_gr, Pair(-1, 0)); + typename GR::template NodeMap pi(_gr); + int n = _nodes->size(); + LargeValue length; + int size; + Node u; + + // Search for cycles that are already found + _curr_found = false; + for (int i = 0; i < n; ++i) { + u = (*_nodes)[i]; + if (_data[u][k].dist == INF) continue; + for (int j = k; j >= 0; --j) { + if (level[u].first == i && level[u].second > 0) { + // A cycle is found + length = _data[u][level[u].second].dist - _data[u][j].dist; + size = level[u].second - j; + if (!_curr_found || length * _curr_size < _curr_length * size) { + _curr_length = length; + _curr_size = size; + _curr_node = u; + _curr_level = level[u].second; + _curr_found = true; + } + } + level[u] = Pair(i, j); + if (j != 0) { + u = _gr.source(_data[u][j].pred); + } + } + } + + // If at least one cycle is found, check the optimality condition + LargeValue d; + if (_curr_found && k < n) { + // Find node potentials + for (int i = 0; i < n; ++i) { + u = (*_nodes)[i]; + pi[u] = INF; + for (int j = 0; j <= k; ++j) { + if (_data[u][j].dist < INF) { + d = _data[u][j].dist * _curr_size - j * _curr_length; + if (_tolerance.less(d, pi[u])) pi[u] = d; + } + } + } + + // Check the optimality condition for all arcs + bool done = true; + for (ArcIt a(_gr); a != INVALID; ++a) { + if (_tolerance.less(_length[a] * _curr_size - _curr_length, + pi[_gr.target(a)] - pi[_gr.source(a)]) ) { + done = false; + break; + } + } + return done; + } + return (k == n); + } + + }; //class HartmannOrlin + + ///@} + +} //namespace lemon + +#endif //LEMON_HARTMANN_ORLIN_H diff --git a/lemon/howard.h b/lemon/howard.h new file mode 100644 --- /dev/null +++ b/lemon/howard.h @@ -0,0 +1,597 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2008 + * 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_HOWARD_H +#define LEMON_HOWARD_H + +/// \ingroup min_mean_cycle +/// +/// \file +/// \brief Howard's algorithm for finding a minimum mean cycle. + +#include +#include +#include +#include +#include +#include + +namespace lemon { + + /// \brief Default traits class of Howard class. + /// + /// Default traits class of Howard class. + /// \tparam GR The type of the digraph. + /// \tparam LEN The type of the length map. + /// It must conform to the \ref concepts::ReadMap "ReadMap" concept. +#ifdef DOXYGEN + template +#else + template ::is_integer> +#endif + struct HowardDefaultTraits + { + /// The type of the digraph + typedef GR Digraph; + /// The type of the length map + typedef LEN LengthMap; + /// The type of the arc lengths + typedef typename LengthMap::Value Value; + + /// \brief The large value type used for internal computations + /// + /// The large value type used for internal computations. + /// It is \c long \c long if the \c Value type is integer, + /// otherwise it is \c double. + /// \c Value must be convertible to \c LargeValue. + typedef double LargeValue; + + /// The tolerance type used for internal computations + typedef lemon::Tolerance Tolerance; + + /// \brief The path type of the found cycles + /// + /// The path type of the found cycles. + /// It must conform to the \ref lemon::concepts::Path "Path" concept + /// and it must have an \c addBack() function. + typedef lemon::Path Path; + }; + + // Default traits class for integer value types + template + struct HowardDefaultTraits + { + typedef GR Digraph; + typedef LEN LengthMap; + typedef typename LengthMap::Value Value; +#ifdef LEMON_HAVE_LONG_LONG + typedef long long LargeValue; +#else + typedef long LargeValue; +#endif + typedef lemon::Tolerance Tolerance; + typedef lemon::Path Path; + }; + + + /// \addtogroup min_mean_cycle + /// @{ + + /// \brief Implementation of Howard's algorithm for finding a minimum + /// mean cycle. + /// + /// This class implements Howard's policy iteration algorithm for finding + /// a directed cycle of minimum mean length (cost) in a digraph + /// \ref amo93networkflows, \ref dasdan98minmeancycle. + /// This class provides the most efficient algorithm for the + /// minimum mean cycle problem, though the best known theoretical + /// bound on its running time is exponential. + /// + /// \tparam GR The type of the digraph the algorithm runs on. + /// \tparam LEN The type of the length map. The default + /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap". +#ifdef DOXYGEN + template +#else + template < typename GR, + typename LEN = typename GR::template ArcMap, + typename TR = HowardDefaultTraits > +#endif + class Howard + { + public: + + /// The type of the digraph + typedef typename TR::Digraph Digraph; + /// The type of the length map + typedef typename TR::LengthMap LengthMap; + /// The type of the arc lengths + typedef typename TR::Value Value; + + /// \brief The large value type + /// + /// The large value type used for internal computations. + /// Using the \ref HowardDefaultTraits "default traits class", + /// it is \c long \c long if the \c Value type is integer, + /// otherwise it is \c double. + typedef typename TR::LargeValue LargeValue; + + /// The tolerance type + typedef typename TR::Tolerance Tolerance; + + /// \brief The path type of the found cycles + /// + /// The path type of the found cycles. + /// Using the \ref HowardDefaultTraits "default traits class", + /// it is \ref lemon::Path "Path". + typedef typename TR::Path Path; + + /// The \ref HowardDefaultTraits "traits class" of the algorithm + typedef TR Traits; + + private: + + TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); + + // The digraph the algorithm runs on + const Digraph &_gr; + // The length of the arcs + const LengthMap &_length; + + // Data for the found cycles + bool _curr_found, _best_found; + LargeValue _curr_length, _best_length; + int _curr_size, _best_size; + Node _curr_node, _best_node; + + Path *_cycle_path; + bool _local_path; + + // Internal data used by the algorithm + typename Digraph::template NodeMap _policy; + typename Digraph::template NodeMap _reached; + typename Digraph::template NodeMap _level; + typename Digraph::template NodeMap _dist; + + // Data for storing the strongly connected components + int _comp_num; + typename Digraph::template NodeMap _comp; + std::vector > _comp_nodes; + std::vector* _nodes; + typename Digraph::template NodeMap > _in_arcs; + + // Queue used for BFS search + std::vector _queue; + int _qfront, _qback; + + Tolerance _tolerance; + + // Infinite constant + const LargeValue INF; + + public: + + /// \name Named Template Parameters + /// @{ + + template + struct SetLargeValueTraits : public Traits { + typedef T LargeValue; + typedef lemon::Tolerance Tolerance; + }; + + /// \brief \ref named-templ-param "Named parameter" for setting + /// \c LargeValue type. + /// + /// \ref named-templ-param "Named parameter" for setting \c LargeValue + /// type. It is used for internal computations in the algorithm. + template + struct SetLargeValue + : public Howard > { + typedef Howard > Create; + }; + + template + struct SetPathTraits : public Traits { + typedef T Path; + }; + + /// \brief \ref named-templ-param "Named parameter" for setting + /// \c %Path type. + /// + /// \ref named-templ-param "Named parameter" for setting the \c %Path + /// type of the found cycles. + /// It must conform to the \ref lemon::concepts::Path "Path" concept + /// and it must have an \c addBack() function. + template + struct SetPath + : public Howard > { + typedef Howard > Create; + }; + + /// @} + + public: + + /// \brief Constructor. + /// + /// The constructor of the class. + /// + /// \param digraph The digraph the algorithm runs on. + /// \param length The lengths (costs) of the arcs. + Howard( const Digraph &digraph, + const LengthMap &length ) : + _gr(digraph), _length(length), _best_found(false), + _best_length(0), _best_size(1), _cycle_path(NULL), _local_path(false), + _policy(digraph), _reached(digraph), _level(digraph), _dist(digraph), + _comp(digraph), _in_arcs(digraph), + INF(std::numeric_limits::has_infinity ? + std::numeric_limits::infinity() : + std::numeric_limits::max()) + {} + + /// Destructor. + ~Howard() { + if (_local_path) delete _cycle_path; + } + + /// \brief Set the path structure for storing the found cycle. + /// + /// This function sets an external path structure for storing the + /// found cycle. + /// + /// If you don't call this function before calling \ref run() or + /// \ref findMinMean(), it will allocate a local \ref Path "path" + /// structure. The destuctor deallocates this automatically + /// allocated object, of course. + /// + /// \note The algorithm calls only the \ref lemon::Path::addBack() + /// "addBack()" function of the given path structure. + /// + /// \return (*this) + Howard& cycle(Path &path) { + if (_local_path) { + delete _cycle_path; + _local_path = false; + } + _cycle_path = &path; + return *this; + } + + /// \brief Set the tolerance used by the algorithm. + /// + /// This function sets the tolerance object used by the algorithm. + /// + /// \return (*this) + Howard& tolerance(const Tolerance& tolerance) { + _tolerance = tolerance; + return *this; + } + + /// \brief Return a const reference to the tolerance. + /// + /// This function returns a const reference to the tolerance object + /// used by the algorithm. + const Tolerance& tolerance() const { + return _tolerance; + } + + /// \name Execution control + /// The simplest way to execute the algorithm is to call the \ref run() + /// function.\n + /// If you only need the minimum mean length, you may call + /// \ref findMinMean(). + + /// @{ + + /// \brief Run the algorithm. + /// + /// This function runs the algorithm. + /// It can be called more than once (e.g. if the underlying digraph + /// and/or the arc lengths have been modified). + /// + /// \return \c true if a directed cycle exists in the digraph. + /// + /// \note mmc.run() is just a shortcut of the following code. + /// \code + /// return mmc.findMinMean() && mmc.findCycle(); + /// \endcode + bool run() { + return findMinMean() && findCycle(); + } + + /// \brief Find the minimum cycle mean. + /// + /// This function finds the minimum mean length of the directed + /// cycles in the digraph. + /// + /// \return \c true if a directed cycle exists in the digraph. + bool findMinMean() { + // Initialize and find strongly connected components + init(); + findComponents(); + + // Find the minimum cycle mean in the components + for (int comp = 0; comp < _comp_num; ++comp) { + // Find the minimum mean cycle in the current component + if (!buildPolicyGraph(comp)) continue; + while (true) { + findPolicyCycle(); + if (!computeNodeDistances()) break; + } + // Update the best cycle (global minimum mean cycle) + if ( _curr_found && (!_best_found || + _curr_length * _best_size < _best_length * _curr_size) ) { + _best_found = true; + _best_length = _curr_length; + _best_size = _curr_size; + _best_node = _curr_node; + } + } + return _best_found; + } + + /// \brief Find a minimum mean directed cycle. + /// + /// This function finds a directed cycle of minimum mean length + /// in the digraph using the data computed by findMinMean(). + /// + /// \return \c true if a directed cycle exists in the digraph. + /// + /// \pre \ref findMinMean() must be called before using this function. + bool findCycle() { + if (!_best_found) return false; + _cycle_path->addBack(_policy[_best_node]); + for ( Node v = _best_node; + (v = _gr.target(_policy[v])) != _best_node; ) { + _cycle_path->addBack(_policy[v]); + } + return true; + } + + /// @} + + /// \name Query Functions + /// The results of the algorithm can be obtained using these + /// functions.\n + /// The algorithm should be executed before using them. + + /// @{ + + /// \brief Return the total length of the found cycle. + /// + /// This function returns the total length of the found cycle. + /// + /// \pre \ref run() or \ref findMinMean() must be called before + /// using this function. + LargeValue cycleLength() const { + return _best_length; + } + + /// \brief Return the number of arcs on the found cycle. + /// + /// This function returns the number of arcs on the found cycle. + /// + /// \pre \ref run() or \ref findMinMean() must be called before + /// using this function. + int cycleArcNum() const { + return _best_size; + } + + /// \brief Return the mean length of the found cycle. + /// + /// This function returns the mean length of the found cycle. + /// + /// \note alg.cycleMean() is just a shortcut of the + /// following code. + /// \code + /// return static_cast(alg.cycleLength()) / alg.cycleArcNum(); + /// \endcode + /// + /// \pre \ref run() or \ref findMinMean() must be called before + /// using this function. + double cycleMean() const { + return static_cast(_best_length) / _best_size; + } + + /// \brief Return the found cycle. + /// + /// This function returns a const reference to the path structure + /// storing the found cycle. + /// + /// \pre \ref run() or \ref findCycle() must be called before using + /// this function. + const Path& cycle() const { + return *_cycle_path; + } + + ///@} + + private: + + // Initialize + void init() { + if (!_cycle_path) { + _local_path = true; + _cycle_path = new Path; + } + _queue.resize(countNodes(_gr)); + _best_found = false; + _best_length = 0; + _best_size = 1; + _cycle_path->clear(); + } + + // Find strongly connected components and initialize _comp_nodes + // and _in_arcs + void findComponents() { + _comp_num = stronglyConnectedComponents(_gr, _comp); + _comp_nodes.resize(_comp_num); + if (_comp_num == 1) { + _comp_nodes[0].clear(); + for (NodeIt n(_gr); n != INVALID; ++n) { + _comp_nodes[0].push_back(n); + _in_arcs[n].clear(); + for (InArcIt a(_gr, n); a != INVALID; ++a) { + _in_arcs[n].push_back(a); + } + } + } else { + for (int i = 0; i < _comp_num; ++i) + _comp_nodes[i].clear(); + for (NodeIt n(_gr); n != INVALID; ++n) { + int k = _comp[n]; + _comp_nodes[k].push_back(n); + _in_arcs[n].clear(); + for (InArcIt a(_gr, n); a != INVALID; ++a) { + if (_comp[_gr.source(a)] == k) _in_arcs[n].push_back(a); + } + } + } + } + + // Build the policy graph in the given strongly connected component + // (the out-degree of every node is 1) + bool buildPolicyGraph(int comp) { + _nodes = &(_comp_nodes[comp]); + if (_nodes->size() < 1 || + (_nodes->size() == 1 && _in_arcs[(*_nodes)[0]].size() == 0)) { + return false; + } + for (int i = 0; i < int(_nodes->size()); ++i) { + _dist[(*_nodes)[i]] = INF; + } + Node u, v; + Arc e; + for (int i = 0; i < int(_nodes->size()); ++i) { + v = (*_nodes)[i]; + for (int j = 0; j < int(_in_arcs[v].size()); ++j) { + e = _in_arcs[v][j]; + u = _gr.source(e); + if (_length[e] < _dist[u]) { + _dist[u] = _length[e]; + _policy[u] = e; + } + } + } + return true; + } + + // Find the minimum mean cycle in the policy graph + void findPolicyCycle() { + for (int i = 0; i < int(_nodes->size()); ++i) { + _level[(*_nodes)[i]] = -1; + } + LargeValue clength; + int csize; + Node u, v; + _curr_found = false; + for (int i = 0; i < int(_nodes->size()); ++i) { + u = (*_nodes)[i]; + if (_level[u] >= 0) continue; + for (; _level[u] < 0; u = _gr.target(_policy[u])) { + _level[u] = i; + } + if (_level[u] == i) { + // A cycle is found + clength = _length[_policy[u]]; + csize = 1; + for (v = u; (v = _gr.target(_policy[v])) != u; ) { + clength += _length[_policy[v]]; + ++csize; + } + if ( !_curr_found || + (clength * _curr_size < _curr_length * csize) ) { + _curr_found = true; + _curr_length = clength; + _curr_size = csize; + _curr_node = u; + } + } + } + } + + // Contract the policy graph and compute node distances + bool computeNodeDistances() { + // Find the component of the main cycle and compute node distances + // using reverse BFS + for (int i = 0; i < int(_nodes->size()); ++i) { + _reached[(*_nodes)[i]] = false; + } + _qfront = _qback = 0; + _queue[0] = _curr_node; + _reached[_curr_node] = true; + _dist[_curr_node] = 0; + Node u, v; + Arc e; + while (_qfront <= _qback) { + v = _queue[_qfront++]; + for (int j = 0; j < int(_in_arcs[v].size()); ++j) { + e = _in_arcs[v][j]; + u = _gr.source(e); + if (_policy[u] == e && !_reached[u]) { + _reached[u] = true; + _dist[u] = _dist[v] + _length[e] * _curr_size - _curr_length; + _queue[++_qback] = u; + } + } + } + + // Connect all other nodes to this component and compute node + // distances using reverse BFS + _qfront = 0; + while (_qback < int(_nodes->size())-1) { + v = _queue[_qfront++]; + for (int j = 0; j < int(_in_arcs[v].size()); ++j) { + e = _in_arcs[v][j]; + u = _gr.source(e); + if (!_reached[u]) { + _reached[u] = true; + _policy[u] = e; + _dist[u] = _dist[v] + _length[e] * _curr_size - _curr_length; + _queue[++_qback] = u; + } + } + } + + // Improve node distances + bool improved = false; + for (int i = 0; i < int(_nodes->size()); ++i) { + v = (*_nodes)[i]; + for (int j = 0; j < int(_in_arcs[v].size()); ++j) { + e = _in_arcs[v][j]; + u = _gr.source(e); + LargeValue delta = _dist[v] + _length[e] * _curr_size - _curr_length; + if (_tolerance.less(delta, _dist[u])) { + _dist[u] = delta; + _policy[u] = e; + improved = true; + } + } + } + return improved; + } + + }; //class Howard + + ///@} + +} //namespace lemon + +#endif //LEMON_HOWARD_H diff --git a/lemon/hypercube_graph.h b/lemon/hypercube_graph.h --- a/lemon/hypercube_graph.h +++ b/lemon/hypercube_graph.h @@ -262,7 +262,7 @@ return arc._id >> _dim; } - int index(Node node) const { + static int index(Node node) { return node._id; } @@ -282,17 +282,23 @@ /// /// \brief Hypercube graph class /// - /// This class implements a special graph type. The nodes of the graph - /// are indiced with integers with at most \c dim binary digits. + /// HypercubeGraph implements a special graph type. The nodes of the + /// graph are indexed with integers having at most \c dim binary digits. /// Two nodes are connected in the graph if and only if their indices /// differ only on one position in the binary form. + /// This class is completely static and it needs constant memory space. + /// Thus you can neither add nor delete nodes or edges, however, + /// the structure can be resized using resize(). + /// + /// This type fully conforms to the \ref concepts::Graph "Graph concept". + /// Most of its member functions and nested classes are documented + /// only in the concept class. + /// + /// This class provides constant time counting for nodes, edges and arcs. /// /// \note The type of the indices is chosen to \c int for efficiency /// reasons. Thus the maximum dimension of this implementation is 26 /// (assuming that the size of \c int is 32 bit). - /// - /// This graph type fully conforms to the \ref concepts::Graph - /// "Graph concept". class HypercubeGraph : public ExtendedHypercubeGraphBase { typedef ExtendedHypercubeGraphBase Parent; @@ -303,6 +309,21 @@ /// Constructs a hypercube graph with \c dim dimensions. HypercubeGraph(int dim) { construct(dim); } + /// \brief Resizes the graph + /// + /// This function resizes the graph. It fully destroys and + /// rebuilds the structure, therefore the maps of the graph will be + /// reallocated automatically and the previous values will be lost. + void resize(int dim) { + Parent::notifier(Arc()).clear(); + Parent::notifier(Edge()).clear(); + Parent::notifier(Node()).clear(); + construct(dim); + Parent::notifier(Node()).build(); + Parent::notifier(Edge()).build(); + Parent::notifier(Arc()).build(); + } + /// \brief The number of dimensions. /// /// Gives back the number of dimensions. @@ -320,7 +341,7 @@ /// \brief The dimension id of an edge. /// /// Gives back the dimension id of the given edge. - /// It is in the [0..dim-1] range. + /// It is in the range [0..dim-1]. int dimension(Edge edge) const { return Parent::dimension(edge); } @@ -328,7 +349,7 @@ /// \brief The dimension id of an arc. /// /// Gives back the dimension id of the given arc. - /// It is in the [0..dim-1] range. + /// It is in the range [0..dim-1]. int dimension(Arc arc) const { return Parent::dimension(arc); } @@ -337,7 +358,7 @@ /// /// Gives back the index of the given node. /// The lower bits of the integer describes the node. - int index(Node node) const { + static int index(Node node) { return Parent::index(node); } diff --git a/lemon/karp.h b/lemon/karp.h new file mode 100644 --- /dev/null +++ b/lemon/karp.h @@ -0,0 +1,582 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2008 + * 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_KARP_H +#define LEMON_KARP_H + +/// \ingroup min_mean_cycle +/// +/// \file +/// \brief Karp's algorithm for finding a minimum mean cycle. + +#include +#include +#include +#include +#include +#include + +namespace lemon { + + /// \brief Default traits class of Karp algorithm. + /// + /// Default traits class of Karp algorithm. + /// \tparam GR The type of the digraph. + /// \tparam LEN The type of the length map. + /// It must conform to the \ref concepts::ReadMap "ReadMap" concept. +#ifdef DOXYGEN + template +#else + template ::is_integer> +#endif + struct KarpDefaultTraits + { + /// The type of the digraph + typedef GR Digraph; + /// The type of the length map + typedef LEN LengthMap; + /// The type of the arc lengths + typedef typename LengthMap::Value Value; + + /// \brief The large value type used for internal computations + /// + /// The large value type used for internal computations. + /// It is \c long \c long if the \c Value type is integer, + /// otherwise it is \c double. + /// \c Value must be convertible to \c LargeValue. + typedef double LargeValue; + + /// The tolerance type used for internal computations + typedef lemon::Tolerance Tolerance; + + /// \brief The path type of the found cycles + /// + /// The path type of the found cycles. + /// It must conform to the \ref lemon::concepts::Path "Path" concept + /// and it must have an \c addFront() function. + typedef lemon::Path Path; + }; + + // Default traits class for integer value types + template + struct KarpDefaultTraits + { + typedef GR Digraph; + typedef LEN LengthMap; + typedef typename LengthMap::Value Value; +#ifdef LEMON_HAVE_LONG_LONG + typedef long long LargeValue; +#else + typedef long LargeValue; +#endif + typedef lemon::Tolerance Tolerance; + typedef lemon::Path Path; + }; + + + /// \addtogroup min_mean_cycle + /// @{ + + /// \brief Implementation of Karp's algorithm for finding a minimum + /// mean cycle. + /// + /// This class implements Karp's algorithm for finding a directed + /// cycle of minimum mean length (cost) in a digraph + /// \ref amo93networkflows, \ref dasdan98minmeancycle. + /// It runs in time O(ne) and uses space O(n2+e). + /// + /// \tparam GR The type of the digraph the algorithm runs on. + /// \tparam LEN The type of the length map. The default + /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap". +#ifdef DOXYGEN + template +#else + template < typename GR, + typename LEN = typename GR::template ArcMap, + typename TR = KarpDefaultTraits > +#endif + class Karp + { + public: + + /// The type of the digraph + typedef typename TR::Digraph Digraph; + /// The type of the length map + typedef typename TR::LengthMap LengthMap; + /// The type of the arc lengths + typedef typename TR::Value Value; + + /// \brief The large value type + /// + /// The large value type used for internal computations. + /// Using the \ref KarpDefaultTraits "default traits class", + /// it is \c long \c long if the \c Value type is integer, + /// otherwise it is \c double. + typedef typename TR::LargeValue LargeValue; + + /// The tolerance type + typedef typename TR::Tolerance Tolerance; + + /// \brief The path type of the found cycles + /// + /// The path type of the found cycles. + /// Using the \ref KarpDefaultTraits "default traits class", + /// it is \ref lemon::Path "Path". + typedef typename TR::Path Path; + + /// The \ref KarpDefaultTraits "traits class" of the algorithm + typedef TR Traits; + + private: + + TEMPLATE_DIGRAPH_TYPEDEFS(Digraph); + + // Data sturcture for path data + struct PathData + { + LargeValue dist; + Arc pred; + PathData(LargeValue d, Arc p = INVALID) : + dist(d), pred(p) {} + }; + + typedef typename Digraph::template NodeMap > + PathDataNodeMap; + + private: + + // The digraph the algorithm runs on + const Digraph &_gr; + // The length of the arcs + const LengthMap &_length; + + // Data for storing the strongly connected components + int _comp_num; + typename Digraph::template NodeMap _comp; + std::vector > _comp_nodes; + std::vector* _nodes; + typename Digraph::template NodeMap > _out_arcs; + + // Data for the found cycle + LargeValue _cycle_length; + int _cycle_size; + Node _cycle_node; + + Path *_cycle_path; + bool _local_path; + + // Node map for storing path data + PathDataNodeMap _data; + // The processed nodes in the last round + std::vector _process; + + Tolerance _tolerance; + + // Infinite constant + const LargeValue INF; + + public: + + /// \name Named Template Parameters + /// @{ + + template + struct SetLargeValueTraits : public Traits { + typedef T LargeValue; + typedef lemon::Tolerance Tolerance; + }; + + /// \brief \ref named-templ-param "Named parameter" for setting + /// \c LargeValue type. + /// + /// \ref named-templ-param "Named parameter" for setting \c LargeValue + /// type. It is used for internal computations in the algorithm. + template + struct SetLargeValue + : public Karp > { + typedef Karp > Create; + }; + + template + struct SetPathTraits : public Traits { + typedef T Path; + }; + + /// \brief \ref named-templ-param "Named parameter" for setting + /// \c %Path type. + /// + /// \ref named-templ-param "Named parameter" for setting the \c %Path + /// type of the found cycles. + /// It must conform to the \ref lemon::concepts::Path "Path" concept + /// and it must have an \c addFront() function. + template + struct SetPath + : public Karp > { + typedef Karp > Create; + }; + + /// @} + + public: + + /// \brief Constructor. + /// + /// The constructor of the class. + /// + /// \param digraph The digraph the algorithm runs on. + /// \param length The lengths (costs) of the arcs. + Karp( const Digraph &digraph, + const LengthMap &length ) : + _gr(digraph), _length(length), _comp(digraph), _out_arcs(digraph), + _cycle_length(0), _cycle_size(1), _cycle_node(INVALID), + _cycle_path(NULL), _local_path(false), _data(digraph), + INF(std::numeric_limits::has_infinity ? + std::numeric_limits::infinity() : + std::numeric_limits::max()) + {} + + /// Destructor. + ~Karp() { + if (_local_path) delete _cycle_path; + } + + /// \brief Set the path structure for storing the found cycle. + /// + /// This function sets an external path structure for storing the + /// found cycle. + /// + /// If you don't call this function before calling \ref run() or + /// \ref findMinMean(), it will allocate a local \ref Path "path" + /// structure. The destuctor deallocates this automatically + /// allocated object, of course. + /// + /// \note The algorithm calls only the \ref lemon::Path::addFront() + /// "addFront()" function of the given path structure. + /// + /// \return (*this) + Karp& cycle(Path &path) { + if (_local_path) { + delete _cycle_path; + _local_path = false; + } + _cycle_path = &path; + return *this; + } + + /// \brief Set the tolerance used by the algorithm. + /// + /// This function sets the tolerance object used by the algorithm. + /// + /// \return (*this) + Karp& tolerance(const Tolerance& tolerance) { + _tolerance = tolerance; + return *this; + } + + /// \brief Return a const reference to the tolerance. + /// + /// This function returns a const reference to the tolerance object + /// used by the algorithm. + const Tolerance& tolerance() const { + return _tolerance; + } + + /// \name Execution control + /// The simplest way to execute the algorithm is to call the \ref run() + /// function.\n + /// If you only need the minimum mean length, you may call + /// \ref findMinMean(). + + /// @{ + + /// \brief Run the algorithm. + /// + /// This function runs the algorithm. + /// It can be called more than once (e.g. if the underlying digraph + /// and/or the arc lengths have been modified). + /// + /// \return \c true if a directed cycle exists in the digraph. + /// + /// \note mmc.run() is just a shortcut of the following code. + /// \code + /// return mmc.findMinMean() && mmc.findCycle(); + /// \endcode + bool run() { + return findMinMean() && findCycle(); + } + + /// \brief Find the minimum cycle mean. + /// + /// This function finds the minimum mean length of the directed + /// cycles in the digraph. + /// + /// \return \c true if a directed cycle exists in the digraph. + bool findMinMean() { + // Initialization and find strongly connected components + init(); + findComponents(); + + // Find the minimum cycle mean in the components + for (int comp = 0; comp < _comp_num; ++comp) { + if (!initComponent(comp)) continue; + processRounds(); + updateMinMean(); + } + return (_cycle_node != INVALID); + } + + /// \brief Find a minimum mean directed cycle. + /// + /// This function finds a directed cycle of minimum mean length + /// in the digraph using the data computed by findMinMean(). + /// + /// \return \c true if a directed cycle exists in the digraph. + /// + /// \pre \ref findMinMean() must be called before using this function. + bool findCycle() { + if (_cycle_node == INVALID) return false; + IntNodeMap reached(_gr, -1); + int r = _data[_cycle_node].size(); + Node u = _cycle_node; + while (reached[u] < 0) { + reached[u] = --r; + u = _gr.source(_data[u][r].pred); + } + r = reached[u]; + Arc e = _data[u][r].pred; + _cycle_path->addFront(e); + _cycle_length = _length[e]; + _cycle_size = 1; + Node v; + while ((v = _gr.source(e)) != u) { + e = _data[v][--r].pred; + _cycle_path->addFront(e); + _cycle_length += _length[e]; + ++_cycle_size; + } + return true; + } + + /// @} + + /// \name Query Functions + /// The results of the algorithm can be obtained using these + /// functions.\n + /// The algorithm should be executed before using them. + + /// @{ + + /// \brief Return the total length of the found cycle. + /// + /// This function returns the total length of the found cycle. + /// + /// \pre \ref run() or \ref findMinMean() must be called before + /// using this function. + LargeValue cycleLength() const { + return _cycle_length; + } + + /// \brief Return the number of arcs on the found cycle. + /// + /// This function returns the number of arcs on the found cycle. + /// + /// \pre \ref run() or \ref findMinMean() must be called before + /// using this function. + int cycleArcNum() const { + return _cycle_size; + } + + /// \brief Return the mean length of the found cycle. + /// + /// This function returns the mean length of the found cycle. + /// + /// \note alg.cycleMean() is just a shortcut of the + /// following code. + /// \code + /// return static_cast(alg.cycleLength()) / alg.cycleArcNum(); + /// \endcode + /// + /// \pre \ref run() or \ref findMinMean() must be called before + /// using this function. + double cycleMean() const { + return static_cast(_cycle_length) / _cycle_size; + } + + /// \brief Return the found cycle. + /// + /// This function returns a const reference to the path structure + /// storing the found cycle. + /// + /// \pre \ref run() or \ref findCycle() must be called before using + /// this function. + const Path& cycle() const { + return *_cycle_path; + } + + ///@} + + private: + + // Initialization + void init() { + if (!_cycle_path) { + _local_path = true; + _cycle_path = new Path; + } + _cycle_path->clear(); + _cycle_length = 0; + _cycle_size = 1; + _cycle_node = INVALID; + for (NodeIt u(_gr); u != INVALID; ++u) + _data[u].clear(); + } + + // Find strongly connected components and initialize _comp_nodes + // and _out_arcs + void findComponents() { + _comp_num = stronglyConnectedComponents(_gr, _comp); + _comp_nodes.resize(_comp_num); + if (_comp_num == 1) { + _comp_nodes[0].clear(); + for (NodeIt n(_gr); n != INVALID; ++n) { + _comp_nodes[0].push_back(n); + _out_arcs[n].clear(); + for (OutArcIt a(_gr, n); a != INVALID; ++a) { + _out_arcs[n].push_back(a); + } + } + } else { + for (int i = 0; i < _comp_num; ++i) + _comp_nodes[i].clear(); + for (NodeIt n(_gr); n != INVALID; ++n) { + int k = _comp[n]; + _comp_nodes[k].push_back(n); + _out_arcs[n].clear(); + for (OutArcIt a(_gr, n); a != INVALID; ++a) { + if (_comp[_gr.target(a)] == k) _out_arcs[n].push_back(a); + } + } + } + } + + // Initialize path data for the current component + bool initComponent(int comp) { + _nodes = &(_comp_nodes[comp]); + int n = _nodes->size(); + if (n < 1 || (n == 1 && _out_arcs[(*_nodes)[0]].size() == 0)) { + return false; + } + for (int i = 0; i < n; ++i) { + _data[(*_nodes)[i]].resize(n + 1, PathData(INF)); + } + return true; + } + + // Process all rounds of computing path data for the current component. + // _data[v][k] is the length of a shortest directed walk from the root + // node to node v containing exactly k arcs. + void processRounds() { + Node start = (*_nodes)[0]; + _data[start][0] = PathData(0); + _process.clear(); + _process.push_back(start); + + int k, n = _nodes->size(); + for (k = 1; k <= n && int(_process.size()) < n; ++k) { + processNextBuildRound(k); + } + for ( ; k <= n; ++k) { + processNextFullRound(k); + } + } + + // Process one round and rebuild _process + void processNextBuildRound(int k) { + std::vector next; + Node u, v; + Arc e; + LargeValue d; + for (int i = 0; i < int(_process.size()); ++i) { + u = _process[i]; + for (int j = 0; j < int(_out_arcs[u].size()); ++j) { + e = _out_arcs[u][j]; + v = _gr.target(e); + d = _data[u][k-1].dist + _length[e]; + if (_tolerance.less(d, _data[v][k].dist)) { + if (_data[v][k].dist == INF) next.push_back(v); + _data[v][k] = PathData(d, e); + } + } + } + _process.swap(next); + } + + // Process one round using _nodes instead of _process + void processNextFullRound(int k) { + Node u, v; + Arc e; + LargeValue d; + for (int i = 0; i < int(_nodes->size()); ++i) { + u = (*_nodes)[i]; + for (int j = 0; j < int(_out_arcs[u].size()); ++j) { + e = _out_arcs[u][j]; + v = _gr.target(e); + d = _data[u][k-1].dist + _length[e]; + if (_tolerance.less(d, _data[v][k].dist)) { + _data[v][k] = PathData(d, e); + } + } + } + } + + // Update the minimum cycle mean + void updateMinMean() { + int n = _nodes->size(); + for (int i = 0; i < n; ++i) { + Node u = (*_nodes)[i]; + if (_data[u][n].dist == INF) continue; + LargeValue length, max_length = 0; + int size, max_size = 1; + bool found_curr = false; + for (int k = 0; k < n; ++k) { + if (_data[u][k].dist == INF) continue; + length = _data[u][n].dist - _data[u][k].dist; + size = n - k; + if (!found_curr || length * max_size > max_length * size) { + found_curr = true; + max_length = length; + max_size = size; + } + } + if ( found_curr && (_cycle_node == INVALID || + max_length * _cycle_size < _cycle_length * max_size) ) { + _cycle_length = max_length; + _cycle_size = max_size; + _cycle_node = u; + } + } + } + + }; //class Karp + + ///@} + +} //namespace lemon + +#endif //LEMON_KARP_H diff --git a/lemon/lgf_reader.h b/lemon/lgf_reader.h --- a/lemon/lgf_reader.h +++ b/lemon/lgf_reader.h @@ -427,7 +427,7 @@ /// run(); ///\endcode /// - /// By default the reader uses the first section in the file of the + /// By default, the reader uses the first section in the file of the /// proper type. If a section has an optional name, then it can be /// selected for reading by giving an optional name parameter to the /// \c nodes(), \c arcs() or \c attributes() functions. @@ -2221,7 +2221,7 @@ /// and the comment lines are filtered out, and the leading /// whitespaces are trimmed from each processed string. /// - /// For example let's see a section, which contain several + /// For example, let's see a section, which contain several /// integers, which should be inserted into a vector. ///\code /// @numbers diff --git a/lemon/list_graph.h b/lemon/list_graph.h --- a/lemon/list_graph.h +++ b/lemon/list_graph.h @@ -21,7 +21,7 @@ ///\ingroup graphs ///\file -///\brief ListDigraph, ListGraph classes. +///\brief ListDigraph and ListGraph classes. #include #include @@ -32,6 +32,8 @@ namespace lemon { + class ListDigraph; + class ListDigraphBase { protected: @@ -62,6 +64,7 @@ class Node { friend class ListDigraphBase; + friend class ListDigraph; protected: int id; @@ -77,6 +80,7 @@ class Arc { friend class ListDigraphBase; + friend class ListDigraph; protected: int id; @@ -116,20 +120,20 @@ void first(Arc& arc) const { int n; for(n = first_node; - n!=-1 && nodes[n].first_in == -1; + n != -1 && nodes[n].first_out == -1; n = nodes[n].next) {} - arc.id = (n == -1) ? -1 : nodes[n].first_in; + arc.id = (n == -1) ? -1 : nodes[n].first_out; } void next(Arc& arc) const { - if (arcs[arc.id].next_in != -1) { - arc.id = arcs[arc.id].next_in; + if (arcs[arc.id].next_out != -1) { + arc.id = arcs[arc.id].next_out; } else { int n; - for(n = nodes[arcs[arc.id].target].next; - n!=-1 && nodes[n].first_in == -1; + for(n = nodes[arcs[arc.id].source].next; + n != -1 && nodes[n].first_out == -1; n = nodes[n].next) {} - arc.id = (n == -1) ? -1 : nodes[n].first_in; + arc.id = (n == -1) ? -1 : nodes[n].first_out; } } @@ -311,31 +315,27 @@ ///A general directed graph structure. - ///\ref ListDigraph is a simple and fast directed graph - ///implementation based on static linked lists that are stored in + ///\ref ListDigraph is a versatile and fast directed graph + ///implementation based on linked lists that are stored in ///\c std::vector structures. /// - ///It conforms to the \ref concepts::Digraph "Digraph concept" and it - ///also provides several useful additional functionalities. - ///Most of the member functions and nested classes are documented + ///This type fully conforms to the \ref concepts::Digraph "Digraph concept" + ///and it also provides several useful additional functionalities. + ///Most of its member functions and nested classes are documented ///only in the concept class. /// + ///This class provides only linear time counting for nodes and arcs. + /// ///\sa concepts::Digraph - + ///\sa ListGraph class ListDigraph : public ExtendedListDigraphBase { typedef ExtendedListDigraphBase Parent; private: - ///ListDigraph is \e not copy constructible. Use copyDigraph() instead. - - ///ListDigraph is \e not copy constructible. Use copyDigraph() instead. - /// + /// Digraphs are \e not copy constructible. Use DigraphCopy instead. ListDigraph(const ListDigraph &) :ExtendedListDigraphBase() {}; - ///\brief Assignment of ListDigraph to another one is \e not allowed. - ///Use copyDigraph() instead. - - ///Assignment of ListDigraph to another one is \e not allowed. - ///Use copyDigraph() instead. + /// \brief Assignment of a digraph to another one is \e not allowed. + /// Use DigraphCopy instead. void operator=(const ListDigraph &) {} public: @@ -347,71 +347,72 @@ ///Add a new node to the digraph. - ///Add a new node to the digraph. + ///This function adds a new node to the digraph. ///\return The new node. Node addNode() { return Parent::addNode(); } ///Add a new arc to the digraph. - ///Add a new arc to the digraph with source node \c s + ///This function adds a new arc to the digraph with source node \c s ///and target node \c t. ///\return The new arc. - Arc addArc(const Node& s, const Node& t) { + Arc addArc(Node s, Node t) { return Parent::addArc(s, t); } ///\brief Erase a node from the digraph. /// - ///Erase a node from the digraph. + ///This function erases the given node along with its outgoing and + ///incoming arcs from the digraph. /// - void erase(const Node& n) { Parent::erase(n); } + ///\note All iterators referencing the removed node or the connected + ///arcs are invalidated, of course. + void erase(Node n) { Parent::erase(n); } ///\brief Erase an arc from the digraph. /// - ///Erase an arc from the digraph. + ///This function erases the given arc from the digraph. /// - void erase(const Arc& a) { Parent::erase(a); } + ///\note All iterators referencing the removed arc are invalidated, + ///of course. + void erase(Arc a) { Parent::erase(a); } /// Node validity check - /// This function gives back true if the given node is valid, - /// ie. it is a real node of the graph. + /// This function gives back \c true if the given node is valid, + /// i.e. it is a real node of the digraph. /// - /// \warning A Node pointing to a removed item - /// could become valid again later if new nodes are - /// added to the graph. + /// \warning A removed node could become valid again if new nodes are + /// added to the digraph. bool valid(Node n) const { return Parent::valid(n); } /// Arc validity check - /// This function gives back true if the given arc is valid, - /// ie. it is a real arc of the graph. + /// This function gives back \c true if the given arc is valid, + /// i.e. it is a real arc of the digraph. /// - /// \warning An Arc pointing to a removed item - /// could become valid again later if new nodes are - /// added to the graph. + /// \warning A removed arc could become valid again if new arcs are + /// added to the digraph. bool valid(Arc a) const { return Parent::valid(a); } - /// Change the target of \c a to \c n + /// Change the target node of an arc - /// Change the target of \c a to \c n + /// This function changes the target node of the given arc \c a to \c n. /// - ///\note The ArcIts and OutArcIts referencing - ///the changed arc remain valid. However InArcIts are - ///invalidated. + ///\note \c ArcIt and \c OutArcIt iterators referencing the changed + ///arc remain valid, but \c InArcIt iterators are invalidated. /// ///\warning This functionality cannot be used together with the Snapshot ///feature. void changeTarget(Arc a, Node n) { Parent::changeTarget(a,n); } - /// Change the source of \c a to \c n + /// Change the source node of an arc - /// Change the source of \c a to \c n + /// This function changes the source node of the given arc \c a to \c n. /// - ///\note The InArcIts referencing the changed arc remain - ///valid. However the ArcIts and OutArcIts are - ///invalidated. + ///\note \c InArcIt iterators referencing the changed arc remain + ///valid, but \c ArcIt and \c OutArcIt iterators are invalidated. /// ///\warning This functionality cannot be used together with the Snapshot ///feature. @@ -419,94 +420,76 @@ Parent::changeSource(a,n); } - /// Invert the direction of an arc. + /// Reverse the direction of an arc. - ///\note The ArcIts referencing the changed arc remain - ///valid. However OutArcIts and InArcIts are - ///invalidated. + /// This function reverses the direction of the given arc. + ///\note \c ArcIt, \c OutArcIt and \c InArcIt iterators referencing + ///the changed arc are invalidated. /// ///\warning This functionality cannot be used together with the Snapshot ///feature. - void reverseArc(Arc e) { - Node t=target(e); - changeTarget(e,source(e)); - changeSource(e,t); + void reverseArc(Arc a) { + Node t=target(a); + changeTarget(a,source(a)); + changeSource(a,t); } - /// Reserve memory for nodes. - - /// Using this function it is possible to avoid the superfluous memory - /// allocation: if you know that the digraph you want to build will - /// be very large (e.g. it will contain millions of nodes and/or arcs) - /// then it is worth reserving space for this amount before starting - /// to build the digraph. - /// \sa reserveArc - void reserveNode(int n) { nodes.reserve(n); }; - - /// Reserve memory for arcs. - - /// Using this function it is possible to avoid the superfluous memory - /// allocation: if you know that the digraph you want to build will - /// be very large (e.g. it will contain millions of nodes and/or arcs) - /// then it is worth reserving space for this amount before starting - /// to build the digraph. - /// \sa reserveNode - void reserveArc(int m) { arcs.reserve(m); }; - ///Contract two nodes. - ///This function contracts two nodes. - ///Node \p b will be removed but instead of deleting - ///incident arcs, they will be joined to \p a. - ///The last parameter \p r controls whether to remove loops. \c true - ///means that loops will be removed. + ///This function contracts the given two nodes. + ///Node \c v is removed, but instead of deleting its + ///incident arcs, they are joined to node \c u. + ///If the last parameter \c r is \c true (this is the default value), + ///then the newly created loops are removed. /// - ///\note The ArcIts referencing a moved arc remain - ///valid. However InArcIts and OutArcIts - ///may be invalidated. + ///\note The moved arcs are joined to node \c u using changeSource() + ///or changeTarget(), thus \c ArcIt and \c OutArcIt iterators are + ///invalidated for the outgoing arcs of node \c v and \c InArcIt + ///iterators are invalidated for the incomming arcs of \c v. + ///Moreover all iterators referencing node \c v or the removed + ///loops are also invalidated. Other iterators remain valid. /// ///\warning This functionality cannot be used together with the Snapshot ///feature. - void contract(Node a, Node b, bool r = true) + void contract(Node u, Node v, bool r = true) { - for(OutArcIt e(*this,b);e!=INVALID;) { + for(OutArcIt e(*this,v);e!=INVALID;) { OutArcIt f=e; ++f; - if(r && target(e)==a) erase(e); - else changeSource(e,a); + if(r && target(e)==u) erase(e); + else changeSource(e,u); e=f; } - for(InArcIt e(*this,b);e!=INVALID;) { + for(InArcIt e(*this,v);e!=INVALID;) { InArcIt f=e; ++f; - if(r && source(e)==a) erase(e); - else changeTarget(e,a); + if(r && source(e)==u) erase(e); + else changeTarget(e,u); e=f; } - erase(b); + erase(v); } ///Split a node. - ///This function splits a node. First a new node is added to the digraph, - ///then the source of each outgoing arc of \c n is moved to this new node. - ///If \c connect is \c true (this is the default value), then a new arc - ///from \c n to the newly created node is also added. + ///This function splits the given node. First, a new node is added + ///to the digraph, then the source of each outgoing arc of node \c n + ///is moved to this new node. + ///If the second parameter \c connect is \c true (this is the default + ///value), then a new arc from node \c n to the newly created node + ///is also added. ///\return The newly created node. /// - ///\note The ArcIts referencing a moved arc remain - ///valid. However InArcIts and OutArcIts may - ///be invalidated. + ///\note All iterators remain valid. /// - ///\warning This functionality cannot be used in conjunction with the + ///\warning This functionality cannot be used together with the ///Snapshot feature. Node split(Node n, bool connect = true) { Node b = addNode(); - for(OutArcIt e(*this,n);e!=INVALID;) { - OutArcIt f=e; - ++f; - changeSource(e,b); - e=f; + nodes[b.id].first_out=nodes[n.id].first_out; + nodes[n.id].first_out=-1; + for(int i=nodes[b.id].first_out; i!=-1; i=arcs[i].next_out) { + arcs[i].source=b.id; } if (connect) addArc(n,b); return b; @@ -514,21 +497,53 @@ ///Split an arc. - ///This function splits an arc. First a new node \c b is added to - ///the digraph, then the original arc is re-targeted to \c - ///b. Finally an arc from \c b to the original target is added. + ///This function splits the given arc. First, a new node \c v is + ///added to the digraph, then the target node of the original arc + ///is set to \c v. Finally, an arc from \c v to the original target + ///is added. + ///\return The newly created node. /// - ///\return The newly created node. + ///\note \c InArcIt iterators referencing the original arc are + ///invalidated. Other iterators remain valid. /// ///\warning This functionality cannot be used together with the ///Snapshot feature. - Node split(Arc e) { - Node b = addNode(); - addArc(b,target(e)); - changeTarget(e,b); - return b; + Node split(Arc a) { + Node v = addNode(); + addArc(v,target(a)); + changeTarget(a,v); + return v; } + ///Clear the digraph. + + ///This function erases all nodes and arcs from the digraph. + /// + ///\note All iterators of the digraph are invalidated, of course. + void clear() { + Parent::clear(); + } + + /// Reserve memory for nodes. + + /// Using this function, it is possible to avoid superfluous memory + /// allocation: if you know that the digraph you want to build will + /// be large (e.g. it will contain millions of nodes and/or arcs), + /// then it is worth reserving space for this amount before starting + /// to build the digraph. + /// \sa reserveArc() + void reserveNode(int n) { nodes.reserve(n); }; + + /// Reserve memory for arcs. + + /// Using this function, it is possible to avoid superfluous memory + /// allocation: if you know that the digraph you want to build will + /// be large (e.g. it will contain millions of nodes and/or arcs), + /// then it is worth reserving space for this amount before starting + /// to build the digraph. + /// \sa reserveNode() + void reserveArc(int m) { arcs.reserve(m); }; + /// \brief Class to make a snapshot of the digraph and restore /// it later. /// @@ -537,9 +552,15 @@ /// The newly added nodes and arcs can be removed using the /// restore() function. /// - /// \warning Arc and node deletions and other modifications (e.g. - /// contracting, splitting, reversing arcs or nodes) cannot be + /// \note After a state is restored, you cannot restore a later state, + /// i.e. you cannot add the removed nodes and arcs again using + /// another Snapshot instance. + /// + /// \warning Node and arc deletions and other modifications (e.g. + /// reversing, contracting, splitting arcs or nodes) cannot be /// restored. These events invalidate the snapshot. + /// However, the arcs and nodes that were added to the digraph after + /// making the current snapshot can be removed without invalidating it. class Snapshot { protected: @@ -709,39 +730,40 @@ /// \brief Default constructor. /// /// Default constructor. - /// To actually make a snapshot you must call save(). + /// You have to call save() to actually make a snapshot. Snapshot() : digraph(0), node_observer_proxy(*this), arc_observer_proxy(*this) {} /// \brief Constructor that immediately makes a snapshot. /// - /// This constructor immediately makes a snapshot of the digraph. - /// \param _digraph The digraph we make a snapshot of. - Snapshot(ListDigraph &_digraph) + /// This constructor immediately makes a snapshot of the given digraph. + Snapshot(ListDigraph &gr) : node_observer_proxy(*this), arc_observer_proxy(*this) { - attach(_digraph); + attach(gr); } /// \brief Make a snapshot. /// - /// Make a snapshot of the digraph. - /// - /// This function can be called more than once. In case of a repeated + /// This function makes a snapshot of the given digraph. + /// It can be called more than once. In case of a repeated /// call, the previous snapshot gets lost. - /// \param _digraph The digraph we make the snapshot of. - void save(ListDigraph &_digraph) { + void save(ListDigraph &gr) { if (attached()) { detach(); clear(); } - attach(_digraph); + attach(gr); } /// \brief Undo the changes until the last snapshot. - // - /// Undo the changes until the last snapshot created by save(). + /// + /// This function undos the changes until the last snapshot + /// created by save() or Snapshot(ListDigraph&). + /// + /// \warning This method invalidates the snapshot, i.e. repeated + /// restoring is not supported unless you call save() again. void restore() { detach(); for(std::list::iterator it = added_arcs.begin(); @@ -755,9 +777,9 @@ clear(); } - /// \brief Gives back true when the snapshot is valid. + /// \brief Returns \c true if the snapshot is valid. /// - /// Gives back true when the snapshot is valid. + /// This function returns \c true if the snapshot is valid. bool valid() const { return attached(); } @@ -795,10 +817,6 @@ typedef ListGraphBase Graph; - class Node; - class Arc; - class Edge; - class Node { friend class ListGraphBase; protected: @@ -848,8 +866,6 @@ bool operator<(const Arc& arc) const {return id < arc.id;} }; - - ListGraphBase() : nodes(), first_node(-1), first_free_node(-1), arcs(), first_free_arc(-1) {} @@ -1164,31 +1180,27 @@ ///A general undirected graph structure. - ///\ref ListGraph is a simple and fast undirected graph - ///implementation based on static linked lists that are stored in + ///\ref ListGraph is a versatile and fast undirected graph + ///implementation based on linked lists that are stored in ///\c std::vector structures. /// - ///It conforms to the \ref concepts::Graph "Graph concept" and it - ///also provides several useful additional functionalities. - ///Most of the member functions and nested classes are documented + ///This type fully conforms to the \ref concepts::Graph "Graph concept" + ///and it also provides several useful additional functionalities. + ///Most of its member functions and nested classes are documented ///only in the concept class. /// + ///This class provides only linear time counting for nodes, edges and arcs. + /// ///\sa concepts::Graph - + ///\sa ListDigraph class ListGraph : public ExtendedListGraphBase { typedef ExtendedListGraphBase Parent; private: - ///ListGraph is \e not copy constructible. Use copyGraph() instead. - - ///ListGraph is \e not copy constructible. Use copyGraph() instead. - /// + /// Graphs are \e not copy constructible. Use GraphCopy instead. ListGraph(const ListGraph &) :ExtendedListGraphBase() {}; - ///\brief Assignment of ListGraph to another one is \e not allowed. - ///Use copyGraph() instead. - - ///Assignment of ListGraph to another one is \e not allowed. - ///Use copyGraph() instead. + /// \brief Assignment of a graph to another one is \e not allowed. + /// Use GraphCopy instead. void operator=(const ListGraph &) {} public: /// Constructor @@ -1201,94 +1213,102 @@ /// \brief Add a new node to the graph. /// - /// Add a new node to the graph. + /// This function adds a new node to the graph. /// \return The new node. Node addNode() { return Parent::addNode(); } /// \brief Add a new edge to the graph. /// - /// Add a new edge to the graph with source node \c s - /// and target node \c t. + /// This function adds a new edge to the graph between nodes + /// \c u and \c v with inherent orientation from node \c u to + /// node \c v. /// \return The new edge. - Edge addEdge(const Node& s, const Node& t) { - return Parent::addEdge(s, t); + Edge addEdge(Node u, Node v) { + return Parent::addEdge(u, v); } - /// \brief Erase a node from the graph. + ///\brief Erase a node from the graph. /// - /// Erase a node from the graph. + /// This function erases the given node along with its incident arcs + /// from the graph. /// - void erase(const Node& n) { Parent::erase(n); } + /// \note All iterators referencing the removed node or the incident + /// edges are invalidated, of course. + void erase(Node n) { Parent::erase(n); } - /// \brief Erase an edge from the graph. + ///\brief Erase an edge from the graph. /// - /// Erase an edge from the graph. + /// This function erases the given edge from the graph. /// - void erase(const Edge& e) { Parent::erase(e); } + /// \note All iterators referencing the removed edge are invalidated, + /// of course. + void erase(Edge e) { Parent::erase(e); } /// Node validity check - /// This function gives back true if the given node is valid, - /// ie. it is a real node of the graph. + /// This function gives back \c true if the given node is valid, + /// i.e. it is a real node of the graph. /// - /// \warning A Node pointing to a removed item - /// could become valid again later if new nodes are + /// \warning A removed node could become valid again if new nodes are /// added to the graph. bool valid(Node n) const { return Parent::valid(n); } + /// Edge validity check + + /// This function gives back \c true if the given edge is valid, + /// i.e. it is a real edge of the graph. + /// + /// \warning A removed edge could become valid again if new edges are + /// added to the graph. + bool valid(Edge e) const { return Parent::valid(e); } /// Arc validity check - /// This function gives back true if the given arc is valid, - /// ie. it is a real arc of the graph. + /// This function gives back \c true if the given arc is valid, + /// i.e. it is a real arc of the graph. /// - /// \warning An Arc pointing to a removed item - /// could become valid again later if new edges are + /// \warning A removed arc could become valid again if new edges are /// added to the graph. bool valid(Arc a) const { return Parent::valid(a); } - /// Edge validity check - /// This function gives back true if the given edge is valid, - /// ie. it is a real arc of the graph. + /// \brief Change the first node of an edge. /// - /// \warning A Edge pointing to a removed item - /// could become valid again later if new edges are - /// added to the graph. - bool valid(Edge e) const { return Parent::valid(e); } - /// \brief Change the end \c u of \c e to \c n + /// This function changes the first node of the given edge \c e to \c n. /// - /// This function changes the end \c u of \c e to node \c n. - /// - ///\note The EdgeIts and ArcIts referencing the - ///changed edge are invalidated and if the changed node is the - ///base node of an iterator then this iterator is also - ///invalidated. + ///\note \c EdgeIt and \c ArcIt iterators referencing the + ///changed edge are invalidated and all other iterators whose + ///base node is the changed node are also invalidated. /// ///\warning This functionality cannot be used together with the ///Snapshot feature. void changeU(Edge e, Node n) { Parent::changeU(e,n); } - /// \brief Change the end \c v of \c e to \c n + /// \brief Change the second node of an edge. /// - /// This function changes the end \c v of \c e to \c n. + /// This function changes the second node of the given edge \c e to \c n. /// - ///\note The EdgeIts referencing the changed edge remain - ///valid, however ArcIts and if the changed node is the - ///base node of an iterator then this iterator is invalidated. + ///\note \c EdgeIt iterators referencing the changed edge remain + ///valid, but \c ArcIt iterators referencing the changed edge and + ///all other iterators whose base node is the changed node are also + ///invalidated. /// ///\warning This functionality cannot be used together with the ///Snapshot feature. void changeV(Edge e, Node n) { Parent::changeV(e,n); } + /// \brief Contract two nodes. /// - /// This function contracts two nodes. - /// Node \p b will be removed but instead of deleting - /// its neighboring arcs, they will be joined to \p a. - /// The last parameter \p r controls whether to remove loops. \c true - /// means that loops will be removed. + /// This function contracts the given two nodes. + /// Node \c b is removed, but instead of deleting + /// its incident edges, they are joined to node \c a. + /// If the last parameter \c r is \c true (this is the default value), + /// then the newly created loops are removed. /// - /// \note The ArcIts referencing a moved arc remain - /// valid. + /// \note The moved edges are joined to node \c a using changeU() + /// or changeV(), thus all edge and arc iterators whose base node is + /// \c b are invalidated. + /// Moreover all iterators referencing node \c b or the removed + /// loops are also invalidated. Other iterators remain valid. /// ///\warning This functionality cannot be used together with the ///Snapshot feature. @@ -1307,6 +1327,34 @@ erase(b); } + ///Clear the graph. + + ///This function erases all nodes and arcs from the graph. + /// + ///\note All iterators of the graph are invalidated, of course. + void clear() { + Parent::clear(); + } + + /// Reserve memory for nodes. + + /// Using this function, it is possible to avoid superfluous memory + /// allocation: if you know that the graph you want to build will + /// be large (e.g. it will contain millions of nodes and/or edges), + /// then it is worth reserving space for this amount before starting + /// to build the graph. + /// \sa reserveEdge() + void reserveNode(int n) { nodes.reserve(n); }; + + /// Reserve memory for edges. + + /// Using this function, it is possible to avoid superfluous memory + /// allocation: if you know that the graph you want to build will + /// be large (e.g. it will contain millions of nodes and/or edges), + /// then it is worth reserving space for this amount before starting + /// to build the graph. + /// \sa reserveNode() + void reserveEdge(int m) { arcs.reserve(2 * m); }; /// \brief Class to make a snapshot of the graph and restore /// it later. @@ -1316,9 +1364,15 @@ /// The newly added nodes and edges can be removed /// using the restore() function. /// - /// \warning Edge and node deletions and other modifications - /// (e.g. changing nodes of edges, contracting nodes) cannot be - /// restored. These events invalidate the snapshot. + /// \note After a state is restored, you cannot restore a later state, + /// i.e. you cannot add the removed nodes and edges again using + /// another Snapshot instance. + /// + /// \warning Node and edge deletions and other modifications + /// (e.g. changing the end-nodes of edges or contracting nodes) + /// cannot be restored. These events invalidate the snapshot. + /// However, the edges and nodes that were added to the graph after + /// making the current snapshot can be removed without invalidating it. class Snapshot { protected: @@ -1488,39 +1542,40 @@ /// \brief Default constructor. /// /// Default constructor. - /// To actually make a snapshot you must call save(). + /// You have to call save() to actually make a snapshot. Snapshot() : graph(0), node_observer_proxy(*this), edge_observer_proxy(*this) {} /// \brief Constructor that immediately makes a snapshot. /// - /// This constructor immediately makes a snapshot of the graph. - /// \param _graph The graph we make a snapshot of. - Snapshot(ListGraph &_graph) + /// This constructor immediately makes a snapshot of the given graph. + Snapshot(ListGraph &gr) : node_observer_proxy(*this), edge_observer_proxy(*this) { - attach(_graph); + attach(gr); } /// \brief Make a snapshot. /// - /// Make a snapshot of the graph. - /// - /// This function can be called more than once. In case of a repeated + /// This function makes a snapshot of the given graph. + /// It can be called more than once. In case of a repeated /// call, the previous snapshot gets lost. - /// \param _graph The graph we make the snapshot of. - void save(ListGraph &_graph) { + void save(ListGraph &gr) { if (attached()) { detach(); clear(); } - attach(_graph); + attach(gr); } /// \brief Undo the changes until the last snapshot. - // - /// Undo the changes until the last snapshot created by save(). + /// + /// This function undos the changes until the last snapshot + /// created by save() or Snapshot(ListGraph&). + /// + /// \warning This method invalidates the snapshot, i.e. repeated + /// restoring is not supported unless you call save() again. void restore() { detach(); for(std::list::iterator it = added_edges.begin(); @@ -1534,9 +1589,9 @@ clear(); } - /// \brief Gives back true when the snapshot is valid. + /// \brief Returns \c true if the snapshot is valid. /// - /// Gives back true when the snapshot is valid. + /// This function returns \c true if the snapshot is valid. bool valid() const { return attached(); } diff --git a/lemon/lp_base.h b/lemon/lp_base.h --- a/lemon/lp_base.h +++ b/lemon/lp_base.h @@ -146,7 +146,7 @@ ///Iterator for iterate over the columns of an LP problem - /// Its usage is quite simple, for example you can count the number + /// Its usage is quite simple, for example, you can count the number /// of columns in an LP \c lp: ///\code /// int count=0; @@ -241,7 +241,7 @@ ///Iterator for iterate over the rows of an LP problem - /// Its usage is quite simple, for example you can count the number + /// Its usage is quite simple, for example, you can count the number /// of rows in an LP \c lp: ///\code /// int count=0; @@ -943,6 +943,14 @@ virtual int _addCol() = 0; virtual int _addRow() = 0; + virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u) { + int row = _addRow(); + _setRowCoeffs(row, b, e); + _setRowLowerBound(row, l); + _setRowUpperBound(row, u); + return row; + } + virtual void _eraseCol(int col) = 0; virtual void _eraseRow(int row) = 0; @@ -1207,8 +1215,10 @@ ///\param u is the upper bound (\ref INF means no bound) ///\return The created row. Row addRow(Value l,const Expr &e, Value u) { - Row r=addRow(); - row(r,l,e,u); + Row r; + e.simplify(); + r._id = _addRowId(_addRow(l - *e, ExprIterator(e.comps.begin(), cols), + ExprIterator(e.comps.end(), cols), u - *e)); return r; } @@ -1217,8 +1227,12 @@ ///\param c is a linear expression (see \ref Constr) ///\return The created row. Row addRow(const Constr &c) { - Row r=addRow(); - row(r,c); + Row r; + c.expr().simplify(); + r._id = _addRowId(_addRow(c.lowerBounded()?c.lowerBound():-INF, + ExprIterator(c.expr().comps.begin(), cols), + ExprIterator(c.expr().comps.end(), cols), + c.upperBounded()?c.upperBound():INF)); return r; } ///Erase a column (i.e a variable) from the LP diff --git a/lemon/lp_skeleton.cc b/lemon/lp_skeleton.cc --- a/lemon/lp_skeleton.cc +++ b/lemon/lp_skeleton.cc @@ -32,6 +32,11 @@ return ++row_num; } + int SkeletonSolverBase::_addRow(Value, ExprIterator, ExprIterator, Value) + { + return ++row_num; + } + void SkeletonSolverBase::_eraseCol(int) {} void SkeletonSolverBase::_eraseRow(int) {} diff --git a/lemon/lp_skeleton.h b/lemon/lp_skeleton.h --- a/lemon/lp_skeleton.h +++ b/lemon/lp_skeleton.h @@ -45,6 +45,8 @@ /// \e virtual int _addRow(); /// \e + virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u); + /// \e virtual void _eraseCol(int i); /// \e virtual void _eraseRow(int i); diff --git a/lemon/maps.h b/lemon/maps.h --- a/lemon/maps.h +++ b/lemon/maps.h @@ -56,7 +56,7 @@ /// its type definitions, or if you have to provide a writable map, /// but data written to it is not required (i.e. it will be sent to /// /dev/null). - /// It conforms the \ref concepts::ReadWriteMap "ReadWriteMap" concept. + /// It conforms to the \ref concepts::ReadWriteMap "ReadWriteMap" concept. /// /// \sa ConstMap template @@ -89,7 +89,7 @@ /// value to each key. /// /// In other aspects it is equivalent to \c NullMap. - /// So it conforms the \ref concepts::ReadWriteMap "ReadWriteMap" + /// So it conforms to the \ref concepts::ReadWriteMap "ReadWriteMap" /// concept, but it absorbs the data written to it. /// /// The simplest way of using this map is through the constMap() @@ -158,7 +158,7 @@ /// value to each key. /// /// In other aspects it is equivalent to \c NullMap. - /// So it conforms the \ref concepts::ReadWriteMap "ReadWriteMap" + /// So it conforms to the \ref concepts::ReadWriteMap "ReadWriteMap" /// concept, but it absorbs the data written to it. /// /// The simplest way of using this map is through the constMap() @@ -230,10 +230,10 @@ /// /// This map is essentially a wrapper for \c std::vector. It assigns /// values to integer keys from the range [0..size-1]. - /// It can be used with some data structures, for example - /// \c UnionFind, \c BinHeap, when the used items are small - /// integers. This map conforms the \ref concepts::ReferenceMap - /// "ReferenceMap" concept. + /// It can be used together with some data structures, e.g. + /// heap types and \c UnionFind, when the used items are small + /// integers. This map conforms to the \ref concepts::ReferenceMap + /// "ReferenceMap" concept. /// /// The simplest way of using this map is through the rangeMap() /// function. @@ -340,7 +340,7 @@ /// that you can specify a default value for the keys that are not /// stored actually. This value can be different from the default /// contructed value (i.e. \c %Value()). - /// This type conforms the \ref concepts::ReferenceMap "ReferenceMap" + /// This type conforms to the \ref concepts::ReferenceMap "ReferenceMap" /// concept. /// /// This map is useful if a default value should be assigned to most of @@ -348,9 +348,9 @@ /// keys (i.e. the map is "sparse"). /// The name of this type also refers to this important usage. /// - /// Apart form that this map can be used in many other cases since it + /// Apart form that, this map can be used in many other cases since it /// is based on \c std::map, which is a general associative container. - /// However keep in mind that it is usually not as efficient as other + /// However, keep in mind that it is usually not as efficient as other /// maps. /// /// The simplest way of using this map is through the sparseMap() @@ -706,7 +706,7 @@ /// "readable map" to another type using the default conversion. /// The \c Key type of it is inherited from \c M and the \c Value /// type is \c V. - /// This type conforms the \ref concepts::ReadMap "ReadMap" concept. + /// This type conforms to the \ref concepts::ReadMap "ReadMap" concept. /// /// The simplest way of using this map is through the convertMap() /// function. @@ -1785,22 +1785,22 @@ /// /// The most important usage of it is storing certain nodes or arcs /// that were marked \c true by an algorithm. - /// For example it makes easier to store the nodes in the processing + /// For example, it makes easier to store the nodes in the processing /// order of Dfs algorithm, as the following examples show. /// \code /// std::vector v; - /// dfs(g,s).processedMap(loggerBoolMap(std::back_inserter(v))).run(); + /// dfs(g).processedMap(loggerBoolMap(std::back_inserter(v))).run(s); /// \endcode /// \code /// std::vector v(countNodes(g)); - /// dfs(g,s).processedMap(loggerBoolMap(v.begin())).run(); + /// dfs(g).processedMap(loggerBoolMap(v.begin())).run(s); /// \endcode /// /// \note The container of the iterator must contain enough space /// for the elements or the iterator should be an inserter iterator. /// /// \note LoggerBoolMap is just \ref concepts::WriteMap "writable", so - /// it cannot be used when a readable map is needed, for example as + /// it cannot be used when a readable map is needed, for example, as /// \c ReachedMap for \c Bfs, \c Dfs and \c Dijkstra algorithms. /// /// \relates LoggerBoolMap @@ -1825,7 +1825,7 @@ /// Using this map you get access (i.e. can read) the inner id values of /// the items stored in the graph, which is returned by the \c id() /// function of the graph. This map can be inverted with its member - /// class \c InverseMap or with the \c operator() member. + /// class \c InverseMap or with the \c operator()() member. /// /// \tparam GR The graph type. /// \tparam K The key type of the map (\c GR::Node, \c GR::Arc or @@ -1865,9 +1865,11 @@ public: - /// \brief This class represents the inverse of its owner (IdMap). + /// \brief The inverse map type of IdMap. /// - /// This class represents the inverse of its owner (IdMap). + /// The inverse map type of IdMap. The subscript operator gives back + /// an item by its id. + /// This type conforms to the \ref concepts::ReadMap "ReadMap" concept. /// \see inverse() class InverseMap { public: @@ -1882,9 +1884,9 @@ /// Constructor for creating an id-to-item map. explicit InverseMap(const IdMap& map) : _graph(map._graph) {} - /// \brief Gives back the given item from its id. + /// \brief Gives back an item by its id. /// - /// Gives back the given item from its id. + /// Gives back an item by its id. Item operator[](int id) const { return _graph->fromId(id, Item());} private: @@ -1897,14 +1899,31 @@ InverseMap inverse() const { return InverseMap(*_graph);} }; + /// \brief Returns an \c IdMap class. + /// + /// This function just returns an \c IdMap class. + /// \relates IdMap + template + inline IdMap idMap(const GR& graph) { + return IdMap(graph); + } /// \brief General cross reference graph map type. /// This class provides simple invertable graph maps. /// It wraps a standard graph map (\c NodeMap, \c ArcMap or \c EdgeMap) /// and if a key is set to a new value, then stores it in the inverse map. - /// The values of the map can be accessed - /// with stl compatible forward iterator. + /// The graph items can be accessed by their values either using + /// \c InverseMap or \c operator()(), and the values of the map can be + /// accessed with an STL compatible forward iterator (\c ValueIt). + /// + /// This map is intended to be used when all associated values are + /// different (the map is actually invertable) or there are only a few + /// items with the same value. + /// Otherwise consider to use \c IterableValueMap, which is more + /// suitable and more efficient for such cases. It provides iterators + /// to traverse the items with the same associated value, but + /// it does not have \c InverseMap. /// /// This type is not reference map, so it cannot be modified with /// the subscript operator. @@ -1945,56 +1964,66 @@ /// \brief Forward iterator for values. /// - /// This iterator is an stl compatible forward + /// This iterator is an STL compatible forward /// iterator on the values of the map. The values can /// be accessed in the [beginValue, endValue) range. /// They are considered with multiplicity, so each value is /// traversed for each item it is assigned to. - class ValueIterator + class ValueIt : public std::iterator { friend class CrossRefMap; private: - ValueIterator(typename Container::const_iterator _it) + ValueIt(typename Container::const_iterator _it) : it(_it) {} public: - ValueIterator() {} - - ValueIterator& operator++() { ++it; return *this; } - ValueIterator operator++(int) { - ValueIterator tmp(*this); + /// Constructor + ValueIt() {} + + /// \e + ValueIt& operator++() { ++it; return *this; } + /// \e + ValueIt operator++(int) { + ValueIt tmp(*this); operator++(); return tmp; } + /// \e const Value& operator*() const { return it->first; } + /// \e const Value* operator->() const { return &(it->first); } - bool operator==(ValueIterator jt) const { return it == jt.it; } - bool operator!=(ValueIterator jt) const { return it != jt.it; } + /// \e + bool operator==(ValueIt jt) const { return it == jt.it; } + /// \e + bool operator!=(ValueIt jt) const { return it != jt.it; } private: typename Container::const_iterator it; }; + + /// Alias for \c ValueIt + typedef ValueIt ValueIterator; /// \brief Returns an iterator to the first value. /// - /// Returns an stl compatible iterator to the + /// Returns an STL compatible iterator to the /// first value of the map. The values of the /// map can be accessed in the [beginValue, endValue) /// range. - ValueIterator beginValue() const { - return ValueIterator(_inv_map.begin()); + ValueIt beginValue() const { + return ValueIt(_inv_map.begin()); } /// \brief Returns an iterator after the last value. /// - /// Returns an stl compatible iterator after the + /// Returns an STL compatible iterator after the /// last value of the map. The values of the /// map can be accessed in the [beginValue, endValue) /// range. - ValueIterator endValue() const { - return ValueIterator(_inv_map.end()); + ValueIt endValue() const { + return ValueIt(_inv_map.end()); } /// \brief Sets the value associated with the given key. @@ -2032,6 +2061,14 @@ typename Container::const_iterator it = _inv_map.find(val); return it != _inv_map.end() ? it->second : INVALID; } + + /// \brief Returns the number of items with the given value. + /// + /// This function returns the number of items with the given value + /// associated with it. + int count(const Value &val) const { + return _inv_map.count(val); + } protected: @@ -2082,10 +2119,12 @@ public: - /// \brief The inverse map type. + /// \brief The inverse map type of CrossRefMap. /// - /// The inverse of this map. The subscript operator of the map - /// gives back the item that was last assigned to the value. + /// The inverse map type of CrossRefMap. The subscript operator gives + /// back an item by its value. + /// This type conforms to the \ref concepts::ReadMap "ReadMap" concept. + /// \see inverse() class InverseMap { public: /// \brief Constructor @@ -2112,20 +2151,20 @@ const CrossRefMap& _inverted; }; - /// \brief It gives back the read-only inverse map. + /// \brief Gives back the inverse of the map. /// - /// It gives back the read-only inverse map. + /// Gives back the inverse of the CrossRefMap. InverseMap inverse() const { return InverseMap(*this); } }; - /// \brief Provides continuous and unique ID for the + /// \brief Provides continuous and unique id for the /// items of a graph. /// /// RangeIdMap provides a unique and continuous - /// ID for each item of a given type (\c Node, \c Arc or + /// id for each item of a given type (\c Node, \c Arc or /// \c Edge) in a graph. This id is /// - \b unique: different items get different ids, /// - \b continuous: the range of the ids is the set of integers @@ -2136,7 +2175,7 @@ /// Thus this id is not (necessarily) the same as what can get using /// the \c id() function of the graph or \ref IdMap. /// This map can be inverted with its member class \c InverseMap, - /// or with the \c operator() member. + /// or with the \c operator()() member. /// /// \tparam GR The graph type. /// \tparam K The key type of the map (\c GR::Node, \c GR::Arc or @@ -2264,16 +2303,16 @@ _inv_map[pi] = q; } - /// \brief Gives back the \e RangeId of the item + /// \brief Gives back the \e range \e id of the item /// - /// Gives back the \e RangeId of the item. + /// Gives back the \e range \e id of the item. int operator[](const Item& item) const { return Map::operator[](item); } - /// \brief Gives back the item belonging to a \e RangeId + /// \brief Gives back the item belonging to a \e range \e id /// - /// Gives back the item belonging to a \e RangeId. + /// Gives back the item belonging to the given \e range \e id. Item operator()(int id) const { return _inv_map[id]; } @@ -2287,7 +2326,9 @@ /// \brief The inverse map type of RangeIdMap. /// - /// The inverse map type of RangeIdMap. + /// The inverse map type of RangeIdMap. The subscript operator gives + /// back an item by its \e range \e id. + /// This type conforms to the \ref concepts::ReadMap "ReadMap" concept. class InverseMap { public: /// \brief Constructor @@ -2305,7 +2346,7 @@ /// \brief Subscript operator. /// /// Subscript operator. It gives back the item - /// that the descriptor currently belongs to. + /// that the given \e range \e id currently belongs to. Value operator[](const Key& key) const { return _inverted(key); } @@ -2323,18 +2364,27 @@ /// \brief Gives back the inverse of the map. /// - /// Gives back the inverse of the map. + /// Gives back the inverse of the RangeIdMap. const InverseMap inverse() const { return InverseMap(*this); } }; + /// \brief Returns a \c RangeIdMap class. + /// + /// This function just returns an \c RangeIdMap class. + /// \relates RangeIdMap + template + inline RangeIdMap rangeIdMap(const GR& graph) { + return RangeIdMap(graph); + } + /// \brief Dynamic iterable \c bool map. /// /// This class provides a special graph map type which can store a /// \c bool value for graph items (\c Node, \c Arc or \c Edge). /// For both \c true and \c false values it is possible to iterate on - /// the keys. + /// the keys mapped to the value. /// /// This type is a reference map, so it can be modified with the /// subscript operator. @@ -2703,6 +2753,11 @@ /// For each non-negative value it is possible to iterate on the keys /// mapped to the value. /// + /// This map is intended to be used with small integer values, for which + /// it is efficient, and supports iteration only for non-negative values. + /// If you need large values and/or iteration for negative integers, + /// consider to use \ref IterableValueMap instead. + /// /// This type is a reference map, so it can be modified with the /// subscript operator. /// @@ -2984,15 +3039,17 @@ /// \brief Dynamic iterable map for comparable values. /// - /// This class provides a special graph map type which can store an + /// This class provides a special graph map type which can store a /// comparable value for graph items (\c Node, \c Arc or \c Edge). /// For each value it is possible to iterate on the keys mapped to - /// the value. + /// the value (\c ItemIt), and the values of the map can be accessed + /// with an STL compatible forward iterator (\c ValueIt). + /// The map stores a linked list for each value, which contains + /// the items mapped to the value, and the used values are stored + /// in balanced binary tree (\c std::map). /// - /// The map stores for each value a linked list with - /// the items which mapped to the value, and the values are stored - /// in balanced binary tree. The values of the map can be accessed - /// with stl compatible forward iterator. + /// \ref IterableBoolMap and \ref IterableIntMap are similar classes + /// specialized for \c bool and \c int values, respectively. /// /// This type is not reference map, so it cannot be modified with /// the subscript operator. @@ -3071,31 +3128,38 @@ /// \brief Forward iterator for values. /// - /// This iterator is an stl compatible forward + /// This iterator is an STL compatible forward /// iterator on the values of the map. The values can /// be accessed in the [beginValue, endValue) range. - class ValueIterator + class ValueIt : public std::iterator { friend class IterableValueMap; private: - ValueIterator(typename std::map::const_iterator _it) + ValueIt(typename std::map::const_iterator _it) : it(_it) {} public: - ValueIterator() {} - - ValueIterator& operator++() { ++it; return *this; } - ValueIterator operator++(int) { - ValueIterator tmp(*this); + /// Constructor + ValueIt() {} + + /// \e + ValueIt& operator++() { ++it; return *this; } + /// \e + ValueIt operator++(int) { + ValueIt tmp(*this); operator++(); return tmp; } + /// \e const Value& operator*() const { return it->first; } + /// \e const Value* operator->() const { return &(it->first); } - bool operator==(ValueIterator jt) const { return it == jt.it; } - bool operator!=(ValueIterator jt) const { return it != jt.it; } + /// \e + bool operator==(ValueIt jt) const { return it == jt.it; } + /// \e + bool operator!=(ValueIt jt) const { return it != jt.it; } private: typename std::map::const_iterator it; @@ -3103,22 +3167,22 @@ /// \brief Returns an iterator to the first value. /// - /// Returns an stl compatible iterator to the + /// Returns an STL compatible iterator to the /// first value of the map. The values of the /// map can be accessed in the [beginValue, endValue) /// range. - ValueIterator beginValue() const { - return ValueIterator(_first.begin()); + ValueIt beginValue() const { + return ValueIt(_first.begin()); } /// \brief Returns an iterator after the last value. /// - /// Returns an stl compatible iterator after the + /// Returns an STL compatible iterator after the /// last value of the map. The values of the /// map can be accessed in the [beginValue, endValue) /// range. - ValueIterator endValue() const { - return ValueIterator(_first.end()); + ValueIt endValue() const { + return ValueIt(_first.end()); } /// \brief Set operation of the map. @@ -3236,9 +3300,9 @@ class SourceMap { public: - ///\e + /// The key type (the \c Arc type of the digraph). typedef typename GR::Arc Key; - ///\e + /// The value type (the \c Node type of the digraph). typedef typename GR::Node Value; /// \brief Constructor @@ -3277,9 +3341,9 @@ class TargetMap { public: - ///\e + /// The key type (the \c Arc type of the digraph). typedef typename GR::Arc Key; - ///\e + /// The value type (the \c Node type of the digraph). typedef typename GR::Node Value; /// \brief Constructor @@ -3319,8 +3383,10 @@ class ForwardMap { public: + /// The key type (the \c Edge type of the digraph). + typedef typename GR::Edge Key; + /// The value type (the \c Arc type of the digraph). typedef typename GR::Arc Value; - typedef typename GR::Edge Key; /// \brief Constructor /// @@ -3359,8 +3425,10 @@ class BackwardMap { public: + /// The key type (the \c Edge type of the digraph). + typedef typename GR::Edge Key; + /// The value type (the \c Arc type of the digraph). typedef typename GR::Arc Value; - typedef typename GR::Edge Key; /// \brief Constructor /// @@ -3398,7 +3466,7 @@ /// \warning Besides \c addNode() and \c addArc(), a digraph structure /// may provide alternative ways to modify the digraph. /// The correct behavior of InDegMap is not guarantied if these additional - /// features are used. For example the functions + /// features are used. For example, the functions /// \ref ListDigraph::changeSource() "changeSource()", /// \ref ListDigraph::changeTarget() "changeTarget()" and /// \ref ListDigraph::reverseArc() "reverseArc()" @@ -3528,7 +3596,7 @@ /// \warning Besides \c addNode() and \c addArc(), a digraph structure /// may provide alternative ways to modify the digraph. /// The correct behavior of OutDegMap is not guarantied if these additional - /// features are used. For example the functions + /// features are used. For example, the functions /// \ref ListDigraph::changeSource() "changeSource()", /// \ref ListDigraph::changeTarget() "changeTarget()" and /// \ref ListDigraph::reverseArc() "reverseArc()" @@ -3696,6 +3764,293 @@ return PotentialDifferenceMap(gr, potential); } + + /// \brief Copy the values of a graph map to another map. + /// + /// This function copies the values of a graph map to another graph map. + /// \c To::Key must be equal or convertible to \c From::Key and + /// \c From::Value must be equal or convertible to \c To::Value. + /// + /// For example, an edge map of \c int value type can be copied to + /// an arc map of \c double value type in an undirected graph, but + /// an arc map cannot be copied to an edge map. + /// Note that even a \ref ConstMap can be copied to a standard graph map, + /// but \ref mapFill() can also be used for this purpose. + /// + /// \param gr The graph for which the maps are defined. + /// \param from The map from which the values have to be copied. + /// It must conform to the \ref concepts::ReadMap "ReadMap" concept. + /// \param to The map to which the values have to be copied. + /// It must conform to the \ref concepts::WriteMap "WriteMap" concept. + template + void mapCopy(const GR& gr, const From& from, To& to) { + typedef typename To::Key Item; + typedef typename ItemSetTraits::ItemIt ItemIt; + + for (ItemIt it(gr); it != INVALID; ++it) { + to.set(it, from[it]); + } + } + + /// \brief Compare two graph maps. + /// + /// This function compares the values of two graph maps. It returns + /// \c true if the maps assign the same value for all items in the graph. + /// The \c Key type of the maps (\c Node, \c Arc or \c Edge) must be equal + /// and their \c Value types must be comparable using \c %operator==(). + /// + /// \param gr The graph for which the maps are defined. + /// \param map1 The first map. + /// \param map2 The second map. + template + bool mapCompare(const GR& gr, const Map1& map1, const Map2& map2) { + typedef typename Map2::Key Item; + typedef typename ItemSetTraits::ItemIt ItemIt; + + for (ItemIt it(gr); it != INVALID; ++it) { + if (!(map1[it] == map2[it])) return false; + } + return true; + } + + /// \brief Return an item having minimum value of a graph map. + /// + /// This function returns an item (\c Node, \c Arc or \c Edge) having + /// minimum value of the given graph map. + /// If the item set is empty, it returns \c INVALID. + /// + /// \param gr The graph for which the map is defined. + /// \param map The graph map. + template + typename Map::Key mapMin(const GR& gr, const Map& map) { + return mapMin(gr, map, std::less()); + } + + /// \brief Return an item having minimum value of a graph map. + /// + /// This function returns an item (\c Node, \c Arc or \c Edge) having + /// minimum value of the given graph map. + /// If the item set is empty, it returns \c INVALID. + /// + /// \param gr The graph for which the map is defined. + /// \param map The graph map. + /// \param comp Comparison function object. + template + typename Map::Key mapMin(const GR& gr, const Map& map, const Comp& comp) { + typedef typename Map::Key Item; + typedef typename Map::Value Value; + typedef typename ItemSetTraits::ItemIt ItemIt; + + ItemIt min_item(gr); + if (min_item == INVALID) return INVALID; + Value min = map[min_item]; + for (ItemIt it(gr); it != INVALID; ++it) { + if (comp(map[it], min)) { + min = map[it]; + min_item = it; + } + } + return min_item; + } + + /// \brief Return an item having maximum value of a graph map. + /// + /// This function returns an item (\c Node, \c Arc or \c Edge) having + /// maximum value of the given graph map. + /// If the item set is empty, it returns \c INVALID. + /// + /// \param gr The graph for which the map is defined. + /// \param map The graph map. + template + typename Map::Key mapMax(const GR& gr, const Map& map) { + return mapMax(gr, map, std::less()); + } + + /// \brief Return an item having maximum value of a graph map. + /// + /// This function returns an item (\c Node, \c Arc or \c Edge) having + /// maximum value of the given graph map. + /// If the item set is empty, it returns \c INVALID. + /// + /// \param gr The graph for which the map is defined. + /// \param map The graph map. + /// \param comp Comparison function object. + template + typename Map::Key mapMax(const GR& gr, const Map& map, const Comp& comp) { + typedef typename Map::Key Item; + typedef typename Map::Value Value; + typedef typename ItemSetTraits::ItemIt ItemIt; + + ItemIt max_item(gr); + if (max_item == INVALID) return INVALID; + Value max = map[max_item]; + for (ItemIt it(gr); it != INVALID; ++it) { + if (comp(max, map[it])) { + max = map[it]; + max_item = it; + } + } + return max_item; + } + + /// \brief Return the minimum value of a graph map. + /// + /// This function returns the minimum value of the given graph map. + /// The corresponding item set of the graph must not be empty. + /// + /// \param gr The graph for which the map is defined. + /// \param map The graph map. + template + typename Map::Value mapMinValue(const GR& gr, const Map& map) { + return map[mapMin(gr, map, std::less())]; + } + + /// \brief Return the minimum value of a graph map. + /// + /// This function returns the minimum value of the given graph map. + /// The corresponding item set of the graph must not be empty. + /// + /// \param gr The graph for which the map is defined. + /// \param map The graph map. + /// \param comp Comparison function object. + template + typename Map::Value + mapMinValue(const GR& gr, const Map& map, const Comp& comp) { + return map[mapMin(gr, map, comp)]; + } + + /// \brief Return the maximum value of a graph map. + /// + /// This function returns the maximum value of the given graph map. + /// The corresponding item set of the graph must not be empty. + /// + /// \param gr The graph for which the map is defined. + /// \param map The graph map. + template + typename Map::Value mapMaxValue(const GR& gr, const Map& map) { + return map[mapMax(gr, map, std::less())]; + } + + /// \brief Return the maximum value of a graph map. + /// + /// This function returns the maximum value of the given graph map. + /// The corresponding item set of the graph must not be empty. + /// + /// \param gr The graph for which the map is defined. + /// \param map The graph map. + /// \param comp Comparison function object. + template + typename Map::Value + mapMaxValue(const GR& gr, const Map& map, const Comp& comp) { + return map[mapMax(gr, map, comp)]; + } + + /// \brief Return an item having a specified value in a graph map. + /// + /// This function returns an item (\c Node, \c Arc or \c Edge) having + /// the specified assigned value in the given graph map. + /// If no such item exists, it returns \c INVALID. + /// + /// \param gr The graph for which the map is defined. + /// \param map The graph map. + /// \param val The value that have to be found. + template + typename Map::Key + mapFind(const GR& gr, const Map& map, const typename Map::Value& val) { + typedef typename Map::Key Item; + typedef typename ItemSetTraits::ItemIt ItemIt; + + for (ItemIt it(gr); it != INVALID; ++it) { + if (map[it] == val) return it; + } + return INVALID; + } + + /// \brief Return an item having value for which a certain predicate is + /// true in a graph map. + /// + /// This function returns an item (\c Node, \c Arc or \c Edge) having + /// such assigned value for which the specified predicate is true + /// in the given graph map. + /// If no such item exists, it returns \c INVALID. + /// + /// \param gr The graph for which the map is defined. + /// \param map The graph map. + /// \param pred The predicate function object. + template + typename Map::Key + mapFindIf(const GR& gr, const Map& map, const Pred& pred) { + typedef typename Map::Key Item; + typedef typename ItemSetTraits::ItemIt ItemIt; + + for (ItemIt it(gr); it != INVALID; ++it) { + if (pred(map[it])) return it; + } + return INVALID; + } + + /// \brief Return the number of items having a specified value in a + /// graph map. + /// + /// This function returns the number of items (\c Node, \c Arc or \c Edge) + /// having the specified assigned value in the given graph map. + /// + /// \param gr The graph for which the map is defined. + /// \param map The graph map. + /// \param val The value that have to be counted. + template + int mapCount(const GR& gr, const Map& map, const typename Map::Value& val) { + typedef typename Map::Key Item; + typedef typename ItemSetTraits::ItemIt ItemIt; + + int cnt = 0; + for (ItemIt it(gr); it != INVALID; ++it) { + if (map[it] == val) ++cnt; + } + return cnt; + } + + /// \brief Return the number of items having values for which a certain + /// predicate is true in a graph map. + /// + /// This function returns the number of items (\c Node, \c Arc or \c Edge) + /// having such assigned values for which the specified predicate is true + /// in the given graph map. + /// + /// \param gr The graph for which the map is defined. + /// \param map The graph map. + /// \param pred The predicate function object. + template + int mapCountIf(const GR& gr, const Map& map, const Pred& pred) { + typedef typename Map::Key Item; + typedef typename ItemSetTraits::ItemIt ItemIt; + + int cnt = 0; + for (ItemIt it(gr); it != INVALID; ++it) { + if (pred(map[it])) ++cnt; + } + return cnt; + } + + /// \brief Fill a graph map with a certain value. + /// + /// This function sets the specified value for all items (\c Node, + /// \c Arc or \c Edge) in the given graph map. + /// + /// \param gr The graph for which the map is defined. + /// \param map The graph map. It must conform to the + /// \ref concepts::WriteMap "WriteMap" concept. + /// \param val The value. + template + void mapFill(const GR& gr, Map& map, const typename Map::Value& val) { + typedef typename Map::Key Item; + typedef typename ItemSetTraits::ItemIt ItemIt; + + for (ItemIt it(gr); it != INVALID; ++it) { + map.set(it, val); + } + } + /// @} } diff --git a/lemon/min_cost_arborescence.h b/lemon/min_cost_arborescence.h --- a/lemon/min_cost_arborescence.h +++ b/lemon/min_cost_arborescence.h @@ -488,8 +488,8 @@ /// \name Execution Control /// The simplest way to execute the algorithm is to use /// one of the member functions called \c run(...). \n - /// If you need more control on the execution, - /// first you must call \ref init(), then you can add several + /// If you need better control on the execution, + /// you have to call \ref init() first, then you can add several /// source nodes with \ref addSource(). /// Finally \ref start() will perform the arborescence /// computation. diff --git a/lemon/network_simplex.h b/lemon/network_simplex.h --- a/lemon/network_simplex.h +++ b/lemon/network_simplex.h @@ -40,7 +40,9 @@ /// for finding a \ref min_cost_flow "minimum cost flow". /// /// \ref NetworkSimplex implements the primal Network Simplex algorithm - /// for finding a \ref min_cost_flow "minimum cost flow". + /// for finding a \ref min_cost_flow "minimum cost flow" + /// \ref amo93networkflows, \ref dantzig63linearprog, + /// \ref kellyoneill91netsimplex. /// This algorithm is a specialized version of the linear programming /// simplex method directly for the minimum cost flow problem. /// It is one of the most efficient solution methods. @@ -48,7 +50,7 @@ /// In general this class is the fastest implementation available /// in LEMON for the minimum cost flow problem. /// Moreover it supports both directions of the supply/demand inequality - /// constraints. For more information see \ref SupplyType. + /// constraints. For more information, see \ref SupplyType. /// /// Most of the parameters of the problem (except for the digraph) /// can be given using separate functions, and the algorithm can be @@ -57,16 +59,16 @@ /// /// \tparam GR The digraph type the algorithm runs on. /// \tparam V The value type used for flow amounts, capacity bounds - /// and supply values in the algorithm. By default it is \c int. + /// and supply values in the algorithm. By default, it is \c int. /// \tparam C The value type used for costs and potentials in the - /// algorithm. By default it is the same as \c V. + /// algorithm. By default, it is the same as \c V. /// /// \warning Both value types must be signed and all input data must /// be integer. /// /// \note %NetworkSimplex provides five different pivot rule /// implementations, from which the most efficient one is used - /// by default. For more information see \ref PivotRule. + /// by default. For more information, see \ref PivotRule. template class NetworkSimplex { @@ -122,35 +124,35 @@ /// \ref NetworkSimplex provides five different pivot rule /// implementations that significantly affect the running time /// of the algorithm. - /// By default \ref BLOCK_SEARCH "Block Search" is used, which + /// By default, \ref BLOCK_SEARCH "Block Search" is used, which /// proved to be the most efficient and the most robust on various /// test inputs according to our benchmark tests. - /// However another pivot rule can be selected using the \ref run() + /// However, another pivot rule can be selected using the \ref run() /// function with the proper parameter. enum PivotRule { - /// The First Eligible pivot rule. + /// The \e First \e Eligible pivot rule. /// The next eligible arc is selected in a wraparound fashion /// in every iteration. FIRST_ELIGIBLE, - /// The Best Eligible pivot rule. + /// The \e Best \e Eligible pivot rule. /// The best eligible arc is selected in every iteration. BEST_ELIGIBLE, - /// The Block Search pivot rule. + /// The \e Block \e Search pivot rule. /// A specified number of arcs are examined in every iteration /// in a wraparound fashion and the best eligible arc is selected /// from this block. BLOCK_SEARCH, - /// The Candidate List pivot rule. + /// The \e Candidate \e List pivot rule. /// In a major iteration a candidate list is built from eligible arcs /// in a wraparound fashion and in the following minor iterations /// the best eligible arc is selected from this list. CANDIDATE_LIST, - /// The Altering Candidate List pivot rule. + /// The \e Altering \e Candidate \e List pivot rule. /// It is a modified version of the Candidate List method. /// It keeps only the several best eligible arcs from the former /// candidate list and extends this list in every iteration. @@ -161,8 +163,6 @@ TEMPLATE_DIGRAPH_TYPEDEFS(GR); - typedef std::vector ArcVector; - typedef std::vector NodeVector; typedef std::vector IntVector; typedef std::vector BoolVector; typedef std::vector ValueVector; @@ -364,33 +364,32 @@ bool findEnteringArc() { Cost c, min = 0; int cnt = _block_size; - int e, min_arc = _next_arc; + int e; for (e = _next_arc; e < _search_arc_num; ++e) { c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); if (c < min) { min = c; - min_arc = e; + _in_arc = e; } if (--cnt == 0) { - if (min < 0) break; + if (min < 0) goto search_end; cnt = _block_size; } } - if (min == 0 || cnt > 0) { - for (e = 0; e < _next_arc; ++e) { - c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); - if (c < min) { - min = c; - min_arc = e; - } - if (--cnt == 0) { - if (min < 0) break; - cnt = _block_size; - } + for (e = 0; e < _next_arc; ++e) { + c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); + if (c < min) { + min = c; + _in_arc = e; + } + if (--cnt == 0) { + if (min < 0) goto search_end; + cnt = _block_size; } } if (min >= 0) return false; - _in_arc = min_arc; + + search_end: _next_arc = e; return true; } @@ -428,7 +427,7 @@ _next_arc(0) { // The main parameters of the pivot rule - const double LIST_LENGTH_FACTOR = 1.0; + const double LIST_LENGTH_FACTOR = 0.25; const int MIN_LIST_LENGTH = 10; const double MINOR_LIMIT_FACTOR = 0.1; const int MIN_MINOR_LIMIT = 3; @@ -445,7 +444,7 @@ /// Find next entering arc bool findEnteringArc() { Cost min, c; - int e, min_arc = _next_arc; + int e; if (_curr_length > 0 && _minor_count < _minor_limit) { // Minor iteration: select the best eligible arc from the // current candidate list @@ -456,16 +455,13 @@ c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); if (c < min) { min = c; - min_arc = e; + _in_arc = e; } - if (c >= 0) { + else if (c >= 0) { _candidates[i--] = _candidates[--_curr_length]; } } - if (min < 0) { - _in_arc = min_arc; - return true; - } + if (min < 0) return true; } // Major iteration: build a new candidate list @@ -477,27 +473,26 @@ _candidates[_curr_length++] = e; if (c < min) { min = c; - min_arc = e; + _in_arc = e; } - if (_curr_length == _list_length) break; + if (_curr_length == _list_length) goto search_end; } } - if (_curr_length < _list_length) { - for (e = 0; e < _next_arc; ++e) { - c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); - if (c < 0) { - _candidates[_curr_length++] = e; - if (c < min) { - min = c; - min_arc = e; - } - if (_curr_length == _list_length) break; + for (e = 0; e < _next_arc; ++e) { + c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); + if (c < 0) { + _candidates[_curr_length++] = e; + if (c < min) { + min = c; + _in_arc = e; } + if (_curr_length == _list_length) goto search_end; } } if (_curr_length == 0) return false; + + search_end: _minor_count = 1; - _in_arc = min_arc; _next_arc = e; return true; } @@ -549,7 +544,7 @@ _next_arc(0), _cand_cost(ns._search_arc_num), _sort_func(_cand_cost) { // The main parameters of the pivot rule - const double BLOCK_SIZE_FACTOR = 1.5; + const double BLOCK_SIZE_FACTOR = 1.0; const int MIN_BLOCK_SIZE = 10; const double HEAD_LENGTH_FACTOR = 0.1; const int MIN_HEAD_LENGTH = 3; @@ -578,39 +573,35 @@ // Extend the list int cnt = _block_size; - int last_arc = 0; int limit = _head_length; - for (int e = _next_arc; e < _search_arc_num; ++e) { + for (e = _next_arc; e < _search_arc_num; ++e) { _cand_cost[e] = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); if (_cand_cost[e] < 0) { _candidates[_curr_length++] = e; - last_arc = e; } if (--cnt == 0) { - if (_curr_length > limit) break; + if (_curr_length > limit) goto search_end; limit = 0; cnt = _block_size; } } - if (_curr_length <= limit) { - for (int e = 0; e < _next_arc; ++e) { - _cand_cost[e] = _state[e] * - (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); - if (_cand_cost[e] < 0) { - _candidates[_curr_length++] = e; - last_arc = e; - } - if (--cnt == 0) { - if (_curr_length > limit) break; - limit = 0; - cnt = _block_size; - } + for (e = 0; e < _next_arc; ++e) { + _cand_cost[e] = _state[e] * + (_cost[e] + _pi[_source[e]] - _pi[_target[e]]); + if (_cand_cost[e] < 0) { + _candidates[_curr_length++] = e; + } + if (--cnt == 0) { + if (_curr_length > limit) goto search_end; + limit = 0; + cnt = _block_size; } } if (_curr_length == 0) return false; - _next_arc = last_arc + 1; + + search_end: // Make heap of the candidate list (approximating a partial sort) make_heap( _candidates.begin(), _candidates.begin() + _curr_length, @@ -618,6 +609,7 @@ // Pop the first element of the heap _in_arc = _candidates[0]; + _next_arc = e; pop_heap( _candidates.begin(), _candidates.begin() + _curr_length, _sort_func ); _curr_length = std::min(_head_length, _curr_length - 1); @@ -633,7 +625,11 @@ /// The constructor of the class. /// /// \param graph The digraph the algorithm runs on. - NetworkSimplex(const GR& graph) : + /// \param arc_mixing Indicate if the arcs have to be stored in a + /// mixed order in the internal data structure. + /// In special cases, it could lead to better overall performance, + /// but it is usually slower. Therefore it is disabled by default. + NetworkSimplex(const GR& graph, bool arc_mixing = false) : _graph(graph), _node_id(graph), _arc_id(graph), INF(std::numeric_limits::has_infinity ? std::numeric_limits::infinity() : @@ -671,31 +667,33 @@ _last_succ.resize(all_node_num); _state.resize(max_arc_num); - // Copy the graph (store the arcs in a mixed order) + // Copy the graph int i = 0; for (NodeIt n(_graph); n != INVALID; ++n, ++i) { _node_id[n] = i; } - int k = std::max(int(std::sqrt(double(_arc_num))), 10); - i = 0; - for (ArcIt a(_graph); a != INVALID; ++a) { - _arc_id[a] = i; - _source[i] = _node_id[_graph.source(a)]; - _target[i] = _node_id[_graph.target(a)]; - if ((i += k) >= _arc_num) i = (i % k) + 1; + if (arc_mixing) { + // Store the arcs in a mixed order + int k = std::max(int(std::sqrt(double(_arc_num))), 10); + int i = 0, j = 0; + for (ArcIt a(_graph); a != INVALID; ++a) { + _arc_id[a] = i; + _source[i] = _node_id[_graph.source(a)]; + _target[i] = _node_id[_graph.target(a)]; + if ((i += k) >= _arc_num) i = ++j; + } + } else { + // Store the arcs in the original order + int i = 0; + for (ArcIt a(_graph); a != INVALID; ++a, ++i) { + _arc_id[a] = i; + _source[i] = _node_id[_graph.source(a)]; + _target[i] = _node_id[_graph.target(a)]; + } } - // Initialize maps - for (int i = 0; i != _node_num; ++i) { - _supply[i] = 0; - } - for (int i = 0; i != _arc_num; ++i) { - _lower[i] = 0; - _upper[i] = INF; - _cost[i] = 1; - } - _have_lower = false; - _stype = GEQ; + // Reset parameters + reset(); } /// \name Parameters @@ -768,7 +766,6 @@ /// This function sets the supply values of the nodes. /// If neither this function nor \ref stSupply() is used before /// calling \ref run(), the supply of each node will be set to zero. - /// (It makes sense only if non-zero lower bounds are given.) /// /// \param map A node map storing the supply values. /// Its \c Value type must be convertible to the \c Value type @@ -789,7 +786,6 @@ /// and the required flow value. /// If neither this function nor \ref supplyMap() is used before /// calling \ref run(), the supply of each node will be set to zero. - /// (It makes sense only if non-zero lower bounds are given.) /// /// Using this function has the same effect as using \ref supplyMap() /// with such a map in which \c k is assigned to \c s, \c -k is @@ -816,7 +812,7 @@ /// If it is not used before calling \ref run(), the \ref GEQ supply /// type will be used. /// - /// For more information see \ref SupplyType. + /// For more information, see \ref SupplyType. /// /// \return (*this) NetworkSimplex& supplyType(SupplyType supply_type) { @@ -848,11 +844,11 @@ /// that have been given are kept for the next call, unless /// \ref reset() is called, thus only the modified parameters /// have to be set again. See \ref reset() for examples. - /// However the underlying digraph must not be modified after this + /// However, the underlying digraph must not be modified after this /// class have been constructed, since it copies and extends the graph. /// /// \param pivot_rule The pivot rule that will be used during the - /// algorithm. For more information see \ref PivotRule. + /// algorithm. For more information, see \ref PivotRule. /// /// \return \c INFEASIBLE if no feasible flow exists, /// \n \c OPTIMAL if the problem has optimal solution @@ -877,7 +873,7 @@ /// It is useful for multiple run() calls. If this function is not /// used, all the parameters given before are kept for the next /// \ref run() call. - /// However the underlying digraph must not be modified after this + /// However, the underlying digraph must not be modified after this /// class have been constructed, since it copies and extends the graph. /// /// For example, diff --git a/lemon/path.h b/lemon/path.h --- a/lemon/path.h +++ b/lemon/path.h @@ -70,7 +70,7 @@ /// It simply makes a copy of the given path. template Path(const CPath& cpath) { - copyPath(*this, cpath); + pathCopy(cpath, *this); } /// \brief Template copy assignment @@ -78,7 +78,7 @@ /// This operator makes a copy of a path of any other type. template Path& operator=(const CPath& cpath) { - copyPath(*this, cpath); + pathCopy(cpath, *this); return *this; } @@ -258,7 +258,7 @@ /// makes a copy of the given path. template SimplePath(const CPath& cpath) { - copyPath(*this, cpath); + pathCopy(cpath, *this); } /// \brief Template copy assignment @@ -267,7 +267,7 @@ /// makes a copy of the given path. template SimplePath& operator=(const CPath& cpath) { - copyPath(*this, cpath); + pathCopy(cpath, *this); return *this; } @@ -437,7 +437,7 @@ /// makes a copy of the given path. template ListPath(const CPath& cpath) : first(0), last(0) { - copyPath(*this, cpath); + pathCopy(cpath, *this); } /// \brief Destructor of the path @@ -453,7 +453,7 @@ /// makes a copy of the given path. template ListPath& operator=(const CPath& cpath) { - copyPath(*this, cpath); + pathCopy(cpath, *this); return *this; } @@ -763,7 +763,7 @@ /// This path can be initialized from any other path type. template StaticPath(const CPath& cpath) : arcs(0) { - copyPath(*this, cpath); + pathCopy(cpath, *this); } /// \brief Destructor of the path @@ -779,7 +779,7 @@ /// makes a copy of the given path. template StaticPath& operator=(const CPath& cpath) { - copyPath(*this, cpath); + pathCopy(cpath, *this); return *this; } @@ -928,57 +928,57 @@ static const bool value = true; }; - template ::value> + template ::value> struct PathCopySelectorForward { - static void copy(Target& target, const Source& source) { - target.clear(); - for (typename Source::ArcIt it(source); it != INVALID; ++it) { - target.addBack(it); + static void copy(const From& from, To& to) { + to.clear(); + for (typename From::ArcIt it(from); it != INVALID; ++it) { + to.addBack(it); } } }; - template - struct PathCopySelectorForward { - static void copy(Target& target, const Source& source) { - target.clear(); - target.build(source); + template + struct PathCopySelectorForward { + static void copy(const From& from, To& to) { + to.clear(); + to.build(from); } }; - template ::value> + template ::value> struct PathCopySelectorBackward { - static void copy(Target& target, const Source& source) { - target.clear(); - for (typename Source::RevArcIt it(source); it != INVALID; ++it) { - target.addFront(it); + static void copy(const From& from, To& to) { + to.clear(); + for (typename From::RevArcIt it(from); it != INVALID; ++it) { + to.addFront(it); } } }; - template - struct PathCopySelectorBackward { - static void copy(Target& target, const Source& source) { - target.clear(); - target.buildRev(source); + template + struct PathCopySelectorBackward { + static void copy(const From& from, To& to) { + to.clear(); + to.buildRev(from); } }; - template ::value> + template ::value> struct PathCopySelector { - static void copy(Target& target, const Source& source) { - PathCopySelectorForward::copy(target, source); + static void copy(const From& from, To& to) { + PathCopySelectorForward::copy(from, to); } }; - template - struct PathCopySelector { - static void copy(Target& target, const Source& source) { - PathCopySelectorBackward::copy(target, source); + template + struct PathCopySelector { + static void copy(const From& from, To& to) { + PathCopySelectorBackward::copy(from, to); } }; @@ -987,11 +987,19 @@ /// \brief Make a copy of a path. /// - /// This function makes a copy of a path. - template - void copyPath(Target& target, const Source& source) { - checkConcept, Source>(); - _path_bits::PathCopySelector::copy(target, source); + /// This function makes a copy of a path. + template + void pathCopy(const From& from, To& to) { + checkConcept, From>(); + _path_bits::PathCopySelector::copy(from, to); + } + + /// \brief Deprecated version of \ref pathCopy(). + /// + /// Deprecated version of \ref pathCopy() (only for reverse compatibility). + template + void copyPath(To& to, const From& from) { + pathCopy(from, to); } /// \brief Check the consistency of a path. @@ -1015,18 +1023,20 @@ /// \brief The source of a path /// - /// This function returns the source of the given path. + /// This function returns the source node of the given path. + /// If the path is empty, then it returns \c INVALID. template typename Digraph::Node pathSource(const Digraph& digraph, const Path& path) { - return digraph.source(path.front()); + return path.empty() ? INVALID : digraph.source(path.front()); } /// \brief The target of a path /// - /// This function returns the target of the given path. + /// This function returns the target node of the given path. + /// If the path is empty, then it returns \c INVALID. template typename Digraph::Node pathTarget(const Digraph& digraph, const Path& path) { - return digraph.target(path.back()); + return path.empty() ? INVALID : digraph.target(path.back()); } /// \brief Class which helps to iterate through the nodes of a path diff --git a/lemon/preflow.h b/lemon/preflow.h --- a/lemon/preflow.h +++ b/lemon/preflow.h @@ -52,7 +52,11 @@ /// /// The type of the map that stores the flow values. /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept. +#ifdef DOXYGEN + typedef GR::ArcMap FlowMap; +#else typedef typename Digraph::template ArcMap FlowMap; +#endif /// \brief Instantiates a FlowMap. /// @@ -67,9 +71,12 @@ /// /// The elevator type used by Preflow algorithm. /// - /// \sa Elevator - /// \sa LinkedElevator - typedef LinkedElevator Elevator; + /// \sa Elevator, LinkedElevator +#ifdef DOXYGEN + typedef lemon::Elevator Elevator; +#else + typedef lemon::Elevator Elevator; +#endif /// \brief Instantiates an Elevator. /// @@ -95,7 +102,8 @@ /// /// This class provides an implementation of Goldberg-Tarjan's \e preflow /// \e push-relabel algorithm producing a \ref max_flow - /// "flow of maximum value" in a digraph. + /// "flow of maximum value" in a digraph \ref clrs01algorithms, + /// \ref amo93networkflows, \ref goldberg88newapproach. /// The preflow algorithms are the fastest known maximum /// flow algorithms. The current implementation uses a mixture of the /// \e "highest label" and the \e "bound decrease" heuristics. @@ -257,7 +265,7 @@ /// The Elevator should have standard constructor interface to be /// able to automatically created by the algorithm (i.e. the /// digraph and the maximum level should be passed to it). - /// However an external elevator object could also be passed to the + /// However, an external elevator object could also be passed to the /// algorithm with the \ref elevator(Elevator&) "elevator()" function /// before calling \ref run() or \ref init(). /// \sa SetElevator @@ -391,8 +399,8 @@ /// \name Execution Control /// The simplest way to execute the preflow algorithm is to use /// \ref run() or \ref runMinCut().\n - /// If you need more control on the initial solution or the execution, - /// first you have to call one of the \ref init() functions, then + /// If you need better control on the initial solution or the execution, + /// you have to call one of the \ref init() functions first, then /// \ref startFirstPhase() and if you need it \ref startSecondPhase(). ///@{ diff --git a/lemon/smart_graph.h b/lemon/smart_graph.h --- a/lemon/smart_graph.h +++ b/lemon/smart_graph.h @@ -32,10 +32,7 @@ namespace lemon { class SmartDigraph; - ///Base of SmartDigraph - ///Base of SmartDigraph - /// class SmartDigraphBase { protected: @@ -187,28 +184,28 @@ /// ///\brief A smart directed graph class. /// - ///This is a simple and fast digraph implementation. - ///It is also quite memory efficient, but at the price - ///that it does support only limited (only stack-like) - ///node and arc deletions. - ///It fully conforms to the \ref concepts::Digraph "Digraph concept". + ///\ref SmartDigraph is a simple and fast digraph implementation. + ///It is also quite memory efficient but at the price + ///that it does not support node and arc deletion + ///(except for the Snapshot feature). /// - ///\sa concepts::Digraph. + ///This type fully conforms to the \ref concepts::Digraph "Digraph concept" + ///and it also provides some additional functionalities. + ///Most of its member functions and nested classes are documented + ///only in the concept class. + /// + ///This class provides constant time counting for nodes and arcs. + /// + ///\sa concepts::Digraph + ///\sa SmartGraph class SmartDigraph : public ExtendedSmartDigraphBase { typedef ExtendedSmartDigraphBase Parent; private: - - ///SmartDigraph is \e not copy constructible. Use DigraphCopy() instead. - - ///SmartDigraph is \e not copy constructible. Use DigraphCopy() instead. - /// + /// Digraphs are \e not copy constructible. Use DigraphCopy instead. SmartDigraph(const SmartDigraph &) : ExtendedSmartDigraphBase() {}; - ///\brief Assignment of SmartDigraph to another one is \e not allowed. - ///Use DigraphCopy() instead. - - ///Assignment of SmartDigraph to another one is \e not allowed. - ///Use DigraphCopy() instead. + /// \brief Assignment of a digraph to another one is \e not allowed. + /// Use DigraphCopy instead. void operator=(const SmartDigraph &) {} public: @@ -221,79 +218,49 @@ ///Add a new node to the digraph. - /// Add a new node to the digraph. - /// \return The new node. + ///This function adds a new node to the digraph. + ///\return The new node. Node addNode() { return Parent::addNode(); } ///Add a new arc to the digraph. - ///Add a new arc to the digraph with source node \c s + ///This function adds a new arc to the digraph with source node \c s ///and target node \c t. ///\return The new arc. - Arc addArc(const Node& s, const Node& t) { + Arc addArc(Node s, Node t) { return Parent::addArc(s, t); } - /// \brief Using this it is possible to avoid the superfluous memory - /// allocation. - - /// Using this it is possible to avoid the superfluous memory - /// allocation: if you know that the digraph you want to build will - /// be very large (e.g. it will contain millions of nodes and/or arcs) - /// then it is worth reserving space for this amount before starting - /// to build the digraph. - /// \sa reserveArc - void reserveNode(int n) { nodes.reserve(n); }; - - /// \brief Using this it is possible to avoid the superfluous memory - /// allocation. - - /// Using this it is possible to avoid the superfluous memory - /// allocation: if you know that the digraph you want to build will - /// be very large (e.g. it will contain millions of nodes and/or arcs) - /// then it is worth reserving space for this amount before starting - /// to build the digraph. - /// \sa reserveNode - void reserveArc(int m) { arcs.reserve(m); }; - /// \brief Node validity check /// - /// This function gives back true if the given node is valid, - /// ie. it is a real node of the graph. + /// This function gives back \c true if the given node is valid, + /// i.e. it is a real node of the digraph. /// /// \warning A removed node (using Snapshot) could become valid again - /// when new nodes are added to the graph. + /// if new nodes are added to the digraph. bool valid(Node n) const { return Parent::valid(n); } /// \brief Arc validity check /// - /// This function gives back true if the given arc is valid, - /// ie. it is a real arc of the graph. + /// This function gives back \c true if the given arc is valid, + /// i.e. it is a real arc of the digraph. /// /// \warning A removed arc (using Snapshot) could become valid again - /// when new arcs are added to the graph. + /// if new arcs are added to the graph. bool valid(Arc a) const { return Parent::valid(a); } - ///Clear the digraph. - - ///Erase all the nodes and arcs from the digraph. - /// - void clear() { - Parent::clear(); - } - ///Split a node. - ///This function splits a node. First a new node is added to the digraph, - ///then the source of each outgoing arc of \c n is moved to this new node. - ///If \c connect is \c true (this is the default value), then a new arc - ///from \c n to the newly created node is also added. + ///This function splits the given node. First, a new node is added + ///to the digraph, then the source of each outgoing arc of node \c n + ///is moved to this new node. + ///If the second parameter \c connect is \c true (this is the default + ///value), then a new arc from node \c n to the newly created node + ///is also added. ///\return The newly created node. /// - ///\note The Arcs - ///referencing a moved arc remain - ///valid. However InArc's and OutArc's - ///may be invalidated. + ///\note All iterators remain valid. + /// ///\warning This functionality cannot be used together with the Snapshot ///feature. Node split(Node n, bool connect = true) @@ -308,6 +275,34 @@ return b; } + ///Clear the digraph. + + ///This function erases all nodes and arcs from the digraph. + /// + void clear() { + Parent::clear(); + } + + /// Reserve memory for nodes. + + /// Using this function, it is possible to avoid superfluous memory + /// allocation: if you know that the digraph you want to build will + /// be large (e.g. it will contain millions of nodes and/or arcs), + /// then it is worth reserving space for this amount before starting + /// to build the digraph. + /// \sa reserveArc() + void reserveNode(int n) { nodes.reserve(n); }; + + /// Reserve memory for arcs. + + /// Using this function, it is possible to avoid superfluous memory + /// allocation: if you know that the digraph you want to build will + /// be large (e.g. it will contain millions of nodes and/or arcs), + /// then it is worth reserving space for this amount before starting + /// to build the digraph. + /// \sa reserveNode() + void reserveArc(int m) { arcs.reserve(m); }; + public: class Snapshot; @@ -332,20 +327,23 @@ public: - ///Class to make a snapshot of the digraph and to restrore to it later. + ///Class to make a snapshot of the digraph and to restore it later. - ///Class to make a snapshot of the digraph and to restrore to it later. + ///Class to make a snapshot of the digraph and to restore it later. /// ///The newly added nodes and arcs can be removed using the - ///restore() function. - ///\note After you restore a state, you cannot restore - ///a later state, in other word you cannot add again the arcs deleted - ///by restore() using another one Snapshot instance. + ///restore() function. This is the only way for deleting nodes and/or + ///arcs from a SmartDigraph structure. /// - ///\warning If you do not use correctly the snapshot that can cause - ///either broken program, invalid state of the digraph, valid but - ///not the restored digraph or no change. Because the runtime performance - ///the validity of the snapshot is not stored. + ///\note After a state is restored, you cannot restore a later state, + ///i.e. you cannot add the removed nodes and arcs again using + ///another Snapshot instance. + /// + ///\warning Node splitting cannot be restored. + ///\warning The validity of the snapshot is not stored due to + ///performance reasons. If you do not use the snapshot correctly, + ///it can cause broken program, invalid or not restored state of + ///the digraph or no change. class Snapshot { SmartDigraph *_graph; @@ -357,39 +355,32 @@ ///Default constructor. ///Default constructor. - ///To actually make a snapshot you must call save(). - /// + ///You have to call save() to actually make a snapshot. Snapshot() : _graph(0) {} ///Constructor that immediately makes a snapshot - ///This constructor immediately makes a snapshot of the digraph. - ///\param graph The digraph we make a snapshot of. - Snapshot(SmartDigraph &graph) : _graph(&graph) { + ///This constructor immediately makes a snapshot of the given digraph. + /// + Snapshot(SmartDigraph &gr) : _graph(&gr) { node_num=_graph->nodes.size(); arc_num=_graph->arcs.size(); } ///Make a snapshot. - ///Make a snapshot of the digraph. - /// - ///This function can be called more than once. In case of a repeated + ///This function makes a snapshot of the given digraph. + ///It can be called more than once. In case of a repeated ///call, the previous snapshot gets lost. - ///\param graph The digraph we make the snapshot of. - void save(SmartDigraph &graph) - { - _graph=&graph; + void save(SmartDigraph &gr) { + _graph=&gr; node_num=_graph->nodes.size(); arc_num=_graph->arcs.size(); } ///Undo the changes until a snapshot. - ///Undo the changes until a snapshot created by save(). - /// - ///\note After you restored a state, you cannot restore - ///a later state, in other word you cannot add again the arcs deleted - ///by restore(). + ///This function undos the changes until the last snapshot + ///created by save() or Snapshot(SmartDigraph&). void restore() { _graph->restoreSnapshot(*this); @@ -508,7 +499,7 @@ node._id = nodes.size() - 1; } - void next(Node& node) const { + static void next(Node& node) { --node._id; } @@ -516,7 +507,7 @@ arc._id = arcs.size() - 1; } - void next(Arc& arc) const { + static void next(Arc& arc) { --arc._id; } @@ -524,7 +515,7 @@ arc._id = arcs.size() / 2 - 1; } - void next(Edge& arc) const { + static void next(Edge& arc) { --arc._id; } @@ -621,29 +612,28 @@ /// /// \brief A smart undirected graph class. /// - /// This is a simple and fast graph implementation. - /// It is also quite memory efficient, but at the price - /// that it does support only limited (only stack-like) - /// node and arc deletions. - /// It fully conforms to the \ref concepts::Graph "Graph concept". + /// \ref SmartGraph is a simple and fast graph implementation. + /// It is also quite memory efficient but at the price + /// that it does not support node and edge deletion + /// (except for the Snapshot feature). /// - /// \sa concepts::Graph. + /// This type fully conforms to the \ref concepts::Graph "Graph concept" + /// and it also provides some additional functionalities. + /// Most of its member functions and nested classes are documented + /// only in the concept class. + /// + /// This class provides constant time counting for nodes, edges and arcs. + /// + /// \sa concepts::Graph + /// \sa SmartDigraph class SmartGraph : public ExtendedSmartGraphBase { typedef ExtendedSmartGraphBase Parent; private: - - ///SmartGraph is \e not copy constructible. Use GraphCopy() instead. - - ///SmartGraph is \e not copy constructible. Use GraphCopy() instead. - /// + /// Graphs are \e not copy constructible. Use GraphCopy instead. SmartGraph(const SmartGraph &) : ExtendedSmartGraphBase() {}; - - ///\brief Assignment of SmartGraph to another one is \e not allowed. - ///Use GraphCopy() instead. - - ///Assignment of SmartGraph to another one is \e not allowed. - ///Use GraphCopy() instead. + /// \brief Assignment of a graph to another one is \e not allowed. + /// Use GraphCopy instead. void operator=(const SmartGraph &) {} public: @@ -654,56 +644,77 @@ /// SmartGraph() {} - ///Add a new node to the graph. - - /// Add a new node to the graph. + /// \brief Add a new node to the graph. + /// + /// This function adds a new node to the graph. /// \return The new node. Node addNode() { return Parent::addNode(); } - ///Add a new edge to the graph. - - ///Add a new edge to the graph with node \c s - ///and \c t. - ///\return The new edge. - Edge addEdge(const Node& s, const Node& t) { - return Parent::addEdge(s, t); + /// \brief Add a new edge to the graph. + /// + /// This function adds a new edge to the graph between nodes + /// \c u and \c v with inherent orientation from node \c u to + /// node \c v. + /// \return The new edge. + Edge addEdge(Node u, Node v) { + return Parent::addEdge(u, v); } /// \brief Node validity check /// - /// This function gives back true if the given node is valid, - /// ie. it is a real node of the graph. + /// This function gives back \c true if the given node is valid, + /// i.e. it is a real node of the graph. /// /// \warning A removed node (using Snapshot) could become valid again - /// when new nodes are added to the graph. + /// if new nodes are added to the graph. bool valid(Node n) const { return Parent::valid(n); } + /// \brief Edge validity check + /// + /// This function gives back \c true if the given edge is valid, + /// i.e. it is a real edge of the graph. + /// + /// \warning A removed edge (using Snapshot) could become valid again + /// if new edges are added to the graph. + bool valid(Edge e) const { return Parent::valid(e); } + /// \brief Arc validity check /// - /// This function gives back true if the given arc is valid, - /// ie. it is a real arc of the graph. + /// This function gives back \c true if the given arc is valid, + /// i.e. it is a real arc of the graph. /// /// \warning A removed arc (using Snapshot) could become valid again - /// when new edges are added to the graph. + /// if new edges are added to the graph. bool valid(Arc a) const { return Parent::valid(a); } - /// \brief Edge validity check - /// - /// This function gives back true if the given edge is valid, - /// ie. it is a real edge of the graph. - /// - /// \warning A removed edge (using Snapshot) could become valid again - /// when new edges are added to the graph. - bool valid(Edge e) const { return Parent::valid(e); } - ///Clear the graph. - ///Erase all the nodes and edges from the graph. + ///This function erases all nodes and arcs from the graph. /// void clear() { Parent::clear(); } + /// Reserve memory for nodes. + + /// Using this function, it is possible to avoid superfluous memory + /// allocation: if you know that the graph you want to build will + /// be large (e.g. it will contain millions of nodes and/or edges), + /// then it is worth reserving space for this amount before starting + /// to build the graph. + /// \sa reserveEdge() + void reserveNode(int n) { nodes.reserve(n); }; + + /// Reserve memory for edges. + + /// Using this function, it is possible to avoid superfluous memory + /// allocation: if you know that the graph you want to build will + /// be large (e.g. it will contain millions of nodes and/or edges), + /// then it is worth reserving space for this amount before starting + /// to build the graph. + /// \sa reserveNode() + void reserveEdge(int m) { arcs.reserve(2 * m); }; + public: class Snapshot; @@ -742,21 +753,22 @@ public: - ///Class to make a snapshot of the digraph and to restrore to it later. + ///Class to make a snapshot of the graph and to restore it later. - ///Class to make a snapshot of the digraph and to restrore to it later. + ///Class to make a snapshot of the graph and to restore it later. /// - ///The newly added nodes and arcs can be removed using the - ///restore() function. + ///The newly added nodes and edges can be removed using the + ///restore() function. This is the only way for deleting nodes and/or + ///edges from a SmartGraph structure. /// - ///\note After you restore a state, you cannot restore - ///a later state, in other word you cannot add again the arcs deleted - ///by restore() using another one Snapshot instance. + ///\note After a state is restored, you cannot restore a later state, + ///i.e. you cannot add the removed nodes and edges again using + ///another Snapshot instance. /// - ///\warning If you do not use correctly the snapshot that can cause - ///either broken program, invalid state of the digraph, valid but - ///not the restored digraph or no change. Because the runtime performance - ///the validity of the snapshot is not stored. + ///\warning The validity of the snapshot is not stored due to + ///performance reasons. If you do not use the snapshot correctly, + ///it can cause broken program, invalid or not restored state of + ///the graph or no change. class Snapshot { SmartGraph *_graph; @@ -768,36 +780,30 @@ ///Default constructor. ///Default constructor. - ///To actually make a snapshot you must call save(). - /// + ///You have to call save() to actually make a snapshot. Snapshot() : _graph(0) {} ///Constructor that immediately makes a snapshot - ///This constructor immediately makes a snapshot of the digraph. - ///\param graph The digraph we make a snapshot of. - Snapshot(SmartGraph &graph) { - graph.saveSnapshot(*this); + /// This constructor immediately makes a snapshot of the given graph. + /// + Snapshot(SmartGraph &gr) { + gr.saveSnapshot(*this); } ///Make a snapshot. - ///Make a snapshot of the graph. - /// - ///This function can be called more than once. In case of a repeated + ///This function makes a snapshot of the given graph. + ///It can be called more than once. In case of a repeated ///call, the previous snapshot gets lost. - ///\param graph The digraph we make the snapshot of. - void save(SmartGraph &graph) + void save(SmartGraph &gr) { - graph.saveSnapshot(*this); + gr.saveSnapshot(*this); } - ///Undo the changes until a snapshot. + ///Undo the changes until the last snapshot. - ///Undo the changes until a snapshot created by save(). - /// - ///\note After you restored a state, you cannot restore - ///a later state, in other word you cannot add again the arcs deleted - ///by restore(). + ///This function undos the changes until the last snapshot + ///created by save() or Snapshot(SmartGraph&). void restore() { _graph->restoreSnapshot(*this); diff --git a/lemon/soplex.cc b/lemon/soplex.cc --- a/lemon/soplex.cc +++ b/lemon/soplex.cc @@ -91,6 +91,19 @@ return soplex->nRows() - 1; } + int SoplexLp::_addRow(Value l, ExprIterator b, ExprIterator e, Value u) { + soplex::DSVector v; + for (ExprIterator it = b; it != e; ++it) { + v.add(it->first, it->second); + } + soplex::LPRow r(l, v, u); + soplex->addRow(r); + + _row_names.push_back(std::string()); + + return soplex->nRows() - 1; + } + void SoplexLp::_eraseCol(int i) { soplex->removeCol(i); diff --git a/lemon/soplex.h b/lemon/soplex.h --- a/lemon/soplex.h +++ b/lemon/soplex.h @@ -84,6 +84,7 @@ virtual int _addCol(); virtual int _addRow(); + virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u); virtual void _eraseCol(int i); virtual void _eraseRow(int i); diff --git a/lemon/static_graph.h b/lemon/static_graph.h new file mode 100644 --- /dev/null +++ b/lemon/static_graph.h @@ -0,0 +1,476 @@ +/* -*- C++ -*- + * + * This file is a part of LEMON, a generic C++ optimization library + * + * Copyright (C) 2003-2008 + * 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_STATIC_GRAPH_H +#define LEMON_STATIC_GRAPH_H + +///\ingroup graphs +///\file +///\brief StaticDigraph class. + +#include +#include + +namespace lemon { + + class StaticDigraphBase { + public: + + StaticDigraphBase() + : built(false), node_num(0), arc_num(0), + node_first_out(NULL), node_first_in(NULL), + arc_source(NULL), arc_target(NULL), + arc_next_in(NULL), arc_next_out(NULL) {} + + ~StaticDigraphBase() { + if (built) { + delete[] node_first_out; + delete[] node_first_in; + delete[] arc_source; + delete[] arc_target; + delete[] arc_next_out; + delete[] arc_next_in; + } + } + + class Node { + friend class StaticDigraphBase; + protected: + int id; + Node(int _id) : id(_id) {} + public: + Node() {} + Node (Invalid) : id(-1) {} + bool operator==(const Node& node) const { return id == node.id; } + bool operator!=(const Node& node) const { return id != node.id; } + bool operator<(const Node& node) const { return id < node.id; } + }; + + class Arc { + friend class StaticDigraphBase; + protected: + int id; + Arc(int _id) : id(_id) {} + public: + Arc() { } + Arc (Invalid) : id(-1) {} + bool operator==(const Arc& arc) const { return id == arc.id; } + bool operator!=(const Arc& arc) const { return id != arc.id; } + bool operator<(const Arc& arc) const { return id < arc.id; } + }; + + Node source(const Arc& e) const { return Node(arc_source[e.id]); } + Node target(const Arc& e) const { return Node(arc_target[e.id]); } + + void first(Node& n) const { n.id = node_num - 1; } + static void next(Node& n) { --n.id; } + + void first(Arc& e) const { e.id = arc_num - 1; } + static void next(Arc& e) { --e.id; } + + void firstOut(Arc& e, const Node& n) const { + e.id = node_first_out[n.id] != node_first_out[n.id + 1] ? + node_first_out[n.id] : -1; + } + void nextOut(Arc& e) const { e.id = arc_next_out[e.id]; } + + void firstIn(Arc& e, const Node& n) const { e.id = node_first_in[n.id]; } + void nextIn(Arc& e) const { e.id = arc_next_in[e.id]; } + + static int id(const Node& n) { return n.id; } + static Node nodeFromId(int id) { return Node(id); } + int maxNodeId() const { return node_num - 1; } + + static int id(const Arc& e) { return e.id; } + static Arc arcFromId(int id) { return Arc(id); } + int maxArcId() const { return arc_num - 1; } + + typedef True NodeNumTag; + typedef True ArcNumTag; + + int nodeNum() const { return node_num; } + int arcNum() const { return arc_num; } + + private: + + template + class ArcLess { + public: + typedef typename Digraph::Arc Arc; + + ArcLess(const Digraph &_graph, const NodeRefMap& _nodeRef) + : digraph(_graph), nodeRef(_nodeRef) {} + + bool operator()(const Arc& left, const Arc& right) const { + return nodeRef[digraph.target(left)] < nodeRef[digraph.target(right)]; + } + private: + const Digraph& digraph; + const NodeRefMap& nodeRef; + }; + + public: + + typedef True BuildTag; + + void clear() { + if (built) { + delete[] node_first_out; + delete[] node_first_in; + delete[] arc_source; + delete[] arc_target; + delete[] arc_next_out; + delete[] arc_next_in; + } + built = false; + node_num = 0; + arc_num = 0; + } + + template + void build(const Digraph& digraph, NodeRefMap& nodeRef, ArcRefMap& arcRef) { + typedef typename Digraph::Node GNode; + typedef typename Digraph::Arc GArc; + + built = true; + + node_num = countNodes(digraph); + arc_num = countArcs(digraph); + + node_first_out = new int[node_num + 1]; + node_first_in = new int[node_num]; + + arc_source = new int[arc_num]; + arc_target = new int[arc_num]; + arc_next_out = new int[arc_num]; + arc_next_in = new int[arc_num]; + + int node_index = 0; + for (typename Digraph::NodeIt n(digraph); n != INVALID; ++n) { + nodeRef[n] = Node(node_index); + node_first_in[node_index] = -1; + ++node_index; + } + + ArcLess arcLess(digraph, nodeRef); + + int arc_index = 0; + for (typename Digraph::NodeIt n(digraph); n != INVALID; ++n) { + int source = nodeRef[n].id; + std::vector arcs; + for (typename Digraph::OutArcIt e(digraph, n); e != INVALID; ++e) { + arcs.push_back(e); + } + if (!arcs.empty()) { + node_first_out[source] = arc_index; + std::sort(arcs.begin(), arcs.end(), arcLess); + for (typename std::vector::iterator it = arcs.begin(); + it != arcs.end(); ++it) { + int target = nodeRef[digraph.target(*it)].id; + arcRef[*it] = Arc(arc_index); + arc_source[arc_index] = source; + arc_target[arc_index] = target; + arc_next_in[arc_index] = node_first_in[target]; + node_first_in[target] = arc_index; + arc_next_out[arc_index] = arc_index + 1; + ++arc_index; + } + arc_next_out[arc_index - 1] = -1; + } else { + node_first_out[source] = arc_index; + } + } + node_first_out[node_num] = arc_num; + } + + template + void build(int n, ArcListIterator first, ArcListIterator last) { + built = true; + + node_num = n; + arc_num = std::distance(first, last); + + node_first_out = new int[node_num + 1]; + node_first_in = new int[node_num]; + + arc_source = new int[arc_num]; + arc_target = new int[arc_num]; + arc_next_out = new int[arc_num]; + arc_next_in = new int[arc_num]; + + for (int i = 0; i != node_num; ++i) { + node_first_in[i] = -1; + } + + int arc_index = 0; + for (int i = 0; i != node_num; ++i) { + node_first_out[i] = arc_index; + for ( ; first != last && (*first).first == i; ++first) { + int j = (*first).second; + LEMON_ASSERT(j >= 0 && j < node_num, + "Wrong arc list for StaticDigraph::build()"); + arc_source[arc_index] = i; + arc_target[arc_index] = j; + arc_next_in[arc_index] = node_first_in[j]; + node_first_in[j] = arc_index; + arc_next_out[arc_index] = arc_index + 1; + ++arc_index; + } + if (arc_index > node_first_out[i]) + arc_next_out[arc_index - 1] = -1; + } + LEMON_ASSERT(first == last, + "Wrong arc list for StaticDigraph::build()"); + node_first_out[node_num] = arc_num; + } + + protected: + + void fastFirstOut(Arc& e, const Node& n) const { + e.id = node_first_out[n.id]; + } + + static void fastNextOut(Arc& e) { + ++e.id; + } + void fastLastOut(Arc& e, const Node& n) const { + e.id = node_first_out[n.id + 1]; + } + + protected: + bool built; + int node_num; + int arc_num; + int *node_first_out; + int *node_first_in; + int *arc_source; + int *arc_target; + int *arc_next_in; + int *arc_next_out; + }; + + typedef DigraphExtender ExtendedStaticDigraphBase; + + + /// \ingroup graphs + /// + /// \brief A static directed graph class. + /// + /// \ref StaticDigraph is a highly efficient digraph implementation, + /// but it is fully static. + /// It stores only two \c int values for each node and only four \c int + /// values for each arc. Moreover it provides faster item iteration than + /// \ref ListDigraph and \ref SmartDigraph, especially using \c OutArcIt + /// iterators, since its arcs are stored in an appropriate order. + /// However it only provides build() and clear() functions and does not + /// support any other modification of the digraph. + /// + /// Since this digraph structure is completely static, its nodes and arcs + /// can be indexed with integers from the ranges [0..nodeNum()-1] + /// and [0..arcNum()-1], respectively. + /// The index of an item is the same as its ID, it can be obtained + /// using the corresponding \ref index() or \ref concepts::Digraph::id() + /// "id()" function. A node or arc with a certain index can be obtained + /// using node() or arc(). + /// + /// This type fully conforms to the \ref concepts::Digraph "Digraph concept". + /// Most of its member functions and nested classes are documented + /// only in the concept class. + /// + /// This class provides constant time counting for nodes and arcs. + /// + /// \sa concepts::Digraph + class StaticDigraph : public ExtendedStaticDigraphBase { + public: + + typedef ExtendedStaticDigraphBase Parent; + + public: + + /// \brief Constructor + /// + /// Default constructor. + StaticDigraph() : Parent() {} + + /// \brief The node with the given index. + /// + /// This function returns the node with the given index. + /// \sa index() + static Node node(int ix) { return Parent::nodeFromId(ix); } + + /// \brief The arc with the given index. + /// + /// This function returns the arc with the given index. + /// \sa index() + static Arc arc(int ix) { return Parent::arcFromId(ix); } + + /// \brief The index of the given node. + /// + /// This function returns the index of the the given node. + /// \sa node() + static int index(Node node) { return Parent::id(node); } + + /// \brief The index of the given arc. + /// + /// This function returns the index of the the given arc. + /// \sa arc() + static int index(Arc arc) { return Parent::id(arc); } + + /// \brief Number of nodes. + /// + /// This function returns the number of nodes. + int nodeNum() const { return node_num; } + + /// \brief Number of arcs. + /// + /// This function returns the number of arcs. + int arcNum() const { return arc_num; } + + /// \brief Build the digraph copying another digraph. + /// + /// This function builds the digraph copying another digraph of any + /// kind. It can be called more than once, but in such case, the whole + /// structure and all maps will be cleared and rebuilt. + /// + /// This method also makes possible to copy a digraph to a StaticDigraph + /// structure using \ref DigraphCopy. + /// + /// \param digraph An existing digraph to be copied. + /// \param nodeRef The node references will be copied into this map. + /// Its key type must be \c Digraph::Node and its value type must be + /// \c StaticDigraph::Node. + /// It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap" + /// concept. + /// \param arcRef The arc references will be copied into this map. + /// Its key type must be \c Digraph::Arc and its value type must be + /// \c StaticDigraph::Arc. + /// It must conform to the \ref concepts::WriteMap "WriteMap" concept. + /// + /// \note If you do not need the arc references, then you could use + /// \ref NullMap for the last parameter. However the node references + /// are required by the function itself, thus they must be readable + /// from the map. + template + void build(const Digraph& digraph, NodeRefMap& nodeRef, ArcRefMap& arcRef) { + if (built) Parent::clear(); + Parent::build(digraph, nodeRef, arcRef); + } + + /// \brief Build the digraph from an arc list. + /// + /// This function builds the digraph from the given arc list. + /// It can be called more than once, but in such case, the whole + /// structure and all maps will be cleared and rebuilt. + /// + /// The list of the arcs must be given in the range [begin, end) + /// specified by STL compatible itartors whose \c value_type must be + /// std::pair. + /// Each arc must be specified by a pair of integer indices + /// from the range [0..n-1]. The pairs must be in a + /// non-decreasing order with respect to their first values. + /// If the k-th pair in the list is (i,j), then + /// arc(k-1) will connect node(i) to node(j). + /// + /// \param n The number of nodes. + /// \param begin An iterator pointing to the beginning of the arc list. + /// \param end An iterator pointing to the end of the arc list. + /// + /// For example, a simple digraph can be constructed like this. + /// \code + /// std::vector > arcs; + /// arcs.push_back(std::make_pair(0,1)); + /// arcs.push_back(std::make_pair(0,2)); + /// arcs.push_back(std::make_pair(1,3)); + /// arcs.push_back(std::make_pair(1,2)); + /// arcs.push_back(std::make_pair(3,0)); + /// StaticDigraph gr; + /// gr.build(4, arcs.begin(), arcs.end()); + /// \endcode + template + void build(int n, ArcListIterator begin, ArcListIterator end) { + if (built) Parent::clear(); + StaticDigraphBase::build(n, begin, end); + notifier(Node()).build(); + notifier(Arc()).build(); + } + + /// \brief Clear the digraph. + /// + /// This function erases all nodes and arcs from the digraph. + void clear() { + Parent::clear(); + } + + protected: + + using Parent::fastFirstOut; + using Parent::fastNextOut; + using Parent::fastLastOut; + + public: + + class OutArcIt : public Arc { + public: + + OutArcIt() { } + + OutArcIt(Invalid i) : Arc(i) { } + + OutArcIt(const StaticDigraph& digraph, const Node& node) { + digraph.fastFirstOut(*this, node); + digraph.fastLastOut(last, node); + if (last == *this) *this = INVALID; + } + + OutArcIt(const StaticDigraph& digraph, const Arc& arc) : Arc(arc) { + if (arc != INVALID) { + digraph.fastLastOut(last, digraph.source(arc)); + } + } + + OutArcIt& operator++() { + StaticDigraph::fastNextOut(*this); + if (last == *this) *this = INVALID; + return *this; + } + + private: + Arc last; + }; + + Node baseNode(const OutArcIt &arc) const { + return Parent::source(static_cast(arc)); + } + + Node runningNode(const OutArcIt &arc) const { + return Parent::target(static_cast(arc)); + } + + Node baseNode(const InArcIt &arc) const { + return Parent::target(static_cast(arc)); + } + + Node runningNode(const InArcIt &arc) const { + return Parent::source(static_cast(arc)); + } + + }; + +} + +#endif diff --git a/lemon/time_measure.h b/lemon/time_measure.h --- a/lemon/time_measure.h +++ b/lemon/time_measure.h @@ -375,7 +375,7 @@ ///This function returns the number of stop() exections that is ///necessary to really stop the timer. - ///For example the timer + ///For example, the timer ///is running if and only if the return value is \c true ///(i.e. greater than ///zero). diff --git a/lemon/unionfind.h b/lemon/unionfind.h --- a/lemon/unionfind.h +++ b/lemon/unionfind.h @@ -43,7 +43,7 @@ /// the find operation uses path compression. /// This is a very simple but efficient implementation, providing /// only four methods: join (union), find, insert and size. - /// For more features see the \ref UnionFindEnum class. + /// For more features, see the \ref UnionFindEnum class. /// /// It is primarily used in Kruskal algorithm for finding minimal /// cost spanning tree in a graph. diff --git a/m4/lx_check_coin.m4 b/m4/lx_check_coin.m4 --- a/m4/lx_check_coin.m4 +++ b/m4/lx_check_coin.m4 @@ -88,7 +88,7 @@ elif test x"$with_coin" != x"yes"; then CBC_LDFLAGS="-L$with_coin/lib" fi - CBC_LIBS="-lOsi -lCbc -lOsiCbc -lCbcSolver -lClp -lOsiClp -lCoinUtils -lVol -lOsiVol -lCgl -lm -llapack -lblas" + CBC_LIBS="-lOsi -lCbc -lCbcSolver -lClp -lOsiClp -lCoinUtils -lVol -lOsiVol -lCgl -lm -llapack -lblas" lx_save_cxxflags="$CXXFLAGS" lx_save_ldflags="$LDFLAGS" diff --git a/scripts/Makefile.am b/scripts/Makefile.am new file mode 100644 --- /dev/null +++ b/scripts/Makefile.am @@ -0,0 +1,7 @@ +EXTRA_DIST += \ + scripts/bib2dox.py \ + scripts/bootstrap.sh \ + scripts/chg-len.py \ + scripts/mk-release.sh \ + scripts/unify-sources.sh \ + scripts/valgrind-wrapper.sh diff --git a/scripts/bib2dox.py b/scripts/bib2dox.py new file mode 100755 --- /dev/null +++ b/scripts/bib2dox.py @@ -0,0 +1,811 @@ +#!/usr/bin/env /usr/local/Python/bin/python2.1 +""" + BibTeX to Doxygen converter + Usage: python bib2dox.py bibfile.bib > bibfile.dox + + This code is the modification of the BibTeX to XML converter + by Vidar Bronken Gundersen et al. See the original copyright notices below. + + ********************************************************************** + + Decoder for bibliographic data, BibTeX + Usage: python bibtex2xml.py bibfile.bib > bibfile.xml + + v.8 + (c)2002-06-23 Vidar Bronken Gundersen + http://bibtexml.sf.net/ + Reuse approved as long as this notification is kept. + Licence: GPL. + + Contributions/thanks to: + Egon Willighagen, http://sf.net/projects/jreferences/ + Richard Mahoney (for providing a test case) + + Editted by Sara Sprenkle to be more robust and handle more bibtex features. + (c) 2003-01-15 + + 1. Changed bibtex: tags to bibxml: tags. + 2. Use xmlns:bibxml="http://bibtexml.sf.net/" + 3. Allow spaces between @type and first { + 4. "author" fields with multiple authors split by " and " + are put in separate xml "bibxml:author" tags. + 5. Option for Titles: words are capitalized + only if first letter in title or capitalized inside braces + 6. Removes braces from within field values + 7. Ignores comments in bibtex file (including @comment{ or % ) + 8. Replaces some special latex tags, e.g., replaces ~ with ' ' + 9. Handles bibtex @string abbreviations + --> includes bibtex's default abbreviations for months + --> does concatenation of abbr # " more " and " more " # abbr + 10. Handles @type( ... ) or @type{ ... } + 11. The keywords field is split on , or ; and put into separate xml + "bibxml:keywords" tags + 12. Ignores @preamble + + Known Limitations + 1. Does not transform Latex encoding like math mode and special + latex symbols. + 2. Does not parse author fields into first and last names. + E.g., It does not do anything special to an author whose name is + in the form LAST_NAME, FIRST_NAME + In "author" tag, will show up as + LAST_NAME, FIRST_NAME + 3. Does not handle "crossref" fields other than to print + ... + 4. Does not inform user of the input's format errors. You just won't + be able to transform the file later with XSL + + You will have to manually edit the XML output if you need to handle + these (and unknown) limitations. + +""" + +import string, re + +# set of valid name characters +valid_name_chars = '[\w\-:]' + +# +# define global regular expression variables +# +author_rex = re.compile('\s+and\s+') +rembraces_rex = re.compile('[{}]') +capitalize_rex = re.compile('({[^}]*})') + +# used by bibtexkeywords(data) +keywords_rex = re.compile('[,;]') + +# used by concat_line(line) +concatsplit_rex = re.compile('\s*#\s*') + +# split on {, }, or " in verify_out_of_braces +delimiter_rex = re.compile('([{}"])',re.I) + +field_rex = re.compile('\s*(\w*)\s*=\s*(.*)') +data_rex = re.compile('\s*(\w*)\s*=\s*([^,]*),?') + +url_rex = re.compile('\\\url\{([^}]*)\}') + +# +# styles for html formatting +# +divstyle = 'margin-top: -4ex; margin-left: 8em;' + +# +# return the string parameter without braces +# +def transformurls(str): + return url_rex.sub(r'\1', str) + +# +# return the string parameter without braces +# +def removebraces(str): + return rembraces_rex.sub('', str) + +# +# latex-specific replacements +# (do this after braces were removed) +# +def latexreplacements(line): + line = string.replace(line, '~', ' ') + line = string.replace(line, '\\\'a', 'á') + line = string.replace(line, '\\"a', 'ä') + line = string.replace(line, '\\\'e', 'é') + line = string.replace(line, '\\"e', 'ë') + line = string.replace(line, '\\\'i', 'í') + line = string.replace(line, '\\"i', 'ï') + line = string.replace(line, '\\\'o', 'ó') + line = string.replace(line, '\\"o', 'ö') + line = string.replace(line, '\\\'u', 'ú') + line = string.replace(line, '\\"u', 'ü') + line = string.replace(line, '\\H o', 'õ') + line = string.replace(line, '\\H u', 'ü') # ũ does not exist + line = string.replace(line, '\\\'A', 'Á') + line = string.replace(line, '\\"A', 'Ä') + line = string.replace(line, '\\\'E', 'É') + line = string.replace(line, '\\"E', 'Ë') + line = string.replace(line, '\\\'I', 'Í') + line = string.replace(line, '\\"I', 'Ï') + line = string.replace(line, '\\\'O', 'Ó') + line = string.replace(line, '\\"O', 'Ö') + line = string.replace(line, '\\\'U', 'Ú') + line = string.replace(line, '\\"U', 'Ü') + line = string.replace(line, '\\H O', 'Õ') + line = string.replace(line, '\\H U', 'Ü') # Ũ does not exist + + return line + +# +# copy characters form a string decoding html expressions (&xyz;) +# +def copychars(str, ifrom, count): + result = '' + i = ifrom + c = 0 + html_spec = False + while (i < len(str)) and (c < count): + if str[i] == '&': + html_spec = True; + if i+1 < len(str): + result += str[i+1] + c += 1 + i += 2 + else: + if not html_spec: + if ((str[i] >= 'A') and (str[i] <= 'Z')) or \ + ((str[i] >= 'a') and (str[i] <= 'z')): + result += str[i] + c += 1 + elif str[i] == ';': + html_spec = False; + i += 1 + + return result + + +# +# Handle a list of authors (separated by 'and'). +# It gives back an array of the follwing values: +# - num: the number of authors, +# - list: the list of the author names, +# - text: the bibtex text (separated by commas and/or 'and') +# - abbrev: abbreviation that can be used for indicate the +# bibliography entries +# +def bibtexauthor(data): + result = {} + bibtex = '' + result['list'] = author_rex.split(data) + result['num'] = len(result['list']) + for i, author in enumerate(result['list']): + # general transformations + author = latexreplacements(removebraces(author.strip())) + # transform "Xyz, A. B." to "A. B. Xyz" + pos = author.find(',') + if pos != -1: + author = author[pos+1:].strip() + ' ' + author[:pos].strip() + result['list'][i] = author + bibtex += author + '#' + bibtex = bibtex[:-1] + if result['num'] > 1: + ix = bibtex.rfind('#') + if result['num'] == 2: + bibtex = bibtex[:ix] + ' and ' + bibtex[ix+1:] + else: + bibtex = bibtex[:ix] + ', and ' + bibtex[ix+1:] + bibtex = bibtex.replace('#', ', ') + result['text'] = bibtex + + result['abbrev'] = '' + for author in result['list']: + pos = author.rfind(' ') + 1 + count = 1 + if result['num'] == 1: + count = 3 + result['abbrev'] += copychars(author, pos, count) + + return result + + +# +# data = title string +# @return the capitalized title (first letter is capitalized), rest are capitalized +# only if capitalized inside braces +# +def capitalizetitle(data): + title_list = capitalize_rex.split(data) + title = '' + count = 0 + for phrase in title_list: + check = string.lstrip(phrase) + + # keep phrase's capitalization the same + if check.find('{') == 0: + title += removebraces(phrase) + else: + # first word --> capitalize first letter (after spaces) + if count == 0: + title += check.capitalize() + else: + title += phrase.lower() + count = count + 1 + + return title + + +# +# @return the bibtex for the title +# @param data --> title string +# braces are removed from title +# +def bibtextitle(data, entrytype): + if entrytype in ('book', 'inbook'): + title = removebraces(data.strip()) + else: + title = removebraces(capitalizetitle(data.strip())) + bibtex = title + return bibtex + + +# +# function to compare entry lists +# +def entry_cmp(x, y): + return cmp(x[0], y[0]) + + +# +# print the XML for the transformed "filecont_source" +# +def bibtexdecoder(filecont_source): + filecont = [] + file = [] + + # want @{, + pubtype_rex = re.compile('@(\w*)\s*{\s*(.*),') + endtype_rex = re.compile('}\s*$') + endtag_rex = re.compile('^\s*}\s*$') + + bracefield_rex = re.compile('\s*(\w*)\s*=\s*(.*)') + bracedata_rex = re.compile('\s*(\w*)\s*=\s*{(.*)},?') + + quotefield_rex = re.compile('\s*(\w*)\s*=\s*(.*)') + quotedata_rex = re.compile('\s*(\w*)\s*=\s*"(.*)",?') + + for line in filecont_source: + line = line[:-1] + + # encode character entities + line = string.replace(line, '&', '&') + line = string.replace(line, '<', '<') + line = string.replace(line, '>', '>') + + # start entry: publication type (store for later use) + if pubtype_rex.match(line): + # want @{, + entrycont = {} + entry = [] + entrytype = pubtype_rex.sub('\g<1>',line) + entrytype = string.lower(entrytype) + entryid = pubtype_rex.sub('\g<2>', line) + + # end entry if just a } + elif endtype_rex.match(line): + # generate doxygen code for the entry + + # enty type related formattings + if entrytype in ('book', 'inbook'): + entrycont['title'] = '' + entrycont['title'] + '' + if not entrycont.has_key('author'): + entrycont['author'] = entrycont['editor'] + entrycont['author']['text'] += ', editors' + elif entrytype == 'article': + entrycont['journal'] = '' + entrycont['journal'] + '' + elif entrytype in ('inproceedings', 'incollection', 'conference'): + entrycont['booktitle'] = '' + entrycont['booktitle'] + '' + elif entrytype == 'techreport': + if not entrycont.has_key('type'): + entrycont['type'] = 'Technical report' + elif entrytype == 'mastersthesis': + entrycont['type'] = 'Master\'s thesis' + elif entrytype == 'phdthesis': + entrycont['type'] = 'PhD thesis' + + for eline in entrycont: + if eline != '': + eline = latexreplacements(eline) + + if entrycont.has_key('pages') and (entrycont['pages'] != ''): + entrycont['pages'] = string.replace(entrycont['pages'], '--', '-') + + if entrycont.has_key('author') and (entrycont['author'] != ''): + entry.append(entrycont['author']['text'] + '.') + if entrycont.has_key('title') and (entrycont['title'] != ''): + entry.append(entrycont['title'] + '.') + if entrycont.has_key('journal') and (entrycont['journal'] != ''): + entry.append(entrycont['journal'] + ',') + if entrycont.has_key('booktitle') and (entrycont['booktitle'] != ''): + entry.append('In ' + entrycont['booktitle'] + ',') + if entrycont.has_key('type') and (entrycont['type'] != ''): + eline = entrycont['type'] + if entrycont.has_key('number') and (entrycont['number'] != ''): + eline += ' ' + entrycont['number'] + eline += ',' + entry.append(eline) + if entrycont.has_key('institution') and (entrycont['institution'] != ''): + entry.append(entrycont['institution'] + ',') + if entrycont.has_key('publisher') and (entrycont['publisher'] != ''): + entry.append(entrycont['publisher'] + ',') + if entrycont.has_key('school') and (entrycont['school'] != ''): + entry.append(entrycont['school'] + ',') + if entrycont.has_key('address') and (entrycont['address'] != ''): + entry.append(entrycont['address'] + ',') + if entrycont.has_key('edition') and (entrycont['edition'] != ''): + entry.append(entrycont['edition'] + ' edition,') + if entrycont.has_key('howpublished') and (entrycont['howpublished'] != ''): + entry.append(entrycont['howpublished'] + ',') + if entrycont.has_key('volume') and (entrycont['volume'] != ''): + eline = entrycont['volume']; + if entrycont.has_key('number') and (entrycont['number'] != ''): + eline += '(' + entrycont['number'] + ')' + if entrycont.has_key('pages') and (entrycont['pages'] != ''): + eline += ':' + entrycont['pages'] + eline += ',' + entry.append(eline) + else: + if entrycont.has_key('pages') and (entrycont['pages'] != ''): + entry.append('pages ' + entrycont['pages'] + ',') + if entrycont.has_key('year') and (entrycont['year'] != ''): + if entrycont.has_key('month') and (entrycont['month'] != ''): + entry.append(entrycont['month'] + ' ' + entrycont['year'] + '.') + else: + entry.append(entrycont['year'] + '.') + if entrycont.has_key('note') and (entrycont['note'] != ''): + entry.append(entrycont['note'] + '.') + if entrycont.has_key('url') and (entrycont['url'] != ''): + entry.append(entrycont['url'] + '.') + + # generate keys for sorting and for the output + sortkey = '' + bibkey = '' + if entrycont.has_key('author'): + for author in entrycont['author']['list']: + sortkey += copychars(author, author.rfind(' ')+1, len(author)) + bibkey = entrycont['author']['abbrev'] + else: + bibkey = 'x' + if entrycont.has_key('year'): + sortkey += entrycont['year'] + bibkey += entrycont['year'][-2:] + if entrycont.has_key('title'): + sortkey += entrycont['title'] + if entrycont.has_key('key'): + sortkey = entrycont['key'] + sortkey + bibkey = entrycont['key'] + entry.insert(0, sortkey) + entry.insert(1, bibkey) + entry.insert(2, entryid) + + # add the entry to the file contents + filecont.append(entry) + + else: + # field, publication info + field = '' + data = '' + + # field = {data} entries + if bracedata_rex.match(line): + field = bracefield_rex.sub('\g<1>', line) + field = string.lower(field) + data = bracedata_rex.sub('\g<2>', line) + + # field = "data" entries + elif quotedata_rex.match(line): + field = quotefield_rex.sub('\g<1>', line) + field = string.lower(field) + data = quotedata_rex.sub('\g<2>', line) + + # field = data entries + elif data_rex.match(line): + field = field_rex.sub('\g<1>', line) + field = string.lower(field) + data = data_rex.sub('\g<2>', line) + + if field == 'url': + data = '\\url{' + data.strip() + '}' + + if field in ('author', 'editor'): + entrycont[field] = bibtexauthor(data) + line = '' + elif field == 'title': + line = bibtextitle(data, entrytype) + elif field != '': + line = removebraces(transformurls(data.strip())) + + if line != '': + line = latexreplacements(line) + entrycont[field] = line + + + # sort entries + filecont.sort(entry_cmp) + + # count the bibtex keys + keytable = {} + counttable = {} + for entry in filecont: + bibkey = entry[1] + if not keytable.has_key(bibkey): + keytable[bibkey] = 1 + else: + keytable[bibkey] += 1 + + for bibkey in keytable.keys(): + counttable[bibkey] = 0 + + # generate output + for entry in filecont: + # generate output key form the bibtex key + bibkey = entry[1] + entryid = entry[2] + if keytable[bibkey] == 1: + outkey = bibkey + else: + outkey = bibkey + chr(97 + counttable[bibkey]) + counttable[bibkey] += 1 + + # append the entry code to the output + file.append('\\section ' + entryid + ' [' + outkey + ']') + file.append('
') + for line in entry[3:]: + file.append(line) + file.append('
') + file.append('') + + return file + + +# +# return 1 iff abbr is in line but not inside braces or quotes +# assumes that abbr appears only once on the line (out of braces and quotes) +# +def verify_out_of_braces(line, abbr): + + phrase_split = delimiter_rex.split(line) + + abbr_rex = re.compile( '\\b' + abbr + '\\b', re.I) + + open_brace = 0 + open_quote = 0 + + for phrase in phrase_split: + if phrase == "{": + open_brace = open_brace + 1 + elif phrase == "}": + open_brace = open_brace - 1 + elif phrase == '"': + if open_quote == 1: + open_quote = 0 + else: + open_quote = 1 + elif abbr_rex.search(phrase): + if open_brace == 0 and open_quote == 0: + return 1 + + return 0 + + +# +# a line in the form phrase1 # phrase2 # ... # phrasen +# is returned as phrase1 phrase2 ... phrasen +# with the correct punctuation +# Bug: Doesn't always work with multiple abbreviations plugged in +# +def concat_line(line): + # only look at part after equals + field = field_rex.sub('\g<1>',line) + rest = field_rex.sub('\g<2>',line) + + concat_line = field + ' =' + + pound_split = concatsplit_rex.split(rest) + + phrase_count = 0 + length = len(pound_split) + + for phrase in pound_split: + phrase = phrase.strip() + if phrase_count != 0: + if phrase.startswith('"') or phrase.startswith('{'): + phrase = phrase[1:] + elif phrase.startswith('"'): + phrase = phrase.replace('"','{',1) + + if phrase_count != length-1: + if phrase.endswith('"') or phrase.endswith('}'): + phrase = phrase[:-1] + else: + if phrase.endswith('"'): + phrase = phrase[:-1] + phrase = phrase + "}" + elif phrase.endswith('",'): + phrase = phrase[:-2] + phrase = phrase + "}," + + # if phrase did have \#, add the \# back + if phrase.endswith('\\'): + phrase = phrase + "#" + concat_line = concat_line + ' ' + phrase + + phrase_count = phrase_count + 1 + + return concat_line + + +# +# substitute abbreviations into filecont +# @param filecont_source - string of data from file +# +def bibtex_replace_abbreviations(filecont_source): + filecont = filecont_source.splitlines() + + # These are defined in bibtex, so we'll define them too + abbr_list = ['jan','feb','mar','apr','may','jun', + 'jul','aug','sep','oct','nov','dec'] + value_list = ['January','February','March','April', + 'May','June','July','August','September', + 'October','November','December'] + + abbr_rex = [] + total_abbr_count = 0 + + front = '\\b' + back = '(,?)\\b' + + for x in abbr_list: + abbr_rex.append( re.compile( front + abbr_list[total_abbr_count] + back, re.I ) ) + total_abbr_count = total_abbr_count + 1 + + + abbrdef_rex = re.compile('\s*@string\s*{\s*('+ valid_name_chars +'*)\s*=(.*)', + re.I) + + comment_rex = re.compile('@comment\s*{',re.I) + preamble_rex = re.compile('@preamble\s*{',re.I) + + waiting_for_end_string = 0 + i = 0 + filecont2 = '' + + for line in filecont: + if line == ' ' or line == '': + continue + + if waiting_for_end_string: + if re.search('}',line): + waiting_for_end_string = 0 + continue + + if abbrdef_rex.search(line): + abbr = abbrdef_rex.sub('\g<1>', line) + + if abbr_list.count(abbr) == 0: + val = abbrdef_rex.sub('\g<2>', line) + abbr_list.append(abbr) + value_list.append(string.strip(val)) + abbr_rex.append( re.compile( front + abbr_list[total_abbr_count] + back, re.I ) ) + total_abbr_count = total_abbr_count + 1 + waiting_for_end_string = 1 + continue + + if comment_rex.search(line): + waiting_for_end_string = 1 + continue + + if preamble_rex.search(line): + waiting_for_end_string = 1 + continue + + + # replace subsequent abbreviations with the value + abbr_count = 0 + + for x in abbr_list: + + if abbr_rex[abbr_count].search(line): + if verify_out_of_braces(line,abbr_list[abbr_count]) == 1: + line = abbr_rex[abbr_count].sub( value_list[abbr_count] + '\g<1>', line) + # Check for # concatenations + if concatsplit_rex.search(line): + line = concat_line(line) + abbr_count = abbr_count + 1 + + + filecont2 = filecont2 + line + '\n' + i = i+1 + + + # Do one final pass over file + + # make sure that didn't end up with {" or }" after the substitution + filecont2 = filecont2.replace('{"','{{') + filecont2 = filecont2.replace('"}','}}') + + afterquotevalue_rex = re.compile('"\s*,\s*') + afterbrace_rex = re.compile('"\s*}') + afterbracevalue_rex = re.compile('(=\s*{[^=]*)},\s*') + + # add new lines to data that changed because of abbreviation substitutions + filecont2 = afterquotevalue_rex.sub('",\n', filecont2) + filecont2 = afterbrace_rex.sub('"\n}', filecont2) + filecont2 = afterbracevalue_rex.sub('\g<1>},\n', filecont2) + + return filecont2 + +# +# convert @type( ... ) to @type{ ... } +# +def no_outer_parens(filecont): + + # do checking for open parens + # will convert to braces + paren_split = re.split('([(){}])',filecont) + + open_paren_count = 0 + open_type = 0 + look_next = 0 + + # rebuild filecont + filecont = '' + + at_rex = re.compile('@\w*') + + for phrase in paren_split: + if look_next == 1: + if phrase == '(': + phrase = '{' + open_paren_count = open_paren_count + 1 + else: + open_type = 0 + look_next = 0 + + if phrase == '(': + open_paren_count = open_paren_count + 1 + + elif phrase == ')': + open_paren_count = open_paren_count - 1 + if open_type == 1 and open_paren_count == 0: + phrase = '}' + open_type = 0 + + elif at_rex.search( phrase ): + open_type = 1 + look_next = 1 + + filecont = filecont + phrase + + return filecont + + +# +# make all whitespace into just one space +# format the bibtex file into a usable form. +# +def bibtexwasher(filecont_source): + + space_rex = re.compile('\s+') + comment_rex = re.compile('\s*%') + + filecont = [] + + # remove trailing and excessive whitespace + # ignore comments + for line in filecont_source: + line = string.strip(line) + line = space_rex.sub(' ', line) + # ignore comments + if not comment_rex.match(line) and line != '': + filecont.append(' '+ line) + + filecont = string.join(filecont, '') + + # the file is in one long string + + filecont = no_outer_parens(filecont) + + # + # split lines according to preferred syntax scheme + # + filecont = re.sub('(=\s*{[^=]*)},', '\g<1>},\n', filecont) + + # add new lines after commas that are after values + filecont = re.sub('"\s*,', '",\n', filecont) + filecont = re.sub('=\s*([\w\d]+)\s*,', '= \g<1>,\n', filecont) + filecont = re.sub('(@\w*)\s*({(\s*)[^,\s]*)\s*,', + '\n\n\g<1>\g<2>,\n', filecont) + + # add new lines after } + filecont = re.sub('"\s*}','"\n}\n', filecont) + filecont = re.sub('}\s*,','},\n', filecont) + + + filecont = re.sub('@(\w*)', '\n@\g<1>', filecont) + + # character encoding, reserved latex characters + filecont = re.sub('{\\\&}', '&', filecont) + filecont = re.sub('\\\&', '&', filecont) + + # do checking for open braces to get format correct + open_brace_count = 0 + brace_split = re.split('([{}])',filecont) + + # rebuild filecont + filecont = '' + + for phrase in brace_split: + if phrase == '{': + open_brace_count = open_brace_count + 1 + elif phrase == '}': + open_brace_count = open_brace_count - 1 + if open_brace_count == 0: + filecont = filecont + '\n' + + filecont = filecont + phrase + + filecont2 = bibtex_replace_abbreviations(filecont) + + # gather + filecont = filecont2.splitlines() + i=0 + j=0 # count the number of blank lines + for line in filecont: + # ignore blank lines + if line == '' or line == ' ': + j = j+1 + continue + filecont[i] = line + '\n' + i = i+1 + + # get rid of the extra stuff at the end of the array + # (The extra stuff are duplicates that are in the array because + # blank lines were removed.) + length = len( filecont) + filecont[length-j:length] = [] + + return filecont + + +def filehandler(filepath): + try: + fd = open(filepath, 'r') + filecont_source = fd.readlines() + fd.close() + except: + print 'Could not open file:', filepath + washeddata = bibtexwasher(filecont_source) + outdata = bibtexdecoder(washeddata) + print '/**' + print '\page references References' + print + for line in outdata: + print line + print '*/' + + +# main program + +def main(): + import sys + if sys.argv[1:]: + filepath = sys.argv[1] + else: + print "No input file" + sys.exit() + filehandler(filepath) + +if __name__ == "__main__": main() + + +# end python script diff --git a/scripts/bootstrap.sh b/scripts/bootstrap.sh new file mode 100755 --- /dev/null +++ b/scripts/bootstrap.sh @@ -0,0 +1,142 @@ +#!/bin/bash +# +# This file is a part of LEMON, a generic C++ optimization library. +# +# Copyright (C) 2003-2009 +# 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. + + +if [ ! -f ~/.lemon-bootstrap ]; then + echo 'Create ~/.lemon-bootstrap'. + cat >~/.lemon-bootstrap <>~/.lemon-bootstrap + echo $3 >>~/.lemon-bootstrap + echo $1=$2 >>~/.lemon-bootstrap + fi +} + +augment_config LEMON_INSTALL_PREFIX /usr/local \ + "# LEMON installation prefix" + +augment_config COIN_OR_PREFIX /usr/local/coin-or \ + "# COIN-OR installation root prefix (used for CLP/CBC)" + +augment_config SOPLEX_PREFIX /usr/local/soplex \ + "# Soplex build prefix" + + +function ask() { +echo -n "$1 [$2]? " +read _an +if [ "x$_an" == "x" ]; then + ret="$2" +else + ret=$_an +fi +} + +function yesorno() { + ret='rossz' + while [ "$ret" != "y" -a "$ret" != "n" -a "$ret" != "yes" -a "$ret" != "no" ]; do + ask "$1" "$2" + done + if [ "$ret" != "y" -a "$ret" != "yes" ]; then + return 1 + else + return 0 + fi +} + +if yesorno "External build" "n" +then + CONFIGURE_PATH=".." +else + CONFIGURE_PATH="." + if yesorno "Autoreconf" "y" + then + AUTORE=yes + else + AUTORE=no + fi +fi + +if yesorno "Optimize" "n" +then + opt_flags=' -O2' +else + opt_flags='' +fi + +if yesorno "Stop on warning" "y" +then + werror_flags=' -Werror' +else + werror_flags='' +fi + +cxx_flags="CXXFLAGS=-ggdb$opt_flags$werror_flags" + +if yesorno "Check with valgrind" "n" +then + valgrind_flags=' --enable-valgrind' +else + valgrind_flags='' +fi + +if [ -f ${COIN_OR_PREFIX}/include/coin/config_coinutils.h ]; then + if yesorno "Use COIN-OR (CBC/CLP)" "n" + then + coin_flag="--with-coin=$COIN_OR_PREFIX" + else + coin_flag="" + fi +else + coin_flag="" +fi + +if [ -f ${SOPLEX_PREFIX}/src/soplex.h ]; then + if yesorno "Use Soplex" "n" + then + soplex_flag="--with-soplex=$SOPLEX_PREFIX" + else + soplex_flag="" + fi +else + soplex_flag="" +fi + +if [ "x$AUTORE" == "xyes" ]; then + autoreconf -vif; +fi +${CONFIGURE_PATH}/configure --prefix=$LEMON_INSTALL_PREFIX \ +$valgrind_flags \ +"$cxx_flags" \ +$coin_flag \ +$soplex_flag \ +$* diff --git a/scripts/chg-len.py b/scripts/chg-len.py --- a/scripts/chg-len.py +++ b/scripts/chg-len.py @@ -1,4 +1,18 @@ #! /usr/bin/env python +# +# This file is a part of LEMON, a generic C++ optimization library. +# +# Copyright (C) 2003-2009 +# 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. import sys diff --git a/scripts/mk-release.sh b/scripts/mk-release.sh --- a/scripts/mk-release.sh +++ b/scripts/mk-release.sh @@ -1,4 +1,18 @@ #!/bin/bash +# +# This file is a part of LEMON, a generic C++ optimization library. +# +# Copyright (C) 2003-2009 +# 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. set -e diff --git a/scripts/unify-sources.sh b/scripts/unify-sources.sh --- a/scripts/unify-sources.sh +++ b/scripts/unify-sources.sh @@ -1,4 +1,18 @@ #!/bin/bash +# +# This file is a part of LEMON, a generic C++ optimization library. +# +# Copyright (C) 2003-2009 +# 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. YEAR=`date +%Y` HGROOT=`hg root` diff --git a/scripts/valgrind-wrapper.sh b/scripts/valgrind-wrapper.sh new file mode 100755 --- /dev/null +++ b/scripts/valgrind-wrapper.sh @@ -0,0 +1,22 @@ +#!/bin/sh + +# Run in valgrind, with leak checking enabled + +valgrind -q --leak-check=full "$@" 2> .valgrind-log + +# Save the test result + +result="$?" + +# Valgrind should generate no error messages + +log_contents="`cat .valgrind-log`" + +if [ "$log_contents" != "" ]; then + cat .valgrind-log >&2 + result=1 +fi + +rm -f .valgrind-log + +exit $result diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -32,6 +32,7 @@ matching_test min_cost_arborescence_test min_cost_flow_test + min_mean_cycle_test path_test planarity_test preflow_test diff --git a/test/Makefile.am b/test/Makefile.am --- a/test/Makefile.am +++ b/test/Makefile.am @@ -1,3 +1,7 @@ +if USE_VALGRIND +TESTS_ENVIRONMENT=$(top_srcdir)/scripts/valgrind-wrapper.sh +endif + EXTRA_DIST += \ test/CMakeLists.txt @@ -30,6 +34,7 @@ test/matching_test \ test/min_cost_arborescence_test \ test/min_cost_flow_test \ + test/min_mean_cycle_test \ test/path_test \ test/planarity_test \ test/preflow_test \ @@ -79,6 +84,7 @@ test_matching_test_SOURCES = test/matching_test.cc test_min_cost_arborescence_test_SOURCES = test/min_cost_arborescence_test.cc test_min_cost_flow_test_SOURCES = test/min_cost_flow_test.cc +test_min_mean_cycle_test_SOURCES = test/min_mean_cycle_test.cc test_path_test_SOURCES = test/path_test.cc test_planarity_test_SOURCES = test/planarity_test.cc test_preflow_test_SOURCES = test/preflow_test.cc diff --git a/test/adaptors_test.cc b/test/adaptors_test.cc --- a/test/adaptors_test.cc +++ b/test/adaptors_test.cc @@ -1371,51 +1371,43 @@ GridGraph::Node n4 = graph(1,1); GridGraph::EdgeMap dir_map(graph); - dir_map[graph.right(n1)] = graph.u(graph.right(n1)) == n1; - dir_map[graph.up(n1)] = graph.u(graph.up(n1)) != n1; - dir_map[graph.left(n4)] = graph.u(graph.left(n4)) != n4; - dir_map[graph.down(n4)] = graph.u(graph.down(n4)) != n4; + dir_map[graph.right(n1)] = graph.u(graph.right(n1)) != n1; + dir_map[graph.up(n1)] = graph.u(graph.up(n1)) == n1; + dir_map[graph.left(n4)] = graph.u(graph.left(n4)) == n4; + dir_map[graph.down(n4)] = graph.u(graph.down(n4)) == n4; // Apply several adaptors on the grid graph - typedef SplitNodes< ReverseDigraph< const Orienter< - const GridGraph, GridGraph::EdgeMap > > > - RevSplitGridGraph; - typedef ReverseDigraph SplitGridGraph; + typedef SplitNodes > > + SplitGridGraph; typedef Undirector USplitGridGraph; - typedef Undirector UUSplitGridGraph; - checkConcept(); checkConcept(); checkConcept(); - checkConcept(); - RevSplitGridGraph rev_adaptor = - splitNodes(reverseDigraph(orienter(graph, dir_map))); - SplitGridGraph adaptor = reverseDigraph(rev_adaptor); + SplitGridGraph adaptor = splitNodes(orienter(graph, dir_map)); USplitGridGraph uadaptor = undirector(adaptor); - UUSplitGridGraph uuadaptor = undirector(uadaptor); // Check adaptor checkGraphNodeList(adaptor, 8); checkGraphArcList(adaptor, 8); checkGraphConArcList(adaptor, 8); - checkGraphOutArcList(adaptor, rev_adaptor.inNode(n1), 1); - checkGraphOutArcList(adaptor, rev_adaptor.outNode(n1), 1); - checkGraphOutArcList(adaptor, rev_adaptor.inNode(n2), 2); - checkGraphOutArcList(adaptor, rev_adaptor.outNode(n2), 1); - checkGraphOutArcList(adaptor, rev_adaptor.inNode(n3), 1); - checkGraphOutArcList(adaptor, rev_adaptor.outNode(n3), 1); - checkGraphOutArcList(adaptor, rev_adaptor.inNode(n4), 0); - checkGraphOutArcList(adaptor, rev_adaptor.outNode(n4), 1); + checkGraphOutArcList(adaptor, adaptor.inNode(n1), 1); + checkGraphOutArcList(adaptor, adaptor.outNode(n1), 1); + checkGraphOutArcList(adaptor, adaptor.inNode(n2), 1); + checkGraphOutArcList(adaptor, adaptor.outNode(n2), 0); + checkGraphOutArcList(adaptor, adaptor.inNode(n3), 1); + checkGraphOutArcList(adaptor, adaptor.outNode(n3), 1); + checkGraphOutArcList(adaptor, adaptor.inNode(n4), 1); + checkGraphOutArcList(adaptor, adaptor.outNode(n4), 2); - checkGraphInArcList(adaptor, rev_adaptor.inNode(n1), 1); - checkGraphInArcList(adaptor, rev_adaptor.outNode(n1), 1); - checkGraphInArcList(adaptor, rev_adaptor.inNode(n2), 1); - checkGraphInArcList(adaptor, rev_adaptor.outNode(n2), 0); - checkGraphInArcList(adaptor, rev_adaptor.inNode(n3), 1); - checkGraphInArcList(adaptor, rev_adaptor.outNode(n3), 1); - checkGraphInArcList(adaptor, rev_adaptor.inNode(n4), 1); - checkGraphInArcList(adaptor, rev_adaptor.outNode(n4), 2); + checkGraphInArcList(adaptor, adaptor.inNode(n1), 1); + checkGraphInArcList(adaptor, adaptor.outNode(n1), 1); + checkGraphInArcList(adaptor, adaptor.inNode(n2), 2); + checkGraphInArcList(adaptor, adaptor.outNode(n2), 1); + checkGraphInArcList(adaptor, adaptor.inNode(n3), 1); + checkGraphInArcList(adaptor, adaptor.outNode(n3), 1); + checkGraphInArcList(adaptor, adaptor.inNode(n4), 0); + checkGraphInArcList(adaptor, adaptor.outNode(n4), 1); checkNodeIds(adaptor); checkArcIds(adaptor); @@ -1438,29 +1430,14 @@ checkGraphEdgeMap(uadaptor); checkGraphArcMap(uadaptor); - checkGraphIncEdgeArcLists(uadaptor, rev_adaptor.inNode(n1), 2); - checkGraphIncEdgeArcLists(uadaptor, rev_adaptor.outNode(n1), 2); - checkGraphIncEdgeArcLists(uadaptor, rev_adaptor.inNode(n2), 3); - checkGraphIncEdgeArcLists(uadaptor, rev_adaptor.outNode(n2), 1); - checkGraphIncEdgeArcLists(uadaptor, rev_adaptor.inNode(n3), 2); - checkGraphIncEdgeArcLists(uadaptor, rev_adaptor.outNode(n3), 2); - checkGraphIncEdgeArcLists(uadaptor, rev_adaptor.inNode(n4), 1); - checkGraphIncEdgeArcLists(uadaptor, rev_adaptor.outNode(n4), 3); - - // Check uuadaptor - checkGraphNodeList(uuadaptor, 8); - checkGraphEdgeList(uuadaptor, 16); - checkGraphArcList(uuadaptor, 32); - checkGraphConEdgeList(uuadaptor, 16); - checkGraphConArcList(uuadaptor, 32); - - checkNodeIds(uuadaptor); - checkEdgeIds(uuadaptor); - checkArcIds(uuadaptor); - - checkGraphNodeMap(uuadaptor); - checkGraphEdgeMap(uuadaptor); - checkGraphArcMap(uuadaptor); + checkGraphIncEdgeArcLists(uadaptor, adaptor.inNode(n1), 2); + checkGraphIncEdgeArcLists(uadaptor, adaptor.outNode(n1), 2); + checkGraphIncEdgeArcLists(uadaptor, adaptor.inNode(n2), 3); + checkGraphIncEdgeArcLists(uadaptor, adaptor.outNode(n2), 1); + checkGraphIncEdgeArcLists(uadaptor, adaptor.inNode(n3), 2); + checkGraphIncEdgeArcLists(uadaptor, adaptor.outNode(n3), 2); + checkGraphIncEdgeArcLists(uadaptor, adaptor.inNode(n4), 1); + checkGraphIncEdgeArcLists(uadaptor, adaptor.outNode(n4), 3); } int main(int, const char **) { diff --git a/test/bellman_ford_test.cc b/test/bellman_ford_test.cc --- a/test/bellman_ford_test.cc +++ b/test/bellman_ford_test.cc @@ -65,7 +65,7 @@ Node s, t, n; Arc e; Value l; - int k; + int k=3; bool b; BF::DistMap d(gr); BF::PredMap p(gr); @@ -96,6 +96,7 @@ d = const_bf_test.distMap(); p = const_bf_test.predMap(); pp = const_bf_test.path(t); + pp = const_bf_test.negativeCycle(); for (BF::ActiveIt it(const_bf_test); it != INVALID; ++it) {} } @@ -132,6 +133,7 @@ s = bf_test.predNode(t); b = bf_test.reached(t); pp = bf_test.path(t); + pp = bf_test.negativeCycle(); } } diff --git a/test/digraph_test.cc b/test/digraph_test.cc --- a/test/digraph_test.cc +++ b/test/digraph_test.cc @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "test_tools.h" @@ -35,6 +36,9 @@ checkGraphNodeList(G, 0); checkGraphArcList(G, 0); + G.reserveNode(3); + G.reserveArc(4); + Node n1 = G.addNode(), n2 = G.addNode(), @@ -283,6 +287,14 @@ G.addArc(G.addNode(), G.addNode()); snapshot.restore(); + snapshot.save(G); + + checkGraphNodeList(G, 4); + checkGraphArcList(G, 4); + + G.addArc(G.addNode(), G.addNode()); + + snapshot.restore(); checkGraphNodeList(G, 4); checkGraphArcList(G, 4); @@ -317,6 +329,10 @@ checkConcept, SmartDigraph>(); checkConcept, SmartDigraph>(); } + { // Checking StaticDigraph + checkConcept(); + checkConcept, StaticDigraph>(); + } { // Checking FullDigraph checkConcept(); } @@ -372,10 +388,122 @@ check(!g.valid(g.arcFromId(-1)), "Wrong validity check"); } +void checkStaticDigraph() { + SmartDigraph g; + SmartDigraph::NodeMap nref(g); + SmartDigraph::ArcMap aref(g); + + StaticDigraph G; + + checkGraphNodeList(G, 0); + checkGraphArcList(G, 0); + + G.build(g, nref, aref); + + checkGraphNodeList(G, 0); + checkGraphArcList(G, 0); + + SmartDigraph::Node + n1 = g.addNode(), + n2 = g.addNode(), + n3 = g.addNode(); + + G.build(g, nref, aref); + + checkGraphNodeList(G, 3); + checkGraphArcList(G, 0); + + SmartDigraph::Arc a1 = g.addArc(n1, n2); + + G.build(g, nref, aref); + + check(G.source(aref[a1]) == nref[n1] && G.target(aref[a1]) == nref[n2], + "Wrong arc or wrong references"); + checkGraphNodeList(G, 3); + checkGraphArcList(G, 1); + + checkGraphOutArcList(G, nref[n1], 1); + checkGraphOutArcList(G, nref[n2], 0); + checkGraphOutArcList(G, nref[n3], 0); + + checkGraphInArcList(G, nref[n1], 0); + checkGraphInArcList(G, nref[n2], 1); + checkGraphInArcList(G, nref[n3], 0); + + checkGraphConArcList(G, 1); + + SmartDigraph::Arc + a2 = g.addArc(n2, n1), + a3 = g.addArc(n2, n3), + a4 = g.addArc(n2, n3); + + digraphCopy(g, G).nodeRef(nref).run(); + + checkGraphNodeList(G, 3); + checkGraphArcList(G, 4); + + checkGraphOutArcList(G, nref[n1], 1); + checkGraphOutArcList(G, nref[n2], 3); + checkGraphOutArcList(G, nref[n3], 0); + + checkGraphInArcList(G, nref[n1], 1); + checkGraphInArcList(G, nref[n2], 1); + checkGraphInArcList(G, nref[n3], 2); + + checkGraphConArcList(G, 4); + + std::vector > arcs; + arcs.push_back(std::make_pair(0,1)); + arcs.push_back(std::make_pair(0,2)); + arcs.push_back(std::make_pair(1,3)); + arcs.push_back(std::make_pair(1,2)); + arcs.push_back(std::make_pair(3,0)); + arcs.push_back(std::make_pair(3,3)); + arcs.push_back(std::make_pair(4,2)); + arcs.push_back(std::make_pair(4,3)); + arcs.push_back(std::make_pair(4,1)); + + G.build(6, arcs.begin(), arcs.end()); + + checkGraphNodeList(G, 6); + checkGraphArcList(G, 9); + + checkGraphOutArcList(G, G.node(0), 2); + checkGraphOutArcList(G, G.node(1), 2); + checkGraphOutArcList(G, G.node(2), 0); + checkGraphOutArcList(G, G.node(3), 2); + checkGraphOutArcList(G, G.node(4), 3); + checkGraphOutArcList(G, G.node(5), 0); + + checkGraphInArcList(G, G.node(0), 1); + checkGraphInArcList(G, G.node(1), 2); + checkGraphInArcList(G, G.node(2), 3); + checkGraphInArcList(G, G.node(3), 3); + checkGraphInArcList(G, G.node(4), 0); + checkGraphInArcList(G, G.node(5), 0); + + checkGraphConArcList(G, 9); + + checkNodeIds(G); + checkArcIds(G); + checkGraphNodeMap(G); + checkGraphArcMap(G); + + int n = G.nodeNum(); + int m = G.arcNum(); + check(G.index(G.node(n-1)) == n-1, "Wrong index."); + check(G.index(G.arc(m-1)) == m-1, "Wrong index."); +} + void checkFullDigraph(int num) { typedef FullDigraph Digraph; DIGRAPH_TYPEDEFS(Digraph); + Digraph G(num); + check(G.nodeNum() == num && G.arcNum() == num * num, "Wrong size"); + + G.resize(num); + check(G.nodeNum() == num && G.arcNum() == num * num, "Wrong size"); checkGraphNodeList(G, num); checkGraphArcList(G, num * num); @@ -419,6 +547,9 @@ checkDigraphSnapshot(); checkDigraphValidity(); } + { // Checking StaticDigraph + checkStaticDigraph(); + } { // Checking FullDigraph checkFullDigraph(8); } diff --git a/test/graph_test.cc b/test/graph_test.cc --- a/test/graph_test.cc +++ b/test/graph_test.cc @@ -38,6 +38,9 @@ checkGraphEdgeList(G, 0); checkGraphArcList(G, 0); + G.reserveNode(3); + G.reserveEdge(3); + Node n1 = G.addNode(), n2 = G.addNode(), @@ -256,6 +259,15 @@ G.addEdge(G.addNode(), G.addNode()); snapshot.restore(); + snapshot.save(G); + + checkGraphNodeList(G, 4); + checkGraphEdgeList(G, 3); + checkGraphArcList(G, 6); + + G.addEdge(G.addNode(), G.addNode()); + + snapshot.restore(); checkGraphNodeList(G, 4); checkGraphEdgeList(G, 3); @@ -267,6 +279,13 @@ GRAPH_TYPEDEFS(Graph); Graph G(num); + check(G.nodeNum() == num && G.edgeNum() == num * (num - 1) / 2, + "Wrong size"); + + G.resize(num); + check(G.nodeNum() == num && G.edgeNum() == num * (num - 1) / 2, + "Wrong size"); + checkGraphNodeList(G, num); checkGraphEdgeList(G, num * (num - 1) / 2); @@ -411,6 +430,10 @@ check(G.width() == width, "Wrong column number"); check(G.height() == height, "Wrong row number"); + G.resize(width, height); + check(G.width() == width, "Wrong column number"); + check(G.height() == height, "Wrong row number"); + for (int i = 0; i < width; ++i) { for (int j = 0; j < height; ++j) { check(G.col(G(i, j)) == i, "Wrong column"); @@ -486,6 +509,11 @@ GRAPH_TYPEDEFS(HypercubeGraph); HypercubeGraph G(dim); + check(G.dimension() == dim, "Wrong dimension"); + + G.resize(dim); + check(G.dimension() == dim, "Wrong dimension"); + checkGraphNodeList(G, 1 << dim); checkGraphEdgeList(G, dim * (1 << (dim-1))); checkGraphArcList(G, dim * (1 << dim)); diff --git a/test/maps_test.cc b/test/maps_test.cc --- a/test/maps_test.cc +++ b/test/maps_test.cc @@ -22,7 +22,11 @@ #include #include #include +#include #include +#include +#include +#include #include "test_tools.h" @@ -34,9 +38,22 @@ struct B {}; class C { - int x; + int _x; public: - C(int _x) : x(_x) {} + C(int x) : _x(x) {} + int get() const { return _x; } +}; +inline bool operator<(C c1, C c2) { return c1.get() < c2.get(); } +inline bool operator==(C c1, C c2) { return c1.get() == c2.get(); } + +C createC(int x) { return C(x); } + +template +class Less { + T _t; +public: + Less(T t): _t(t) {} + bool operator()(const T& t) const { return t < _t; } }; class F { @@ -53,6 +70,14 @@ int binc(int a, B) { return a+1; } +template +class Sum { + T& _sum; +public: + Sum(T& sum) : _sum(sum) {} + void operator()(const T& t) { _sum += t; } +}; + typedef ReadMap DoubleMap; typedef ReadWriteMap DoubleWriteMap; typedef ReferenceMap DoubleRefMap; @@ -329,6 +354,10 @@ // LoggerBoolMap { typedef std::vector vec; + checkConcept, LoggerBoolMap >(); + checkConcept, + LoggerBoolMap > >(); + vec v1; vec v2(10); LoggerBoolMap > @@ -348,6 +377,223 @@ for ( LoggerBoolMap::Iterator it = map2.begin(); it != map2.end(); ++it ) check(v1[i++] == *it, "Something is wrong with LoggerBoolMap"); + + typedef ListDigraph Graph; + DIGRAPH_TYPEDEFS(Graph); + Graph gr; + + Node n0 = gr.addNode(); + Node n1 = gr.addNode(); + Node n2 = gr.addNode(); + Node n3 = gr.addNode(); + + gr.addArc(n3, n0); + gr.addArc(n3, n2); + gr.addArc(n0, n2); + gr.addArc(n2, n1); + gr.addArc(n0, n1); + + { + std::vector v; + dfs(gr).processedMap(loggerBoolMap(std::back_inserter(v))).run(); + + check(v.size()==4 && v[0]==n1 && v[1]==n2 && v[2]==n0 && v[3]==n3, + "Something is wrong with LoggerBoolMap"); + } + { + std::vector v(countNodes(gr)); + dfs(gr).processedMap(loggerBoolMap(v.begin())).run(); + + check(v.size()==4 && v[0]==n1 && v[1]==n2 && v[2]==n0 && v[3]==n3, + "Something is wrong with LoggerBoolMap"); + } + } + + // IdMap, RangeIdMap + { + typedef ListDigraph Graph; + DIGRAPH_TYPEDEFS(Graph); + + checkConcept, IdMap >(); + checkConcept, IdMap >(); + checkConcept, RangeIdMap >(); + checkConcept, RangeIdMap >(); + + Graph gr; + IdMap nmap(gr); + IdMap amap(gr); + RangeIdMap nrmap(gr); + RangeIdMap armap(gr); + + Node n0 = gr.addNode(); + Node n1 = gr.addNode(); + Node n2 = gr.addNode(); + + Arc a0 = gr.addArc(n0, n1); + Arc a1 = gr.addArc(n0, n2); + Arc a2 = gr.addArc(n2, n1); + Arc a3 = gr.addArc(n2, n0); + + check(nmap[n0] == gr.id(n0) && nmap(gr.id(n0)) == n0, "Wrong IdMap"); + check(nmap[n1] == gr.id(n1) && nmap(gr.id(n1)) == n1, "Wrong IdMap"); + check(nmap[n2] == gr.id(n2) && nmap(gr.id(n2)) == n2, "Wrong IdMap"); + + check(amap[a0] == gr.id(a0) && amap(gr.id(a0)) == a0, "Wrong IdMap"); + check(amap[a1] == gr.id(a1) && amap(gr.id(a1)) == a1, "Wrong IdMap"); + check(amap[a2] == gr.id(a2) && amap(gr.id(a2)) == a2, "Wrong IdMap"); + check(amap[a3] == gr.id(a3) && amap(gr.id(a3)) == a3, "Wrong IdMap"); + + check(nmap.inverse()[gr.id(n0)] == n0, "Wrong IdMap::InverseMap"); + check(amap.inverse()[gr.id(a0)] == a0, "Wrong IdMap::InverseMap"); + + check(nrmap.size() == 3 && armap.size() == 4, + "Wrong RangeIdMap::size()"); + + check(nrmap[n0] == 0 && nrmap(0) == n0, "Wrong RangeIdMap"); + check(nrmap[n1] == 1 && nrmap(1) == n1, "Wrong RangeIdMap"); + check(nrmap[n2] == 2 && nrmap(2) == n2, "Wrong RangeIdMap"); + + check(armap[a0] == 0 && armap(0) == a0, "Wrong RangeIdMap"); + check(armap[a1] == 1 && armap(1) == a1, "Wrong RangeIdMap"); + check(armap[a2] == 2 && armap(2) == a2, "Wrong RangeIdMap"); + check(armap[a3] == 3 && armap(3) == a3, "Wrong RangeIdMap"); + + check(nrmap.inverse()[0] == n0, "Wrong RangeIdMap::InverseMap"); + check(armap.inverse()[0] == a0, "Wrong RangeIdMap::InverseMap"); + + gr.erase(n1); + + if (nrmap[n0] == 1) nrmap.swap(n0, n2); + nrmap.swap(n2, n0); + if (armap[a1] == 1) armap.swap(a1, a3); + armap.swap(a3, a1); + + check(nrmap.size() == 2 && armap.size() == 2, + "Wrong RangeIdMap::size()"); + + check(nrmap[n0] == 1 && nrmap(1) == n0, "Wrong RangeIdMap"); + check(nrmap[n2] == 0 && nrmap(0) == n2, "Wrong RangeIdMap"); + + check(armap[a1] == 1 && armap(1) == a1, "Wrong RangeIdMap"); + check(armap[a3] == 0 && armap(0) == a3, "Wrong RangeIdMap"); + + check(nrmap.inverse()[0] == n2, "Wrong RangeIdMap::InverseMap"); + check(armap.inverse()[0] == a3, "Wrong RangeIdMap::InverseMap"); + } + + // SourceMap, TargetMap, ForwardMap, BackwardMap, InDegMap, OutDegMap + { + typedef ListGraph Graph; + GRAPH_TYPEDEFS(Graph); + + checkConcept, SourceMap >(); + checkConcept, TargetMap >(); + checkConcept, ForwardMap >(); + checkConcept, BackwardMap >(); + checkConcept, InDegMap >(); + checkConcept, OutDegMap >(); + + Graph gr; + Node n0 = gr.addNode(); + Node n1 = gr.addNode(); + Node n2 = gr.addNode(); + + gr.addEdge(n0,n1); + gr.addEdge(n1,n2); + gr.addEdge(n0,n2); + gr.addEdge(n2,n1); + gr.addEdge(n1,n2); + gr.addEdge(n0,n1); + + for (EdgeIt e(gr); e != INVALID; ++e) { + check(forwardMap(gr)[e] == gr.direct(e, true), "Wrong ForwardMap"); + check(backwardMap(gr)[e] == gr.direct(e, false), "Wrong BackwardMap"); + } + + check(mapCompare(gr, + sourceMap(orienter(gr, constMap(true))), + targetMap(orienter(gr, constMap(false)))), + "Wrong SourceMap or TargetMap"); + + typedef Orienter > Digraph; + Digraph dgr(gr, constMap(true)); + OutDegMap odm(dgr); + InDegMap idm(dgr); + + check(odm[n0] == 3 && odm[n1] == 2 && odm[n2] == 1, "Wrong OutDegMap"); + check(idm[n0] == 0 && idm[n1] == 3 && idm[n2] == 3, "Wrong InDegMap"); + + gr.addEdge(n2, n0); + + check(odm[n0] == 3 && odm[n1] == 2 && odm[n2] == 2, "Wrong OutDegMap"); + check(idm[n0] == 1 && idm[n1] == 3 && idm[n2] == 3, "Wrong InDegMap"); + } + + // CrossRefMap + { + typedef ListDigraph Graph; + DIGRAPH_TYPEDEFS(Graph); + + checkConcept, + CrossRefMap >(); + checkConcept, + CrossRefMap >(); + checkConcept, + CrossRefMap >(); + + Graph gr; + typedef CrossRefMap CRMap; + CRMap map(gr); + + Node n0 = gr.addNode(); + Node n1 = gr.addNode(); + Node n2 = gr.addNode(); + + map.set(n0, 'A'); + map.set(n1, 'B'); + map.set(n2, 'C'); + + check(map[n0] == 'A' && map('A') == n0 && map.inverse()['A'] == n0, + "Wrong CrossRefMap"); + check(map[n1] == 'B' && map('B') == n1 && map.inverse()['B'] == n1, + "Wrong CrossRefMap"); + check(map[n2] == 'C' && map('C') == n2 && map.inverse()['C'] == n2, + "Wrong CrossRefMap"); + check(map.count('A') == 1 && map.count('B') == 1 && map.count('C') == 1, + "Wrong CrossRefMap::count()"); + + CRMap::ValueIt it = map.beginValue(); + check(*it++ == 'A' && *it++ == 'B' && *it++ == 'C' && + it == map.endValue(), "Wrong value iterator"); + + map.set(n2, 'A'); + + check(map[n0] == 'A' && map[n1] == 'B' && map[n2] == 'A', + "Wrong CrossRefMap"); + check(map('A') == n0 && map.inverse()['A'] == n0, "Wrong CrossRefMap"); + check(map('B') == n1 && map.inverse()['B'] == n1, "Wrong CrossRefMap"); + check(map('C') == INVALID && map.inverse()['C'] == INVALID, + "Wrong CrossRefMap"); + check(map.count('A') == 2 && map.count('B') == 1 && map.count('C') == 0, + "Wrong CrossRefMap::count()"); + + it = map.beginValue(); + check(*it++ == 'A' && *it++ == 'A' && *it++ == 'B' && + it == map.endValue(), "Wrong value iterator"); + + map.set(n0, 'C'); + + check(map[n0] == 'C' && map[n1] == 'B' && map[n2] == 'A', + "Wrong CrossRefMap"); + check(map('A') == n2 && map.inverse()['A'] == n2, "Wrong CrossRefMap"); + check(map('B') == n1 && map.inverse()['B'] == n1, "Wrong CrossRefMap"); + check(map('C') == n0 && map.inverse()['C'] == n0, "Wrong CrossRefMap"); + check(map.count('A') == 1 && map.count('B') == 1 && map.count('C') == 1, + "Wrong CrossRefMap::count()"); + + it = map.beginValue(); + check(*it++ == 'A' && *it++ == 'B' && *it++ == 'C' && + it == map.endValue(), "Wrong value iterator"); } // CrossRefMap @@ -546,10 +792,10 @@ check(static_cast(it) == INVALID, "Wrong value"); } - for (Ivm::ValueIterator vit = map1.beginValue(); + for (Ivm::ValueIt vit = map1.beginValue(); vit != map1.endValue(); ++vit) { check(map1[static_cast(Ivm::ItemIt(map1, *vit))] == *vit, - "Wrong ValueIterator"); + "Wrong ValueIt"); } for (int i = 0; i < num; ++i) { @@ -571,5 +817,183 @@ check(n == num, "Wrong number"); } + + // Graph map utilities: + // mapMin(), mapMax(), mapMinValue(), mapMaxValue() + // mapFind(), mapFindIf(), mapCount(), mapCountIf() + // mapCopy(), mapCompare(), mapFill() + { + DIGRAPH_TYPEDEFS(SmartDigraph); + + SmartDigraph g; + Node n1 = g.addNode(); + Node n2 = g.addNode(); + Node n3 = g.addNode(); + + SmartDigraph::NodeMap map1(g); + SmartDigraph::ArcMap map2(g); + ConstMap cmap1 = A(); + ConstMap cmap2 = C(0); + + map1[n1] = 10; + map1[n2] = 5; + map1[n3] = 12; + + // mapMin(), mapMax(), mapMinValue(), mapMaxValue() + check(mapMin(g, map1) == n2, "Wrong mapMin()"); + check(mapMax(g, map1) == n3, "Wrong mapMax()"); + check(mapMin(g, map1, std::greater()) == n3, "Wrong mapMin()"); + check(mapMax(g, map1, std::greater()) == n2, "Wrong mapMax()"); + check(mapMinValue(g, map1) == 5, "Wrong mapMinValue()"); + check(mapMaxValue(g, map1) == 12, "Wrong mapMaxValue()"); + + check(mapMin(g, map2) == INVALID, "Wrong mapMin()"); + check(mapMax(g, map2) == INVALID, "Wrong mapMax()"); + + check(mapMin(g, cmap1) != INVALID, "Wrong mapMin()"); + check(mapMax(g, cmap2) == INVALID, "Wrong mapMax()"); + + Arc a1 = g.addArc(n1, n2); + Arc a2 = g.addArc(n1, n3); + Arc a3 = g.addArc(n2, n3); + Arc a4 = g.addArc(n3, n1); + + map2[a1] = 'b'; + map2[a2] = 'a'; + map2[a3] = 'b'; + map2[a4] = 'c'; + + // mapMin(), mapMax(), mapMinValue(), mapMaxValue() + check(mapMin(g, map2) == a2, "Wrong mapMin()"); + check(mapMax(g, map2) == a4, "Wrong mapMax()"); + check(mapMin(g, map2, std::greater()) == a4, "Wrong mapMin()"); + check(mapMax(g, map2, std::greater()) == a2, "Wrong mapMax()"); + check(mapMinValue(g, map2, std::greater()) == 'c', + "Wrong mapMinValue()"); + check(mapMaxValue(g, map2, std::greater()) == 'a', + "Wrong mapMaxValue()"); + + check(mapMin(g, cmap1) != INVALID, "Wrong mapMin()"); + check(mapMax(g, cmap2) != INVALID, "Wrong mapMax()"); + check(mapMaxValue(g, cmap2) == C(0), "Wrong mapMaxValue()"); + + check(mapMin(g, composeMap(functorToMap(&createC), map2)) == a2, + "Wrong mapMin()"); + check(mapMax(g, composeMap(functorToMap(&createC), map2)) == a4, + "Wrong mapMax()"); + check(mapMinValue(g, composeMap(functorToMap(&createC), map2)) == C('a'), + "Wrong mapMinValue()"); + check(mapMaxValue(g, composeMap(functorToMap(&createC), map2)) == C('c'), + "Wrong mapMaxValue()"); + + // mapFind(), mapFindIf() + check(mapFind(g, map1, 5) == n2, "Wrong mapFind()"); + check(mapFind(g, map1, 6) == INVALID, "Wrong mapFind()"); + check(mapFind(g, map2, 'a') == a2, "Wrong mapFind()"); + check(mapFind(g, map2, 'e') == INVALID, "Wrong mapFind()"); + check(mapFind(g, cmap2, C(0)) == ArcIt(g), "Wrong mapFind()"); + check(mapFind(g, cmap2, C(1)) == INVALID, "Wrong mapFind()"); + + check(mapFindIf(g, map1, Less(7)) == n2, + "Wrong mapFindIf()"); + check(mapFindIf(g, map1, Less(5)) == INVALID, + "Wrong mapFindIf()"); + check(mapFindIf(g, map2, Less('d')) == ArcIt(g), + "Wrong mapFindIf()"); + check(mapFindIf(g, map2, Less('a')) == INVALID, + "Wrong mapFindIf()"); + + // mapCount(), mapCountIf() + check(mapCount(g, map1, 5) == 1, "Wrong mapCount()"); + check(mapCount(g, map1, 6) == 0, "Wrong mapCount()"); + check(mapCount(g, map2, 'a') == 1, "Wrong mapCount()"); + check(mapCount(g, map2, 'b') == 2, "Wrong mapCount()"); + check(mapCount(g, map2, 'e') == 0, "Wrong mapCount()"); + check(mapCount(g, cmap2, C(0)) == 4, "Wrong mapCount()"); + check(mapCount(g, cmap2, C(1)) == 0, "Wrong mapCount()"); + + check(mapCountIf(g, map1, Less(11)) == 2, + "Wrong mapCountIf()"); + check(mapCountIf(g, map1, Less(13)) == 3, + "Wrong mapCountIf()"); + check(mapCountIf(g, map1, Less(5)) == 0, + "Wrong mapCountIf()"); + check(mapCountIf(g, map2, Less('d')) == 4, + "Wrong mapCountIf()"); + check(mapCountIf(g, map2, Less('c')) == 3, + "Wrong mapCountIf()"); + check(mapCountIf(g, map2, Less('a')) == 0, + "Wrong mapCountIf()"); + + // MapIt, ConstMapIt +/* +These tests can be used after applying bugfix #330 + typedef SmartDigraph::NodeMap::MapIt MapIt; + typedef SmartDigraph::NodeMap::ConstMapIt ConstMapIt; + check(*std::min_element(MapIt(map1), MapIt(INVALID)) == 5, + "Wrong NodeMap<>::MapIt"); + check(*std::max_element(ConstMapIt(map1), ConstMapIt(INVALID)) == 12, + "Wrong NodeMap<>::MapIt"); + + int sum = 0; + std::for_each(MapIt(map1), MapIt(INVALID), Sum(sum)); + check(sum == 27, "Wrong NodeMap<>::MapIt"); + std::for_each(ConstMapIt(map1), ConstMapIt(INVALID), Sum(sum)); + check(sum == 54, "Wrong NodeMap<>::ConstMapIt"); +*/ + + // mapCopy(), mapCompare(), mapFill() + check(mapCompare(g, map1, map1), "Wrong mapCompare()"); + check(mapCompare(g, cmap2, cmap2), "Wrong mapCompare()"); + check(mapCompare(g, map1, shiftMap(map1, 0)), "Wrong mapCompare()"); + check(mapCompare(g, map2, scaleMap(map2, 1)), "Wrong mapCompare()"); + check(!mapCompare(g, map1, shiftMap(map1, 1)), "Wrong mapCompare()"); + + SmartDigraph::NodeMap map3(g, 0); + SmartDigraph::ArcMap map4(g, 'a'); + + check(!mapCompare(g, map1, map3), "Wrong mapCompare()"); + check(!mapCompare(g, map2, map4), "Wrong mapCompare()"); + + mapCopy(g, map1, map3); + mapCopy(g, map2, map4); + + check(mapCompare(g, map1, map3), "Wrong mapCompare() or mapCopy()"); + check(mapCompare(g, map2, map4), "Wrong mapCompare() or mapCopy()"); + + Undirector ug(g); + Undirector::EdgeMap umap1(ug, 'x'); + Undirector::ArcMap umap2(ug, 3.14); + + check(!mapCompare(g, map2, umap1), "Wrong mapCompare() or mapCopy()"); + check(!mapCompare(g, umap1, map2), "Wrong mapCompare() or mapCopy()"); + check(!mapCompare(ug, map2, umap1), "Wrong mapCompare() or mapCopy()"); + check(!mapCompare(ug, umap1, map2), "Wrong mapCompare() or mapCopy()"); + + mapCopy(g, map2, umap1); + + check(mapCompare(g, map2, umap1), "Wrong mapCompare() or mapCopy()"); + check(mapCompare(g, umap1, map2), "Wrong mapCompare() or mapCopy()"); + check(mapCompare(ug, map2, umap1), "Wrong mapCompare() or mapCopy()"); + check(mapCompare(ug, umap1, map2), "Wrong mapCompare() or mapCopy()"); + + mapCopy(g, map2, umap1); + mapCopy(g, umap1, map2); + mapCopy(ug, map2, umap1); + mapCopy(ug, umap1, map2); + + check(!mapCompare(ug, umap1, umap2), "Wrong mapCompare() or mapCopy()"); + mapCopy(ug, umap1, umap2); + check(mapCompare(ug, umap1, umap2), "Wrong mapCompare() or mapCopy()"); + + check(!mapCompare(g, map1, constMap(2)), "Wrong mapCompare()"); + mapFill(g, map1, 2); + check(mapCompare(g, constMap(2), map1), "Wrong mapFill()"); + + check(!mapCompare(g, map2, constMap('z')), "Wrong mapCompare()"); + mapCopy(g, constMap('z'), map2); + check(mapCompare(g, constMap('z'), map2), "Wrong mapCopy()"); + } + return 0; } diff --git a/test/min_mean_cycle_test.cc b/test/min_mean_cycle_test.cc new file mode 100644 --- /dev/null +++ b/test/min_mean_cycle_test.cc @@ -0,0 +1,216 @@ +/* -*- mode: C++; indent-tabs-mode: nil; -*- + * + * This file is a part of LEMON, a generic C++ optimization library. + * + * Copyright (C) 2003-2009 + * 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 +#include + +#include "test_tools.h" + +using namespace lemon; + +char test_lgf[] = + "@nodes\n" + "label\n" + "1\n" + "2\n" + "3\n" + "4\n" + "5\n" + "6\n" + "7\n" + "@arcs\n" + " len1 len2 len3 len4 c1 c2 c3 c4\n" + "1 2 1 1 1 1 0 0 0 0\n" + "2 4 5 5 5 5 1 0 0 0\n" + "2 3 8 8 8 8 0 0 0 0\n" + "3 2 -2 0 0 0 1 0 0 0\n" + "3 4 4 4 4 4 0 0 0 0\n" + "3 7 -4 -4 -4 -4 0 0 0 0\n" + "4 1 2 2 2 2 0 0 0 0\n" + "4 3 3 3 3 3 1 0 0 0\n" + "4 4 3 3 0 0 0 0 1 0\n" + "5 2 4 4 4 4 0 0 0 0\n" + "5 6 3 3 3 3 0 1 0 0\n" + "6 5 2 2 2 2 0 1 0 0\n" + "6 4 -1 -1 -1 -1 0 0 0 0\n" + "6 7 1 1 1 1 0 0 0 0\n" + "7 7 4 4 4 -1 0 0 0 1\n"; + + +// Check the interface of an MMC algorithm +template +struct MmcClassConcept +{ + template + struct Constraints { + void constraints() { + const Constraints& me = *this; + + typedef typename MMC + ::template SetPath > + ::template SetLargeValue + ::Create MmcAlg; + MmcAlg mmc(me.g, me.length); + const MmcAlg& const_mmc = mmc; + + typename MmcAlg::Tolerance tol = const_mmc.tolerance(); + mmc.tolerance(tol); + + b = mmc.cycle(p).run(); + b = mmc.findMinMean(); + b = mmc.findCycle(); + + v = const_mmc.cycleLength(); + i = const_mmc.cycleArcNum(); + d = const_mmc.cycleMean(); + p = const_mmc.cycle(); + } + + typedef concepts::ReadMap LM; + + GR g; + LM length; + ListPath p; + Value v; + int i; + double d; + bool b; + }; +}; + +// Perform a test with the given parameters +template +void checkMmcAlg(const SmartDigraph& gr, + const SmartDigraph::ArcMap& lm, + const SmartDigraph::ArcMap& cm, + int length, int size) { + MMC alg(gr, lm); + alg.findMinMean(); + check(alg.cycleMean() == static_cast(length) / size, + "Wrong cycle mean"); + alg.findCycle(); + check(alg.cycleLength() == length && alg.cycleArcNum() == size, + "Wrong path"); + SmartDigraph::ArcMap cycle(gr, 0); + for (typename MMC::Path::ArcIt a(alg.cycle()); a != INVALID; ++a) { + ++cycle[a]; + } + for (SmartDigraph::ArcIt a(gr); a != INVALID; ++a) { + check(cm[a] == cycle[a], "Wrong path"); + } +} + +// Class for comparing types +template +struct IsSameType { + static const int result = 0; +}; + +template +struct IsSameType { + static const int result = 1; +}; + + +int main() { + #ifdef LEMON_HAVE_LONG_LONG + typedef long long long_int; + #else + typedef long long_int; + #endif + + // Check the interface + { + typedef concepts::Digraph GR; + + // Karp + checkConcept< MmcClassConcept, + Karp > >(); + checkConcept< MmcClassConcept, + Karp > >(); + + // HartmannOrlin + checkConcept< MmcClassConcept, + HartmannOrlin > >(); + checkConcept< MmcClassConcept, + HartmannOrlin > >(); + + // Howard + checkConcept< MmcClassConcept, + Howard > >(); + checkConcept< MmcClassConcept, + Howard > >(); + + if (IsSameType >::LargeValue, + long_int>::result == 0) check(false, "Wrong LargeValue type"); + if (IsSameType >::LargeValue, + double>::result == 0) check(false, "Wrong LargeValue type"); + } + + // Run various tests + { + typedef SmartDigraph GR; + DIGRAPH_TYPEDEFS(GR); + + GR gr; + IntArcMap l1(gr), l2(gr), l3(gr), l4(gr); + IntArcMap c1(gr), c2(gr), c3(gr), c4(gr); + + std::istringstream input(test_lgf); + digraphReader(gr, input). + arcMap("len1", l1). + arcMap("len2", l2). + arcMap("len3", l3). + arcMap("len4", l4). + arcMap("c1", c1). + arcMap("c2", c2). + arcMap("c3", c3). + arcMap("c4", c4). + run(); + + // Karp + checkMmcAlg >(gr, l1, c1, 6, 3); + checkMmcAlg >(gr, l2, c2, 5, 2); + checkMmcAlg >(gr, l3, c3, 0, 1); + checkMmcAlg >(gr, l4, c4, -1, 1); + + // HartmannOrlin + checkMmcAlg >(gr, l1, c1, 6, 3); + checkMmcAlg >(gr, l2, c2, 5, 2); + checkMmcAlg >(gr, l3, c3, 0, 1); + checkMmcAlg >(gr, l4, c4, -1, 1); + + // Howard + checkMmcAlg >(gr, l1, c1, 6, 3); + checkMmcAlg >(gr, l2, c2, 5, 2); + checkMmcAlg >(gr, l3, c3, 0, 1); + checkMmcAlg >(gr, l4, c4, -1, 1); + } + + return 0; +} diff --git a/test/mip_test.cc b/test/mip_test.cc --- a/test/mip_test.cc +++ b/test/mip_test.cc @@ -50,7 +50,8 @@ if (stat == MipSolver::OPTIMAL) { std::ostringstream sbuf; - buf << "Wrong optimal value: the right optimum is " << exp_opt; + sbuf << "Wrong optimal value ("<< mip.solValue() + <<" instead of " << exp_opt << ")"; check(std::abs(mip.solValue()-exp_opt) < 1e-3, sbuf.str()); //+ecvt(exp_opt,2) } diff --git a/test/test_tools.h b/test/test_tools.h --- a/test/test_tools.h +++ b/test/test_tools.h @@ -37,10 +37,14 @@ ///\code check(0==1,"This is obviously false.");\endcode will ///print something like this (and then exits). ///\verbatim file_name.cc:123: error: This is obviously false. \endverbatim -#define check(rc, msg) \ - if(!(rc)) { \ - std::cerr << __FILE__ ":" << __LINE__ << ": error: " << msg << std::endl; \ - abort(); \ - } else { } \ +#define check(rc, msg) \ + { \ + if(!(rc)) { \ + std::cerr << __FILE__ ":" << __LINE__ << ": error: " \ + << msg << std::endl; \ + abort(); \ + } else { } \ + } \ + #endif