1.1 --- a/.hgignore Tue Dec 20 17:44:38 2011 +0100
1.2 +++ b/.hgignore Tue Dec 20 18:15:14 2011 +0100
1.3 @@ -22,6 +22,7 @@
1.4 lemon/libemon.la
1.5 lemon/stamp-h2
1.6 doc/Doxyfile
1.7 +doc/references.dox
1.8 cmake/version.cmake
1.9 .dirstamp
1.10 .libs/*
2.1 --- a/CMakeLists.txt Tue Dec 20 17:44:38 2011 +0100
2.2 +++ b/CMakeLists.txt Tue Dec 20 18:15:14 2011 +0100
2.3 @@ -114,6 +114,8 @@
2.4 CHECK_TYPE_SIZE("long long" LONG_LONG)
2.5 SET(LEMON_HAVE_LONG_LONG ${HAVE_LONG_LONG})
2.6
2.7 +INCLUDE(FindPythonInterp)
2.8 +
2.9 ENABLE_TESTING()
2.10
2.11 IF(${CMAKE_BUILD_TYPE} STREQUAL "Maintainer")
3.1 --- a/INSTALL Tue Dec 20 17:44:38 2011 +0100
3.2 +++ b/INSTALL Tue Dec 20 18:15:14 2011 +0100
3.3 @@ -173,3 +173,25 @@
3.4 --without-coin
3.5
3.6 Disable COIN-OR support.
3.7 +
3.8 +
3.9 +Makefile Variables
3.10 +==================
3.11 +
3.12 +Some Makefile variables are reserved by the GNU Coding Standards for
3.13 +the use of the "user" - the person building the package. For instance,
3.14 +CXX and CXXFLAGS are such variables, and have the same meaning as
3.15 +explained in the previous section. These variables can be set on the
3.16 +command line when invoking `make' like this:
3.17 +`make [VARIABLE=VALUE]...'
3.18 +
3.19 +WARNINGCXXFLAGS is a non-standard Makefile variable introduced by us
3.20 +to hold several compiler flags related to warnings. Its default value
3.21 +can be overridden when invoking `make'. For example to disable all
3.22 +warning flags use `make WARNINGCXXFLAGS='.
3.23 +
3.24 +In order to turn off a single flag from the default set of warning
3.25 +flags, you can use the CXXFLAGS variable, since this is passed after
3.26 +WARNINGCXXFLAGS. For example to turn off `-Wold-style-cast' (which is
3.27 +used by default when g++ is detected) you can use
3.28 +`make CXXFLAGS="-g -O2 -Wno-old-style-cast"'.
4.1 --- a/Makefile.am Tue Dec 20 17:44:38 2011 +0100
4.2 +++ b/Makefile.am Tue Dec 20 18:15:14 2011 +0100
4.3 @@ -44,6 +44,7 @@
4.4 include test/Makefile.am
4.5 include doc/Makefile.am
4.6 include tools/Makefile.am
4.7 +include scripts/Makefile.am
4.8
4.9 DIST_SUBDIRS = demo
4.10
5.1 --- a/README Tue Dec 20 17:44:38 2011 +0100
5.2 +++ b/README Tue Dec 20 18:15:14 2011 +0100
5.3 @@ -17,6 +17,10 @@
5.4
5.5 Copying, distribution and modification conditions and terms.
5.6
5.7 +NEWS
5.8 +
5.9 + News and version history.
5.10 +
5.11 INSTALL
5.12
5.13 General building and installation instructions.
5.14 @@ -33,6 +37,10 @@
5.15
5.16 Some example programs to make you easier to get familiar with LEMON.
5.17
5.18 +scripts/
5.19 +
5.20 + Scripts that make it easier to develop LEMON.
5.21 +
5.22 test/
5.23
5.24 Programs to check the integrity and correctness of LEMON.
6.1 --- a/configure.ac Tue Dec 20 17:44:38 2011 +0100
6.2 +++ b/configure.ac Tue Dec 20 18:15:14 2011 +0100
6.3 @@ -41,6 +41,7 @@
6.4 AC_PROG_LIBTOOL
6.5
6.6 AC_CHECK_PROG([doxygen_found],[doxygen],[yes],[no])
6.7 +AC_CHECK_PROG([python_found],[python],[yes],[no])
6.8 AC_CHECK_PROG([gs_found],[gs],[yes],[no])
6.9
6.10 dnl Detect Intel compiler.
6.11 @@ -82,6 +83,21 @@
6.12 fi
6.13 AM_CONDITIONAL([WANT_TOOLS], [test x"$enable_tools" != x"no"])
6.14
6.15 +dnl Support for running test cases using valgrind.
6.16 +use_valgrind=no
6.17 +AC_ARG_ENABLE([valgrind],
6.18 +AS_HELP_STRING([--enable-valgrind], [use valgrind when running tests]),
6.19 + [use_valgrind=yes])
6.20 +
6.21 +if [[ "$use_valgrind" = "yes" ]]; then
6.22 + AC_CHECK_PROG(HAVE_VALGRIND, valgrind, yes, no)
6.23 +
6.24 + if [[ "$HAVE_VALGRIND" = "no" ]]; then
6.25 + AC_MSG_ERROR([Valgrind not found in PATH.])
6.26 + fi
6.27 +fi
6.28 +AM_CONDITIONAL(USE_VALGRIND, [test "$use_valgrind" = "yes"])
6.29 +
6.30 dnl Checks for header files.
6.31 AC_CHECK_HEADERS(limits.h sys/time.h sys/times.h unistd.h)
6.32
6.33 @@ -128,6 +144,7 @@
6.34 echo CBC support................... : $lx_cbc_found
6.35 echo
6.36 echo Build additional tools........ : $enable_tools
6.37 +echo Use valgrind for tests........ : $use_valgrind
6.38 echo
6.39 echo The packace will be installed in
6.40 echo -n ' '
7.1 --- a/demo/arg_parser_demo.cc Tue Dec 20 17:44:38 2011 +0100
7.2 +++ b/demo/arg_parser_demo.cc Tue Dec 20 18:15:14 2011 +0100
7.3 @@ -2,7 +2,7 @@
7.4 *
7.5 * This file is a part of LEMON, a generic C++ optimization library.
7.6 *
7.7 - * Copyright (C) 2003-2009
7.8 + * Copyright (C) 2003-2010
7.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
7.11 *
7.12 @@ -65,9 +65,18 @@
7.13 ap.other("infile", "The input file.")
7.14 .other("...");
7.15
7.16 + // Throw an exception when problems occurs. The default behavior is to
7.17 + // exit(1) on these cases, but this makes Valgrind falsely warn
7.18 + // about memory leaks.
7.19 + ap.throwOnProblems();
7.20 +
7.21 // Perform the parsing process
7.22 // (in case of any error it terminates the program)
7.23 - ap.parse();
7.24 + // The try {} construct is necessary only if the ap.trowOnProblems()
7.25 + // setting is in use.
7.26 + try {
7.27 + ap.parse();
7.28 + } catch (ArgParserException &) { return 1; }
7.29
7.30 // Check each option if it has been given and print its value
7.31 std::cout << "Parameters of '" << ap.commandName() << "':\n";
8.1 --- a/doc/CMakeLists.txt Tue Dec 20 17:44:38 2011 +0100
8.2 +++ b/doc/CMakeLists.txt Tue Dec 20 18:15:14 2011 +0100
8.3 @@ -17,7 +17,7 @@
8.4 @ONLY
8.5 )
8.6
8.7 -IF(DOXYGEN_EXECUTABLE AND GHOSTSCRIPT_EXECUTABLE)
8.8 +IF(DOXYGEN_EXECUTABLE AND PYTHONINTERP_FOUND AND GHOSTSCRIPT_EXECUTABLE)
8.9 FILE(MAKE_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/html/)
8.10 SET(GHOSTSCRIPT_OPTIONS -dNOPAUSE -dBATCH -q -dEPSCrop -dTextAlphaBits=4 -dGraphicsAlphaBits=4 -sDEVICE=pngalpha)
8.11 ADD_CUSTOM_TARGET(html
8.12 @@ -28,14 +28,17 @@
8.13 COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/connected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/connected_components.eps
8.14 COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/edge_biconnected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/edge_biconnected_components.eps
8.15 COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/grid_graph.png ${CMAKE_CURRENT_SOURCE_DIR}/images/grid_graph.eps
8.16 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/matching.png ${CMAKE_CURRENT_SOURCE_DIR}/images/matching.eps
8.17 COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/node_biconnected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/node_biconnected_components.eps
8.18 COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/nodeshape_0.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_0.eps
8.19 COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/nodeshape_1.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_1.eps
8.20 COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/nodeshape_2.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_2.eps
8.21 COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/nodeshape_3.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_3.eps
8.22 COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/nodeshape_4.png ${CMAKE_CURRENT_SOURCE_DIR}/images/nodeshape_4.eps
8.23 + COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/planar.png ${CMAKE_CURRENT_SOURCE_DIR}/images/planar.eps
8.24 COMMAND ${GHOSTSCRIPT_EXECUTABLE} ${GHOSTSCRIPT_OPTIONS} -r18 -sOutputFile=gen-images/strongly_connected_components.png ${CMAKE_CURRENT_SOURCE_DIR}/images/strongly_connected_components.eps
8.25 COMMAND ${CMAKE_COMMAND} -E remove_directory html
8.26 + COMMAND ${PYTHON_EXECUTABLE} ${PROJECT_SOURCE_DIR}/scripts/bib2dox.py ${CMAKE_CURRENT_SOURCE_DIR}/references.bib >references.dox
8.27 COMMAND ${DOXYGEN_EXECUTABLE} Doxyfile
8.28 WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}
8.29 )
9.1 --- a/doc/Doxyfile.in Tue Dec 20 17:44:38 2011 +0100
9.2 +++ b/doc/Doxyfile.in Tue Dec 20 18:15:14 2011 +0100
9.3 @@ -97,7 +97,8 @@
9.4 "@abs_top_srcdir@/demo" \
9.5 "@abs_top_srcdir@/tools" \
9.6 "@abs_top_srcdir@/test/test_tools.h" \
9.7 - "@abs_top_builddir@/doc/mainpage.dox"
9.8 + "@abs_top_builddir@/doc/mainpage.dox" \
9.9 + "@abs_top_builddir@/doc/references.dox"
9.10 INPUT_ENCODING = UTF-8
9.11 FILE_PATTERNS = *.h \
9.12 *.cc \
10.1 --- a/doc/Makefile.am Tue Dec 20 17:44:38 2011 +0100
10.2 +++ b/doc/Makefile.am Tue Dec 20 18:15:14 2011 +0100
10.3 @@ -27,7 +27,9 @@
10.4 bipartite_partitions.eps \
10.5 connected_components.eps \
10.6 edge_biconnected_components.eps \
10.7 + matching.eps \
10.8 node_biconnected_components.eps \
10.9 + planar.eps \
10.10 strongly_connected_components.eps
10.11
10.12 DOC_EPS_IMAGES = \
10.13 @@ -66,7 +68,19 @@
10.14 exit 1; \
10.15 fi
10.16
10.17 -html-local: $(DOC_PNG_IMAGES)
10.18 +references.dox: doc/references.bib
10.19 + if test ${python_found} = yes; then \
10.20 + cd doc; \
10.21 + python @abs_top_srcdir@/scripts/bib2dox.py @abs_top_builddir@/$< >$@; \
10.22 + cd ..; \
10.23 + else \
10.24 + echo; \
10.25 + echo "Python not found."; \
10.26 + echo; \
10.27 + exit 1; \
10.28 + fi
10.29 +
10.30 +html-local: $(DOC_PNG_IMAGES) references.dox
10.31 if test ${doxygen_found} = yes; then \
10.32 cd doc; \
10.33 doxygen Doxyfile; \
11.1 --- a/doc/groups.dox Tue Dec 20 17:44:38 2011 +0100
11.2 +++ b/doc/groups.dox Tue Dec 20 18:15:14 2011 +0100
11.3 @@ -2,7 +2,7 @@
11.4 *
11.5 * This file is a part of LEMON, a generic C++ optimization library.
11.6 *
11.7 - * Copyright (C) 2003-2009
11.8 + * Copyright (C) 2003-2010
11.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
11.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
11.11 *
11.12 @@ -226,14 +226,6 @@
11.13 */
11.14
11.15 /**
11.16 -@defgroup matrices Matrices
11.17 -@ingroup datas
11.18 -\brief Two dimensional data storages implemented in LEMON.
11.19 -
11.20 -This group contains two dimensional data storages implemented in LEMON.
11.21 -*/
11.22 -
11.23 -/**
11.24 @defgroup paths Path Structures
11.25 @ingroup datas
11.26 \brief %Path structures implemented in LEMON.
11.27 @@ -246,7 +238,36 @@
11.28 efficient to have e.g. the Dijkstra algorithm to store its result in
11.29 any kind of path structure.
11.30
11.31 -\sa lemon::concepts::Path
11.32 +\sa \ref concepts::Path "Path concept"
11.33 +*/
11.34 +
11.35 +/**
11.36 +@defgroup heaps Heap Structures
11.37 +@ingroup datas
11.38 +\brief %Heap structures implemented in LEMON.
11.39 +
11.40 +This group contains the heap structures implemented in LEMON.
11.41 +
11.42 +LEMON provides several heap classes. They are efficient implementations
11.43 +of the abstract data type \e priority \e queue. They store items with
11.44 +specified values called \e priorities in such a way that finding and
11.45 +removing the item with minimum priority are efficient.
11.46 +The basic operations are adding and erasing items, changing the priority
11.47 +of an item, etc.
11.48 +
11.49 +Heaps are crucial in several algorithms, such as Dijkstra and Prim.
11.50 +The heap implementations have the same interface, thus any of them can be
11.51 +used easily in such algorithms.
11.52 +
11.53 +\sa \ref concepts::Heap "Heap concept"
11.54 +*/
11.55 +
11.56 +/**
11.57 +@defgroup matrices Matrices
11.58 +@ingroup datas
11.59 +\brief Two dimensional data storages implemented in LEMON.
11.60 +
11.61 +This group contains two dimensional data storages implemented in LEMON.
11.62 */
11.63
11.64 /**
11.65 @@ -259,6 +280,28 @@
11.66 */
11.67
11.68 /**
11.69 +@defgroup geomdat Geometric Data Structures
11.70 +@ingroup auxdat
11.71 +\brief Geometric data structures implemented in LEMON.
11.72 +
11.73 +This group contains geometric data structures implemented in LEMON.
11.74 +
11.75 + - \ref lemon::dim2::Point "dim2::Point" implements a two dimensional
11.76 + vector with the usual operations.
11.77 + - \ref lemon::dim2::Box "dim2::Box" can be used to determine the
11.78 + rectangular bounding box of a set of \ref lemon::dim2::Point
11.79 + "dim2::Point"'s.
11.80 +*/
11.81 +
11.82 +/**
11.83 +@defgroup matrices Matrices
11.84 +@ingroup auxdat
11.85 +\brief Two dimensional data storages implemented in LEMON.
11.86 +
11.87 +This group contains two dimensional data storages implemented in LEMON.
11.88 +*/
11.89 +
11.90 +/**
11.91 @defgroup algs Algorithms
11.92 \brief This group contains the several algorithms
11.93 implemented in LEMON.
11.94 @@ -273,7 +316,8 @@
11.95 \brief Common graph search algorithms.
11.96
11.97 This group contains the common graph search algorithms, namely
11.98 -\e breadth-first \e search (BFS) and \e depth-first \e search (DFS).
11.99 +\e breadth-first \e search (BFS) and \e depth-first \e search (DFS)
11.100 +\ref clrs01algorithms.
11.101 */
11.102
11.103 /**
11.104 @@ -281,7 +325,8 @@
11.105 @ingroup algs
11.106 \brief Algorithms for finding shortest paths.
11.107
11.108 -This group contains the algorithms for finding shortest paths in digraphs.
11.109 +This group contains the algorithms for finding shortest paths in digraphs
11.110 +\ref clrs01algorithms.
11.111
11.112 - \ref Dijkstra algorithm for finding shortest paths from a source node
11.113 when all arc lengths are non-negative.
11.114 @@ -298,12 +343,21 @@
11.115 */
11.116
11.117 /**
11.118 +@defgroup spantree Minimum Spanning Tree Algorithms
11.119 +@ingroup algs
11.120 +\brief Algorithms for finding minimum cost spanning trees and arborescences.
11.121 +
11.122 +This group contains the algorithms for finding minimum cost spanning
11.123 +trees and arborescences \ref clrs01algorithms.
11.124 +*/
11.125 +
11.126 +/**
11.127 @defgroup max_flow Maximum Flow Algorithms
11.128 @ingroup algs
11.129 \brief Algorithms for finding maximum flows.
11.130
11.131 This group contains the algorithms for finding maximum flows and
11.132 -feasible circulations.
11.133 +feasible circulations \ref clrs01algorithms, \ref amo93networkflows.
11.134
11.135 The \e maximum \e flow \e problem is to find a flow of maximum value between
11.136 a single source and a single target. Formally, there is a \f$G=(V,A)\f$
11.137 @@ -318,17 +372,21 @@
11.138 \f[ 0 \leq f(uv) \leq cap(uv) \quad \forall uv\in A \f]
11.139
11.140 LEMON contains several algorithms for solving maximum flow problems:
11.141 -- \ref EdmondsKarp Edmonds-Karp algorithm.
11.142 -- \ref Preflow Goldberg-Tarjan's preflow push-relabel algorithm.
11.143 -- \ref DinitzSleatorTarjan Dinitz's blocking flow algorithm with dynamic trees.
11.144 -- \ref GoldbergTarjan Preflow push-relabel algorithm with dynamic trees.
11.145 +- \ref EdmondsKarp Edmonds-Karp algorithm
11.146 + \ref edmondskarp72theoretical.
11.147 +- \ref Preflow Goldberg-Tarjan's preflow push-relabel algorithm
11.148 + \ref goldberg88newapproach.
11.149 +- \ref DinitzSleatorTarjan Dinitz's blocking flow algorithm with dynamic trees
11.150 + \ref dinic70algorithm, \ref sleator83dynamic.
11.151 +- \ref GoldbergTarjan !Preflow push-relabel algorithm with dynamic trees
11.152 + \ref goldberg88newapproach, \ref sleator83dynamic.
11.153
11.154 -In most cases the \ref Preflow "Preflow" algorithm provides the
11.155 +In most cases the \ref Preflow algorithm provides the
11.156 fastest method for computing a maximum flow. All implementations
11.157 also provide functions to query the minimum cut, which is the dual
11.158 problem of maximum flow.
11.159
11.160 -\ref Circulation is a preflow push-relabel algorithm implemented directly
11.161 +\ref Circulation is a preflow push-relabel algorithm implemented directly
11.162 for finding feasible circulations, which is a somewhat different problem,
11.163 but it is strongly related to maximum flow.
11.164 For more information, see \ref Circulation.
11.165 @@ -341,18 +399,20 @@
11.166 \brief Algorithms for finding minimum cost flows and circulations.
11.167
11.168 This group contains the algorithms for finding minimum cost flows and
11.169 -circulations. For more information about this problem and its dual
11.170 -solution see \ref min_cost_flow "Minimum Cost Flow Problem".
11.171 +circulations \ref amo93networkflows. For more information about this
11.172 +problem and its dual solution, see \ref min_cost_flow
11.173 +"Minimum Cost Flow Problem".
11.174
11.175 LEMON contains several algorithms for this problem.
11.176 - \ref NetworkSimplex Primal Network Simplex algorithm with various
11.177 - pivot strategies.
11.178 - - \ref CostScaling Push-Relabel and Augment-Relabel algorithms based on
11.179 - cost scaling.
11.180 - - \ref CapacityScaling Successive Shortest %Path algorithm with optional
11.181 - capacity scaling.
11.182 - - \ref CancelAndTighten The Cancel and Tighten algorithm.
11.183 - - \ref CycleCanceling Cycle-Canceling algorithms.
11.184 + pivot strategies \ref dantzig63linearprog, \ref kellyoneill91netsimplex.
11.185 + - \ref CostScaling Cost Scaling algorithm based on push/augment and
11.186 + relabel operations \ref goldberg90approximation, \ref goldberg97efficient,
11.187 + \ref bunnagel98efficient.
11.188 + - \ref CapacityScaling Capacity Scaling algorithm based on the successive
11.189 + shortest path method \ref edmondskarp72theoretical.
11.190 + - \ref CycleCanceling Cycle-Canceling algorithms, two of which are
11.191 + strongly polynomial \ref klein67primal, \ref goldberg89cyclecanceling.
11.192
11.193 In general NetworkSimplex is the most efficient implementation,
11.194 but in special cases other algorithms could be faster.
11.195 @@ -375,7 +435,7 @@
11.196 cut is the \f$X\f$ solution of the next optimization problem:
11.197
11.198 \f[ \min_{X \subset V, X\not\in \{\emptyset, V\}}
11.199 - \sum_{uv\in A, u\in X, v\not\in X}cap(uv) \f]
11.200 + \sum_{uv\in A: u\in X, v\not\in X}cap(uv) \f]
11.201
11.202 LEMON contains several algorithms related to minimum cut problems:
11.203
11.204 @@ -391,27 +451,40 @@
11.205 */
11.206
11.207 /**
11.208 -@defgroup graph_properties Connectivity and Other Graph Properties
11.209 +@defgroup min_mean_cycle Minimum Mean Cycle Algorithms
11.210 @ingroup algs
11.211 -\brief Algorithms for discovering the graph properties
11.212 +\brief Algorithms for finding minimum mean cycles.
11.213
11.214 -This group contains the algorithms for discovering the graph properties
11.215 -like connectivity, bipartiteness, euler property, simplicity etc.
11.216 +This group contains the algorithms for finding minimum mean cycles
11.217 +\ref clrs01algorithms, \ref amo93networkflows.
11.218
11.219 -\image html edge_biconnected_components.png
11.220 -\image latex edge_biconnected_components.eps "bi-edge-connected components" width=\textwidth
11.221 -*/
11.222 +The \e minimum \e mean \e cycle \e problem is to find a directed cycle
11.223 +of minimum mean length (cost) in a digraph.
11.224 +The mean length of a cycle is the average length of its arcs, i.e. the
11.225 +ratio between the total length of the cycle and the number of arcs on it.
11.226
11.227 -/**
11.228 -@defgroup planar Planarity Embedding and Drawing
11.229 -@ingroup algs
11.230 -\brief Algorithms for planarity checking, embedding and drawing
11.231 +This problem has an important connection to \e conservative \e length
11.232 +\e functions, too. A length function on the arcs of a digraph is called
11.233 +conservative if and only if there is no directed cycle of negative total
11.234 +length. For an arbitrary length function, the negative of the minimum
11.235 +cycle mean is the smallest \f$\epsilon\f$ value so that increasing the
11.236 +arc lengths uniformly by \f$\epsilon\f$ results in a conservative length
11.237 +function.
11.238
11.239 -This group contains the algorithms for planarity checking,
11.240 -embedding and drawing.
11.241 +LEMON contains three algorithms for solving the minimum mean cycle problem:
11.242 +- \ref Karp "Karp"'s original algorithm \ref amo93networkflows,
11.243 + \ref dasdan98minmeancycle.
11.244 +- \ref HartmannOrlin "Hartmann-Orlin"'s algorithm, which is an improved
11.245 + version of Karp's algorithm \ref dasdan98minmeancycle.
11.246 +- \ref Howard "Howard"'s policy iteration algorithm
11.247 + \ref dasdan98minmeancycle.
11.248
11.249 -\image html planar.png
11.250 -\image latex planar.eps "Plane graph" width=\textwidth
11.251 +In practice, the Howard algorithm proved to be by far the most efficient
11.252 +one, though the best known theoretical bound on its running time is
11.253 +exponential.
11.254 +Both Karp and HartmannOrlin algorithms run in time O(ne) and use space
11.255 +O(n<sup>2</sup>+e), but the latter one is typically faster due to the
11.256 +applied early termination scheme.
11.257 */
11.258
11.259 /**
11.260 @@ -449,18 +522,49 @@
11.261 - \ref MaxWeightedPerfectMatching
11.262 Edmond's blossom shrinking algorithm for calculating maximum weighted
11.263 perfect matching in general graphs.
11.264 +- \ref MaxFractionalMatching Push-relabel algorithm for calculating
11.265 + maximum cardinality fractional matching in general graphs.
11.266 +- \ref MaxWeightedFractionalMatching Augmenting path algorithm for calculating
11.267 + maximum weighted fractional matching in general graphs.
11.268 +- \ref MaxWeightedPerfectFractionalMatching
11.269 + Augmenting path algorithm for calculating maximum weighted
11.270 + perfect fractional matching in general graphs.
11.271
11.272 -\image html bipartite_matching.png
11.273 -\image latex bipartite_matching.eps "Bipartite Matching" width=\textwidth
11.274 +\image html matching.png
11.275 +\image latex matching.eps "Min Cost Perfect Matching" width=\textwidth
11.276 */
11.277
11.278 /**
11.279 -@defgroup spantree Minimum Spanning Tree Algorithms
11.280 +@defgroup graph_properties Connectivity and Other Graph Properties
11.281 @ingroup algs
11.282 -\brief Algorithms for finding minimum cost spanning trees and arborescences.
11.283 +\brief Algorithms for discovering the graph properties
11.284
11.285 -This group contains the algorithms for finding minimum cost spanning
11.286 -trees and arborescences.
11.287 +This group contains the algorithms for discovering the graph properties
11.288 +like connectivity, bipartiteness, euler property, simplicity etc.
11.289 +
11.290 +\image html connected_components.png
11.291 +\image latex connected_components.eps "Connected components" width=\textwidth
11.292 +*/
11.293 +
11.294 +/**
11.295 +@defgroup planar Planarity Embedding and Drawing
11.296 +@ingroup algs
11.297 +\brief Algorithms for planarity checking, embedding and drawing
11.298 +
11.299 +This group contains the algorithms for planarity checking,
11.300 +embedding and drawing.
11.301 +
11.302 +\image html planar.png
11.303 +\image latex planar.eps "Plane graph" width=\textwidth
11.304 +*/
11.305 +
11.306 +/**
11.307 +@defgroup approx Approximation Algorithms
11.308 +@ingroup algs
11.309 +\brief Approximation algorithms.
11.310 +
11.311 +This group contains the approximation and heuristic algorithms
11.312 +implemented in LEMON.
11.313 */
11.314
11.315 /**
11.316 @@ -473,15 +577,6 @@
11.317 */
11.318
11.319 /**
11.320 -@defgroup approx Approximation Algorithms
11.321 -@ingroup algs
11.322 -\brief Approximation algorithms.
11.323 -
11.324 -This group contains the approximation and heuristic algorithms
11.325 -implemented in LEMON.
11.326 -*/
11.327 -
11.328 -/**
11.329 @defgroup gen_opt_group General Optimization Tools
11.330 \brief This group contains some general optimization frameworks
11.331 implemented in LEMON.
11.332 @@ -491,13 +586,16 @@
11.333 */
11.334
11.335 /**
11.336 -@defgroup lp_group Lp and Mip Solvers
11.337 +@defgroup lp_group LP and MIP Solvers
11.338 @ingroup gen_opt_group
11.339 -\brief Lp and Mip solver interfaces for LEMON.
11.340 +\brief LP and MIP solver interfaces for LEMON.
11.341
11.342 -This group contains Lp and Mip solver interfaces for LEMON. The
11.343 -various LP solvers could be used in the same manner with this
11.344 -interface.
11.345 +This group contains LP and MIP solver interfaces for LEMON.
11.346 +Various LP solvers could be used in the same manner with this
11.347 +high-level interface.
11.348 +
11.349 +The currently supported solvers are \ref glpk, \ref clp, \ref cbc,
11.350 +\ref cplex, \ref soplex.
11.351 */
11.352
11.353 /**
11.354 @@ -587,7 +685,7 @@
11.355 */
11.356
11.357 /**
11.358 -@defgroup dimacs_group DIMACS format
11.359 +@defgroup dimacs_group DIMACS Format
11.360 @ingroup io_group
11.361 \brief Read and write files in DIMACS format
11.362
11.363 @@ -636,8 +734,8 @@
11.364 @ingroup concept
11.365 \brief Skeleton and concept checking classes for graph structures
11.366
11.367 -This group contains the skeletons and concept checking classes of LEMON's
11.368 -graph structures and helper classes used to implement these.
11.369 +This group contains the skeletons and concept checking classes of
11.370 +graph structures.
11.371 */
11.372
11.373 /**
11.374 @@ -649,6 +747,15 @@
11.375 */
11.376
11.377 /**
11.378 +@defgroup tools Standalone Utility Applications
11.379 +
11.380 +Some utility applications are listed here.
11.381 +
11.382 +The standard compilation procedure (<tt>./configure;make</tt>) will compile
11.383 +them, as well.
11.384 +*/
11.385 +
11.386 +/**
11.387 \anchor demoprograms
11.388
11.389 @defgroup demos Demo Programs
11.390 @@ -660,13 +767,4 @@
11.391 <tt>make check</tt> commands.
11.392 */
11.393
11.394 -/**
11.395 -@defgroup tools Standalone Utility Applications
11.396 -
11.397 -Some utility applications are listed here.
11.398 -
11.399 -The standard compilation procedure (<tt>./configure;make</tt>) will compile
11.400 -them, as well.
11.401 -*/
11.402 -
11.403 }
12.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
12.2 +++ b/doc/images/matching.eps Tue Dec 20 18:15:14 2011 +0100
12.3 @@ -0,0 +1,130 @@
12.4 +%!PS-Adobe-2.0 EPSF-2.0
12.5 +%%Creator: LEMON, graphToEps()
12.6 +%%CreationDate: Sun Mar 14 09:08:34 2010
12.7 +%%BoundingBox: -353 -264 559 292
12.8 +%%EndComments
12.9 +/lb { setlinewidth setrgbcolor newpath moveto
12.10 + 4 2 roll 1 index 1 index curveto stroke } bind def
12.11 +/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def
12.12 +/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def
12.13 +/sq { newpath 2 index 1 index add 2 index 2 index add moveto
12.14 + 2 index 1 index sub 2 index 2 index add lineto
12.15 + 2 index 1 index sub 2 index 2 index sub lineto
12.16 + 2 index 1 index add 2 index 2 index sub lineto
12.17 + closepath pop pop pop} bind def
12.18 +/di { newpath 2 index 1 index add 2 index moveto
12.19 + 2 index 2 index 2 index add lineto
12.20 + 2 index 1 index sub 2 index lineto
12.21 + 2 index 2 index 2 index sub lineto
12.22 + closepath pop pop pop} bind def
12.23 +/nc { 0 0 0 setrgbcolor 5 index 5 index 5 index c fill
12.24 + setrgbcolor 1.1 div c fill
12.25 + } bind def
12.26 +/nsq { 0 0 0 setrgbcolor 5 index 5 index 5 index sq fill
12.27 + setrgbcolor 1.1 div sq fill
12.28 + } bind def
12.29 +/ndi { 0 0 0 setrgbcolor 5 index 5 index 5 index di fill
12.30 + setrgbcolor 1.1 div di fill
12.31 + } bind def
12.32 +/nfemale { 0 0 0 setrgbcolor 3 index 0.0909091 1.5 mul mul setlinewidth
12.33 + newpath 5 index 5 index moveto 5 index 5 index 5 index 3.01 mul sub
12.34 + lineto 5 index 4 index .7 mul sub 5 index 5 index 2.2 mul sub moveto
12.35 + 5 index 4 index .7 mul add 5 index 5 index 2.2 mul sub lineto stroke
12.36 + 5 index 5 index 5 index c fill
12.37 + setrgbcolor 1.1 div c fill
12.38 + } bind def
12.39 +/nmale {
12.40 + 0 0 0 setrgbcolor 3 index 0.0909091 1.5 mul mul setlinewidth
12.41 + newpath 5 index 5 index moveto
12.42 + 5 index 4 index 1 mul 1.5 mul add
12.43 + 5 index 5 index 3 sqrt 1.5 mul mul add
12.44 + 1 index 1 index lineto
12.45 + 1 index 1 index 7 index sub moveto
12.46 + 1 index 1 index lineto
12.47 + exch 5 index 3 sqrt .5 mul mul sub exch 5 index .5 mul sub lineto
12.48 + stroke
12.49 + 5 index 5 index 5 index c fill
12.50 + setrgbcolor 1.1 div c fill
12.51 + } bind def
12.52 +/arrl 1 def
12.53 +/arrw 0.3 def
12.54 +/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def
12.55 +/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def
12.56 + /w exch def /len exch def
12.57 + newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto
12.58 + len w sub arrl sub dx dy lrl
12.59 + arrw dy dx neg lrl
12.60 + dx arrl w add mul dy w 2 div arrw add mul sub
12.61 + dy arrl w add mul dx w 2 div arrw add mul add rlineto
12.62 + dx arrl w add mul neg dy w 2 div arrw add mul sub
12.63 + dy arrl w add mul neg dx w 2 div arrw add mul add rlineto
12.64 + arrw dy dx neg lrl
12.65 + len w sub arrl sub neg dx dy lrl
12.66 + closepath fill } bind def
12.67 +/cshow { 2 index 2 index moveto dup stringwidth pop
12.68 + neg 2 div fosi .35 mul neg rmoveto show pop pop} def
12.69 +
12.70 +gsave
12.71 +%Arcs:
12.72 +gsave
12.73 +140.321 266.249 -327.729 150.06 0 0 0 4.99223 l
12.74 +82.1207 -238.726 -245.288 -110.743 0 0 0 4.99223 l
12.75 +336.635 -229.036 533.603 13.109 0 0 0 4.99223 l
12.76 +53.8598 -45.8071 -245.288 -110.743 0 0 0 4.99223 l
12.77 +-75.5617 118.579 -327.729 150.06 0 0 0 4.99223 l
12.78 +-327.729 150.06 -245.288 -110.743 1 0 0 11.9813 l
12.79 +533.603 13.109 218.184 -84.2955 0 0 0 4.99223 l
12.80 +39.87 175.035 141.163 67.2575 0 0 0 4.99223 l
12.81 +53.8598 -45.8071 -75.5617 118.579 0 0 0 4.99223 l
12.82 +-102.406 -141.267 82.1207 -238.726 0 0 0 4.99223 l
12.83 +399.144 166.894 533.603 13.109 1 0 0 11.9813 l
12.84 +39.87 175.035 140.321 266.249 1 0 0 11.9813 l
12.85 +399.144 166.894 140.321 266.249 0 0 0 4.99223 l
12.86 +399.144 166.894 141.163 67.2575 0 0 0 4.99223 l
12.87 +53.8598 -45.8071 204.765 -173.77 0 0 0 4.99223 l
12.88 +82.1207 -238.726 204.765 -173.77 0 0 0 4.99223 l
12.89 +258.227 61.658 399.144 166.894 0 0 0 4.99223 l
12.90 +53.8598 -45.8071 -102.406 -141.267 1 0 0 11.9813 l
12.91 +175.073 -37.4477 141.163 67.2575 0 0 0 4.99223 l
12.92 +258.227 61.658 380 0 0 0 0 4.99223 l
12.93 +34.6739 40.8267 -75.5617 118.579 1 0 0 11.9813 l
12.94 +380 0 533.603 13.109 0 0 0 4.99223 l
12.95 +175.073 -37.4477 380 0 0 0 0 4.99223 l
12.96 +218.184 -84.2955 204.765 -173.77 0 0 0 4.99223 l
12.97 +53.8598 -45.8071 34.6739 40.8267 0 0 0 4.99223 l
12.98 +167.905 -213.988 82.1207 -238.726 1 0 0 11.9813 l
12.99 +336.635 -229.036 204.765 -173.77 1 0 0 11.9813 l
12.100 +336.635 -229.036 167.905 -213.988 0 0 0 4.99223 l
12.101 +329.08 -26.3098 218.184 -84.2955 0 0 0 4.99223 l
12.102 +39.87 175.035 -75.5617 118.579 0 0 0 4.99223 l
12.103 +53.8598 -45.8071 175.073 -37.4477 0 0 0 4.99223 l
12.104 +34.6739 40.8267 141.163 67.2575 0 0 0 4.99223 l
12.105 +258.227 61.658 141.163 67.2575 1 0 0 11.9813 l
12.106 +175.073 -37.4477 218.184 -84.2955 1 0 0 11.9813 l
12.107 +380 0 329.08 -26.3098 1 0 0 11.9813 l
12.108 +grestore
12.109 +%Nodes:
12.110 +gsave
12.111 +-245.288 -110.743 14.9767 1 1 1 nc
12.112 +204.765 -173.77 14.9767 1 1 1 nc
12.113 +-327.729 150.06 14.9767 1 1 1 nc
12.114 +-75.5617 118.579 14.9767 1 1 1 nc
12.115 +218.184 -84.2955 14.9767 1 1 1 nc
12.116 +140.321 266.249 14.9767 1 1 1 nc
12.117 +141.163 67.2575 14.9767 1 1 1 nc
12.118 +82.1207 -238.726 14.9767 1 1 1 nc
12.119 +329.08 -26.3098 14.9767 1 1 1 nc
12.120 +-102.406 -141.267 14.9767 1 1 1 nc
12.121 +533.603 13.109 14.9767 1 1 1 nc
12.122 +167.905 -213.988 14.9767 1 1 1 nc
12.123 +336.635 -229.036 14.9767 1 1 1 nc
12.124 +380 0 14.9767 1 1 1 nc
12.125 +399.144 166.894 14.9767 1 1 1 nc
12.126 +34.6739 40.8267 14.9767 1 1 1 nc
12.127 +39.87 175.035 14.9767 1 1 1 nc
12.128 +175.073 -37.4477 14.9767 1 1 1 nc
12.129 +53.8598 -45.8071 14.9767 1 1 1 nc
12.130 +258.227 61.658 14.9767 1 1 1 nc
12.131 +grestore
12.132 +grestore
12.133 +showpage
13.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
13.2 +++ b/doc/images/planar.eps Tue Dec 20 18:15:14 2011 +0100
13.3 @@ -0,0 +1,181 @@
13.4 +%!PS-Adobe-2.0 EPSF-2.0
13.5 +%%Creator: LEMON, graphToEps()
13.6 +%%CreationDate: Fri Oct 19 18:32:32 2007
13.7 +%%BoundingBox: 0 0 596 842
13.8 +%%DocumentPaperSizes: a4
13.9 +%%EndComments
13.10 +/lb { setlinewidth setrgbcolor newpath moveto
13.11 + 4 2 roll 1 index 1 index curveto stroke } bind def
13.12 +/l { setlinewidth setrgbcolor newpath moveto lineto stroke } bind def
13.13 +/c { newpath dup 3 index add 2 index moveto 0 360 arc closepath } bind def
13.14 +/sq { newpath 2 index 1 index add 2 index 2 index add moveto
13.15 + 2 index 1 index sub 2 index 2 index add lineto
13.16 + 2 index 1 index sub 2 index 2 index sub lineto
13.17 + 2 index 1 index add 2 index 2 index sub lineto
13.18 + closepath pop pop pop} bind def
13.19 +/di { newpath 2 index 1 index add 2 index moveto
13.20 + 2 index 2 index 2 index add lineto
13.21 + 2 index 1 index sub 2 index lineto
13.22 + 2 index 2 index 2 index sub lineto
13.23 + closepath pop pop pop} bind def
13.24 +/nc { 0 0 0 setrgbcolor 5 index 5 index 5 index c fill
13.25 + setrgbcolor 1.1 div c fill
13.26 + } bind def
13.27 +/nsq { 0 0 0 setrgbcolor 5 index 5 index 5 index sq fill
13.28 + setrgbcolor 1.1 div sq fill
13.29 + } bind def
13.30 +/ndi { 0 0 0 setrgbcolor 5 index 5 index 5 index di fill
13.31 + setrgbcolor 1.1 div di fill
13.32 + } bind def
13.33 +/nfemale { 0 0 0 setrgbcolor 3 index 0.0909091 1.5 mul mul setlinewidth
13.34 + newpath 5 index 5 index moveto 5 index 5 index 5 index 3.01 mul sub
13.35 + lineto 5 index 4 index .7 mul sub 5 index 5 index 2.2 mul sub moveto
13.36 + 5 index 4 index .7 mul add 5 index 5 index 2.2 mul sub lineto stroke
13.37 + 5 index 5 index 5 index c fill
13.38 + setrgbcolor 1.1 div c fill
13.39 + } bind def
13.40 +/nmale {
13.41 + 0 0 0 setrgbcolor 3 index 0.0909091 1.5 mul mul setlinewidth
13.42 + newpath 5 index 5 index moveto
13.43 + 5 index 4 index 1 mul 1.5 mul add
13.44 + 5 index 5 index 3 sqrt 1.5 mul mul add
13.45 + 1 index 1 index lineto
13.46 + 1 index 1 index 7 index sub moveto
13.47 + 1 index 1 index lineto
13.48 + exch 5 index 3 sqrt .5 mul mul sub exch 5 index .5 mul sub lineto
13.49 + stroke
13.50 + 5 index 5 index 5 index c fill
13.51 + setrgbcolor 1.1 div c fill
13.52 + } bind def
13.53 +/arrl 1 def
13.54 +/arrw 0.3 def
13.55 +/lrl { 2 index mul exch 2 index mul exch rlineto pop} bind def
13.56 +/arr { setrgbcolor /y1 exch def /x1 exch def /dy exch def /dx exch def
13.57 + /w exch def /len exch def
13.58 + newpath x1 dy w 2 div mul add y1 dx w 2 div mul sub moveto
13.59 + len w sub arrl sub dx dy lrl
13.60 + arrw dy dx neg lrl
13.61 + dx arrl w add mul dy w 2 div arrw add mul sub
13.62 + dy arrl w add mul dx w 2 div arrw add mul add rlineto
13.63 + dx arrl w add mul neg dy w 2 div arrw add mul sub
13.64 + dy arrl w add mul neg dx w 2 div arrw add mul add rlineto
13.65 + arrw dy dx neg lrl
13.66 + len w sub arrl sub neg dx dy lrl
13.67 + closepath fill } bind def
13.68 +/cshow { 2 index 2 index moveto dup stringwidth pop
13.69 + neg 2 div fosi .35 mul neg rmoveto show pop pop} def
13.70 +
13.71 +gsave
13.72 +15 138.307 translate
13.73 +12.7843 dup scale
13.74 +90 rotate
13.75 +0.608112 -43.6081 translate
13.76 +%Edges:
13.77 +gsave
13.78 +9 31 9.5 30.5 10 30 0 0 0 0.091217 lb
13.79 +9 31 5.5 34.5 2 38 0 0 0 0.091217 lb
13.80 +9 31 25.5 16 42 1 0 0 0 0.091217 lb
13.81 +3 40 23 20.5 43 1 0 0 0 0.091217 lb
13.82 +3 40 22.5 20.5 42 1 0 0 0 0.091217 lb
13.83 +3 40 2.5 40.5 2 41 0 0 0 0.091217 lb
13.84 +13 25 10.5 24.5 8 24 0 0 0 0.091217 lb
13.85 +13 25 12 27 11 29 0 0 0 0.091217 lb
13.86 +3 4 2.5 3 2 2 0 0 0 0.091217 lb
13.87 +3 4 4.5 3 6 2 0 0 0 0.091217 lb
13.88 +6 25 7 24.5 8 24 0 0 0 0.091217 lb
13.89 +6 25 6 24.5 6 24 0 0 0 0.091217 lb
13.90 +34 2 33.5 2 33 2 0 0 0 0.091217 lb
13.91 +34 2 35 2 36 2 0 0 0 0.091217 lb
13.92 +6 8 16 9 26 10 0 0 0 0.091217 lb
13.93 +6 8 6 10.5 6 13 0 0 0 0.091217 lb
13.94 +6 8 6 7.5 6 7 0 0 0 0.091217 lb
13.95 +26 10 27.5 8.5 29 7 0 0 0 0.091217 lb
13.96 +26 10 27.5 9 29 8 0 0 0 0.091217 lb
13.97 +10 30 10.5 29.5 11 29 0 0 0 0.091217 lb
13.98 +8 24 7 23.5 6 23 0 0 0 0.091217 lb
13.99 +8 24 8 24.5 8 25 0 0 0 0.091217 lb
13.100 +33 2 32.5 2 32 2 0 0 0 0.091217 lb
13.101 +29 7 17.5 7 6 7 0 0 0 0.091217 lb
13.102 +2 2 1.5 22 1 42 0 0 0 0.091217 lb
13.103 +2 2 3.5 2 5 2 0 0 0 0.091217 lb
13.104 +21 15 13.5 14.5 6 14 0 0 0 0.091217 lb
13.105 +21 15 21 15.5 21 16 0 0 0 0.091217 lb
13.106 +1 42 0.5 42.5 0 43 0 0 0 0.091217 lb
13.107 +1 42 1.5 41.5 2 41 0 0 0 0.091217 lb
13.108 +6 15 6 15.5 6 16 0 0 0 0.091217 lb
13.109 +6 15 6 14.5 6 14 0 0 0 0.091217 lb
13.110 +43 1 22 0.5 1 0 0 0 0 0.091217 lb
13.111 +31 2 18.5 2 6 2 0 0 0 0.091217 lb
13.112 +31 2 31.5 2 32 2 0 0 0 0.091217 lb
13.113 +6 24 6 23.5 6 23 0 0 0 0.091217 lb
13.114 +6 16 6 16.5 6 17 0 0 0 0.091217 lb
13.115 +6 23 6 20 6 17 0 0 0 0.091217 lb
13.116 +6 2 5.5 2 5 2 0 0 0 0.091217 lb
13.117 +6 2 6 4.5 6 7 0 0 0 0.091217 lb
13.118 +0 43 0.5 21.5 1 0 0 0 0 0.091217 lb
13.119 +1 1 19.5 1.5 38 2 0 0 0 0.091217 lb
13.120 +1 1 1 0.5 1 0 0 0 0 0.091217 lb
13.121 +2 38 5.5 31.5 9 25 0 0 0 0.091217 lb
13.122 +25 13 15.5 13 6 13 0 0 0 0.091217 lb
13.123 +25 13 15.5 13.5 6 14 0 0 0 0.091217 lb
13.124 +8 25 8.5 25 9 25 0 0 0 0.091217 lb
13.125 +11 29 24.5 15.5 38 2 0 0 0 0.091217 lb
13.126 +6 17 11.5 18 17 19 0 0 0 0.091217 lb
13.127 +16 23 26.5 12.5 37 2 0 0 0 0.091217 lb
13.128 +16 23 18.5 19.5 21 16 0 0 0 0.091217 lb
13.129 +36 2 36.5 2 37 2 0 0 0 0.091217 lb
13.130 +36 2 32.5 5 29 8 0 0 0 0.091217 lb
13.131 +6 13 6 13.5 6 14 0 0 0 0.091217 lb
13.132 +37 2 37.5 2 38 2 0 0 0 0.091217 lb
13.133 +21 16 19 17.5 17 19 0 0 0 0.091217 lb
13.134 +grestore
13.135 +%Nodes:
13.136 +gsave
13.137 +29 8 0.304556 1 1 1 nc
13.138 +2 41 0.304556 1 1 1 nc
13.139 +6 7 0.304556 1 1 1 nc
13.140 +5 2 0.304556 1 1 1 nc
13.141 +17 19 0.304556 1 1 1 nc
13.142 +21 16 0.304556 1 1 1 nc
13.143 +1 0 0.304556 1 1 1 nc
13.144 +9 25 0.304556 1 1 1 nc
13.145 +6 14 0.304556 1 1 1 nc
13.146 +42 1 0.304556 1 1 1 nc
13.147 +38 2 0.304556 1 1 1 nc
13.148 +37 2 0.304556 1 1 1 nc
13.149 +6 13 0.304556 1 1 1 nc
13.150 +36 2 0.304556 1 1 1 nc
13.151 +16 23 0.304556 1 1 1 nc
13.152 +6 17 0.304556 1 1 1 nc
13.153 +11 29 0.304556 1 1 1 nc
13.154 +8 25 0.304556 1 1 1 nc
13.155 +32 2 0.304556 1 1 1 nc
13.156 +25 13 0.304556 1 1 1 nc
13.157 +2 38 0.304556 1 1 1 nc
13.158 +1 1 0.304556 1 1 1 nc
13.159 +0 43 0.304556 1 1 1 nc
13.160 +6 2 0.304556 1 1 1 nc
13.161 +6 23 0.304556 1 1 1 nc
13.162 +6 16 0.304556 1 1 1 nc
13.163 +6 24 0.304556 1 1 1 nc
13.164 +31 2 0.304556 1 1 1 nc
13.165 +43 1 0.304556 1 1 1 nc
13.166 +6 15 0.304556 1 1 1 nc
13.167 +1 42 0.304556 1 1 1 nc
13.168 +21 15 0.304556 1 1 1 nc
13.169 +2 2 0.304556 1 1 1 nc
13.170 +29 7 0.304556 1 1 1 nc
13.171 +33 2 0.304556 1 1 1 nc
13.172 +8 24 0.304556 1 1 1 nc
13.173 +10 30 0.304556 1 1 1 nc
13.174 +26 10 0.304556 1 1 1 nc
13.175 +6 8 0.304556 1 1 1 nc
13.176 +34 2 0.304556 1 1 1 nc
13.177 +6 25 0.304556 1 1 1 nc
13.178 +3 4 0.304556 1 1 1 nc
13.179 +13 25 0.304556 1 1 1 nc
13.180 +3 40 0.304556 1 1 1 nc
13.181 +9 31 0.304556 1 1 1 nc
13.182 +grestore
13.183 +grestore
13.184 +showpage
14.1 --- a/doc/mainpage.dox.in Tue Dec 20 17:44:38 2011 +0100
14.2 +++ b/doc/mainpage.dox.in Tue Dec 20 18:15:14 2011 +0100
14.3 @@ -2,7 +2,7 @@
14.4 *
14.5 * This file is a part of LEMON, a generic C++ optimization library.
14.6 *
14.7 - * Copyright (C) 2003-2009
14.8 + * Copyright (C) 2003-2010
14.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
14.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
14.11 *
14.12 @@ -21,14 +21,11 @@
14.13
14.14 \section intro Introduction
14.15
14.16 -\subsection whatis What is LEMON
14.17 -
14.18 -LEMON stands for <b>L</b>ibrary for <b>E</b>fficient <b>M</b>odeling
14.19 -and <b>O</b>ptimization in <b>N</b>etworks.
14.20 -It is a C++ template
14.21 -library aimed at combinatorial optimization tasks which
14.22 -often involve in working
14.23 -with graphs.
14.24 +<b>LEMON</b> stands for <i><b>L</b>ibrary for <b>E</b>fficient <b>M</b>odeling
14.25 +and <b>O</b>ptimization in <b>N</b>etworks</i>.
14.26 +It is a C++ template library providing efficient implementations of common
14.27 +data structures and algorithms with focus on combinatorial optimization
14.28 +tasks connected mainly with graphs and networks.
14.29
14.30 <b>
14.31 LEMON is an <a class="el" href="http://opensource.org/">open source</a>
14.32 @@ -38,11 +35,24 @@
14.33 \ref license "license terms".
14.34 </b>
14.35
14.36 -\subsection howtoread How to read the documentation
14.37 +The project is maintained by the
14.38 +<a href="http://www.cs.elte.hu/egres/">Egerváry Research Group on
14.39 +Combinatorial Optimization</a> \ref egres
14.40 +at the Operations Research Department of the
14.41 +<a href="http://www.elte.hu/en/">Eötvös Loránd University</a>,
14.42 +Budapest, Hungary.
14.43 +LEMON is also a member of the <a href="http://www.coin-or.org/">COIN-OR</a>
14.44 +initiative \ref coinor.
14.45 +
14.46 +\section howtoread How to Read the Documentation
14.47
14.48 If you would like to get to know the library, see
14.49 <a class="el" href="http://lemon.cs.elte.hu/pub/tutorial/">LEMON Tutorial</a>.
14.50
14.51 +If you are interested in starting to use the library, see the <a class="el"
14.52 +href="http://lemon.cs.elte.hu/trac/lemon/wiki/InstallGuide/">Installation
14.53 +Guide</a>.
14.54 +
14.55 If you know what you are looking for, then try to find it under the
14.56 <a class="el" href="modules.html">Modules</a> section.
14.57
15.1 --- a/doc/min_cost_flow.dox Tue Dec 20 17:44:38 2011 +0100
15.2 +++ b/doc/min_cost_flow.dox Tue Dec 20 18:15:14 2011 +0100
15.3 @@ -2,7 +2,7 @@
15.4 *
15.5 * This file is a part of LEMON, a generic C++ optimization library.
15.6 *
15.7 - * Copyright (C) 2003-2009
15.8 + * Copyright (C) 2003-2010
15.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
15.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
15.11 *
15.12 @@ -26,7 +26,7 @@
15.13 The \e minimum \e cost \e flow \e problem is to find a feasible flow of
15.14 minimum total cost from a set of supply nodes to a set of demand nodes
15.15 in a network with capacity constraints (lower and upper bounds)
15.16 -and arc costs.
15.17 +and arc costs \ref amo93networkflows.
15.18
15.19 Formally, let \f$G=(V,A)\f$ be a digraph, \f$lower: A\rightarrow\mathbf{R}\f$,
15.20 \f$upper: A\rightarrow\mathbf{R}\cup\{+\infty\}\f$ denote the lower and
15.21 @@ -78,10 +78,10 @@
15.22 - if \f$lower(uv)<f(uv)<upper(uv)\f$, then \f$cost^\pi(uv)=0\f$;
15.23 - if \f$cost^\pi(uv)<0\f$, then \f$f(uv)=upper(uv)\f$.
15.24 - For all \f$u\in V\f$ nodes:
15.25 - - \f$\pi(u)<=0\f$;
15.26 + - \f$\pi(u)\leq 0\f$;
15.27 - if \f$\sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu) \neq sup(u)\f$,
15.28 then \f$\pi(u)=0\f$.
15.29 -
15.30 +
15.31 Here \f$cost^\pi(uv)\f$ denotes the \e reduced \e cost of the arc
15.32 \f$uv\in A\f$ with respect to the potential function \f$\pi\f$, i.e.
15.33 \f[ cost^\pi(uv) = cost(uv) + \pi(u) - \pi(v).\f]
15.34 @@ -119,7 +119,7 @@
15.35 sup(u) \quad \forall u\in V \f]
15.36 \f[ lower(uv) \leq f(uv) \leq upper(uv) \quad \forall uv\in A \f]
15.37
15.38 -It means that the total demand must be less or equal to the
15.39 +It means that the total demand must be less or equal to the
15.40 total supply (i.e. \f$\sum_{u\in V} sup(u)\f$ must be zero or
15.41 positive) and all the demands have to be satisfied, but there
15.42 could be supplies that are not carried out from the supply
15.43 @@ -145,7 +145,7 @@
15.44 - if \f$lower(uv)<f(uv)<upper(uv)\f$, then \f$cost^\pi(uv)=0\f$;
15.45 - if \f$cost^\pi(uv)<0\f$, then \f$f(uv)=upper(uv)\f$.
15.46 - For all \f$u\in V\f$ nodes:
15.47 - - \f$\pi(u)>=0\f$;
15.48 + - \f$\pi(u)\geq 0\f$;
15.49 - if \f$\sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu) \neq sup(u)\f$,
15.50 then \f$\pi(u)=0\f$.
15.51
16.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
16.2 +++ b/doc/references.bib Tue Dec 20 18:15:14 2011 +0100
16.3 @@ -0,0 +1,301 @@
16.4 +%%%%% Defining LEMON %%%%%
16.5 +
16.6 +@misc{lemon,
16.7 + key = {LEMON},
16.8 + title = {{LEMON} -- {L}ibrary for {E}fficient {M}odeling and
16.9 + {O}ptimization in {N}etworks},
16.10 + howpublished = {\url{http://lemon.cs.elte.hu/}},
16.11 + year = 2009
16.12 +}
16.13 +
16.14 +@misc{egres,
16.15 + key = {EGRES},
16.16 + title = {{EGRES} -- {E}gerv{\'a}ry {R}esearch {G}roup on
16.17 + {C}ombinatorial {O}ptimization},
16.18 + url = {http://www.cs.elte.hu/egres/}
16.19 +}
16.20 +
16.21 +@misc{coinor,
16.22 + key = {COIN-OR},
16.23 + title = {{COIN-OR} -- {C}omputational {I}nfrastructure for
16.24 + {O}perations {R}esearch},
16.25 + url = {http://www.coin-or.org/}
16.26 +}
16.27 +
16.28 +
16.29 +%%%%% Other libraries %%%%%%
16.30 +
16.31 +@misc{boost,
16.32 + key = {Boost},
16.33 + title = {{B}oost {C++} {L}ibraries},
16.34 + url = {http://www.boost.org/}
16.35 +}
16.36 +
16.37 +@book{bglbook,
16.38 + author = {Jeremy G. Siek and Lee-Quan Lee and Andrew
16.39 + Lumsdaine},
16.40 + title = {The Boost Graph Library: User Guide and Reference
16.41 + Manual},
16.42 + publisher = {Addison-Wesley},
16.43 + year = 2002
16.44 +}
16.45 +
16.46 +@misc{leda,
16.47 + key = {LEDA},
16.48 + title = {{LEDA} -- {L}ibrary of {E}fficient {D}ata {T}ypes and
16.49 + {A}lgorithms},
16.50 + url = {http://www.algorithmic-solutions.com/}
16.51 +}
16.52 +
16.53 +@book{ledabook,
16.54 + author = {Kurt Mehlhorn and Stefan N{\"a}her},
16.55 + title = {{LEDA}: {A} platform for combinatorial and geometric
16.56 + computing},
16.57 + isbn = {0-521-56329-1},
16.58 + publisher = {Cambridge University Press},
16.59 + address = {New York, NY, USA},
16.60 + year = 1999
16.61 +}
16.62 +
16.63 +
16.64 +%%%%% Tools that LEMON depends on %%%%%
16.65 +
16.66 +@misc{cmake,
16.67 + key = {CMake},
16.68 + title = {{CMake} -- {C}ross {P}latform {M}ake},
16.69 + url = {http://www.cmake.org/}
16.70 +}
16.71 +
16.72 +@misc{doxygen,
16.73 + key = {Doxygen},
16.74 + title = {{Doxygen} -- {S}ource code documentation generator
16.75 + tool},
16.76 + url = {http://www.doxygen.org/}
16.77 +}
16.78 +
16.79 +
16.80 +%%%%% LP/MIP libraries %%%%%
16.81 +
16.82 +@misc{glpk,
16.83 + key = {GLPK},
16.84 + title = {{GLPK} -- {GNU} {L}inear {P}rogramming {K}it},
16.85 + url = {http://www.gnu.org/software/glpk/}
16.86 +}
16.87 +
16.88 +@misc{clp,
16.89 + key = {Clp},
16.90 + title = {{Clp} -- {Coin-Or} {L}inear {P}rogramming},
16.91 + url = {http://projects.coin-or.org/Clp/}
16.92 +}
16.93 +
16.94 +@misc{cbc,
16.95 + key = {Cbc},
16.96 + title = {{Cbc} -- {Coin-Or} {B}ranch and {C}ut},
16.97 + url = {http://projects.coin-or.org/Cbc/}
16.98 +}
16.99 +
16.100 +@misc{cplex,
16.101 + key = {CPLEX},
16.102 + title = {{ILOG} {CPLEX}},
16.103 + url = {http://www.ilog.com/}
16.104 +}
16.105 +
16.106 +@misc{soplex,
16.107 + key = {SoPlex},
16.108 + title = {{SoPlex} -- {T}he {S}equential {O}bject-{O}riented
16.109 + {S}implex},
16.110 + url = {http://soplex.zib.de/}
16.111 +}
16.112 +
16.113 +
16.114 +%%%%% General books %%%%%
16.115 +
16.116 +@book{amo93networkflows,
16.117 + author = {Ravindra K. Ahuja and Thomas L. Magnanti and James
16.118 + B. Orlin},
16.119 + title = {Network Flows: Theory, Algorithms, and Applications},
16.120 + publisher = {Prentice-Hall, Inc.},
16.121 + year = 1993,
16.122 + month = feb,
16.123 + isbn = {978-0136175490}
16.124 +}
16.125 +
16.126 +@book{schrijver03combinatorial,
16.127 + author = {Alexander Schrijver},
16.128 + title = {Combinatorial Optimization: Polyhedra and Efficiency},
16.129 + publisher = {Springer-Verlag},
16.130 + year = 2003,
16.131 + isbn = {978-3540443896}
16.132 +}
16.133 +
16.134 +@book{clrs01algorithms,
16.135 + author = {Thomas H. Cormen and Charles E. Leiserson and Ronald
16.136 + L. Rivest and Clifford Stein},
16.137 + title = {Introduction to Algorithms},
16.138 + publisher = {The MIT Press},
16.139 + year = 2001,
16.140 + edition = {2nd}
16.141 +}
16.142 +
16.143 +@book{stroustrup00cpp,
16.144 + author = {Bjarne Stroustrup},
16.145 + title = {The C++ Programming Language},
16.146 + edition = {3rd},
16.147 + publisher = {Addison-Wesley Professional},
16.148 + isbn = 0201700735,
16.149 + month = {February},
16.150 + year = 2000
16.151 +}
16.152 +
16.153 +
16.154 +%%%%% Maximum flow algorithms %%%%%
16.155 +
16.156 +@article{edmondskarp72theoretical,
16.157 + author = {Jack Edmonds and Richard M. Karp},
16.158 + title = {Theoretical improvements in algorithmic efficiency
16.159 + for network flow problems},
16.160 + journal = {Journal of the ACM},
16.161 + year = 1972,
16.162 + volume = 19,
16.163 + number = 2,
16.164 + pages = {248-264}
16.165 +}
16.166 +
16.167 +@article{goldberg88newapproach,
16.168 + author = {Andrew V. Goldberg and Robert E. Tarjan},
16.169 + title = {A new approach to the maximum flow problem},
16.170 + journal = {Journal of the ACM},
16.171 + year = 1988,
16.172 + volume = 35,
16.173 + number = 4,
16.174 + pages = {921-940}
16.175 +}
16.176 +
16.177 +@article{dinic70algorithm,
16.178 + author = {E. A. Dinic},
16.179 + title = {Algorithm for solution of a problem of maximum flow
16.180 + in a network with power estimation},
16.181 + journal = {Soviet Math. Doklady},
16.182 + year = 1970,
16.183 + volume = 11,
16.184 + pages = {1277-1280}
16.185 +}
16.186 +
16.187 +@article{goldberg08partial,
16.188 + author = {Andrew V. Goldberg},
16.189 + title = {The Partial Augment-Relabel Algorithm for the
16.190 + Maximum Flow Problem},
16.191 + journal = {16th Annual European Symposium on Algorithms},
16.192 + year = 2008,
16.193 + pages = {466-477}
16.194 +}
16.195 +
16.196 +@article{sleator83dynamic,
16.197 + author = {Daniel D. Sleator and Robert E. Tarjan},
16.198 + title = {A data structure for dynamic trees},
16.199 + journal = {Journal of Computer and System Sciences},
16.200 + year = 1983,
16.201 + volume = 26,
16.202 + number = 3,
16.203 + pages = {362-391}
16.204 +}
16.205 +
16.206 +
16.207 +%%%%% Minimum mean cycle algorithms %%%%%
16.208 +
16.209 +@article{karp78characterization,
16.210 + author = {Richard M. Karp},
16.211 + title = {A characterization of the minimum cycle mean in a
16.212 + digraph},
16.213 + journal = {Discrete Math.},
16.214 + year = 1978,
16.215 + volume = 23,
16.216 + pages = {309-311}
16.217 +}
16.218 +
16.219 +@article{dasdan98minmeancycle,
16.220 + author = {Ali Dasdan and Rajesh K. Gupta},
16.221 + title = {Faster Maximum and Minimum Mean Cycle Alogrithms for
16.222 + System Performance Analysis},
16.223 + journal = {IEEE Transactions on Computer-Aided Design of
16.224 + Integrated Circuits and Systems},
16.225 + year = 1998,
16.226 + volume = 17,
16.227 + number = 10,
16.228 + pages = {889-899}
16.229 +}
16.230 +
16.231 +
16.232 +%%%%% Minimum cost flow algorithms %%%%%
16.233 +
16.234 +@article{klein67primal,
16.235 + author = {Morton Klein},
16.236 + title = {A primal method for minimal cost flows with
16.237 + applications to the assignment and transportation
16.238 + problems},
16.239 + journal = {Management Science},
16.240 + year = 1967,
16.241 + volume = 14,
16.242 + pages = {205-220}
16.243 +}
16.244 +
16.245 +@article{goldberg89cyclecanceling,
16.246 + author = {Andrew V. Goldberg and Robert E. Tarjan},
16.247 + title = {Finding minimum-cost circulations by canceling
16.248 + negative cycles},
16.249 + journal = {Journal of the ACM},
16.250 + year = 1989,
16.251 + volume = 36,
16.252 + number = 4,
16.253 + pages = {873-886}
16.254 +}
16.255 +
16.256 +@article{goldberg90approximation,
16.257 + author = {Andrew V. Goldberg and Robert E. Tarjan},
16.258 + title = {Finding Minimum-Cost Circulations by Successive
16.259 + Approximation},
16.260 + journal = {Mathematics of Operations Research},
16.261 + year = 1990,
16.262 + volume = 15,
16.263 + number = 3,
16.264 + pages = {430-466}
16.265 +}
16.266 +
16.267 +@article{goldberg97efficient,
16.268 + author = {Andrew V. Goldberg},
16.269 + title = {An Efficient Implementation of a Scaling
16.270 + Minimum-Cost Flow Algorithm},
16.271 + journal = {Journal of Algorithms},
16.272 + year = 1997,
16.273 + volume = 22,
16.274 + number = 1,
16.275 + pages = {1-29}
16.276 +}
16.277 +
16.278 +@article{bunnagel98efficient,
16.279 + author = {Ursula B{\"u}nnagel and Bernhard Korte and Jens
16.280 + Vygen},
16.281 + title = {Efficient implementation of the {G}oldberg-{T}arjan
16.282 + minimum-cost flow algorithm},
16.283 + journal = {Optimization Methods and Software},
16.284 + year = 1998,
16.285 + volume = 10,
16.286 + pages = {157-174}
16.287 +}
16.288 +
16.289 +@book{dantzig63linearprog,
16.290 + author = {George B. Dantzig},
16.291 + title = {Linear Programming and Extensions},
16.292 + publisher = {Princeton University Press},
16.293 + year = 1963
16.294 +}
16.295 +
16.296 +@mastersthesis{kellyoneill91netsimplex,
16.297 + author = {Damian J. Kelly and Garrett M. O'Neill},
16.298 + title = {The Minimum Cost Flow Problem and The Network
16.299 + Simplex Method},
16.300 + school = {University College},
16.301 + address = {Dublin, Ireland},
16.302 + year = 1991,
16.303 + month = sep,
16.304 +}
17.1 --- a/lemon/Makefile.am Tue Dec 20 17:44:38 2011 +0100
17.2 +++ b/lemon/Makefile.am Tue Dec 20 18:15:14 2011 +0100
17.3 @@ -58,19 +58,25 @@
17.4 lemon/adaptors.h \
17.5 lemon/arg_parser.h \
17.6 lemon/assert.h \
17.7 + lemon/bellman_ford.h \
17.8 lemon/bfs.h \
17.9 lemon/bin_heap.h \
17.10 + lemon/binomial_heap.h \
17.11 lemon/bucket_heap.h \
17.12 + lemon/capacity_scaling.h \
17.13 lemon/cbc.h \
17.14 lemon/circulation.h \
17.15 lemon/clp.h \
17.16 lemon/color.h \
17.17 lemon/concept_check.h \
17.18 lemon/connectivity.h \
17.19 + lemon/core.h \
17.20 + lemon/cost_scaling.h \
17.21 lemon/counter.h \
17.22 - lemon/core.h \
17.23 lemon/cplex.h \
17.24 + lemon/cycle_canceling.h \
17.25 lemon/dfs.h \
17.26 + lemon/dheap.h \
17.27 lemon/dijkstra.h \
17.28 lemon/dim2.h \
17.29 lemon/dimacs.h \
17.30 @@ -79,12 +85,16 @@
17.31 lemon/error.h \
17.32 lemon/euler.h \
17.33 lemon/fib_heap.h \
17.34 + lemon/fractional_matching.h \
17.35 lemon/full_graph.h \
17.36 lemon/glpk.h \
17.37 lemon/gomory_hu.h \
17.38 lemon/graph_to_eps.h \
17.39 lemon/grid_graph.h \
17.40 + lemon/hartmann_orlin_mmc.h \
17.41 + lemon/howard_mmc.h \
17.42 lemon/hypercube_graph.h \
17.43 + lemon/karp_mmc.h \
17.44 lemon/kruskal.h \
17.45 lemon/hao_orlin.h \
17.46 lemon/lgf_reader.h \
17.47 @@ -99,13 +109,17 @@
17.48 lemon/min_cost_arborescence.h \
17.49 lemon/nauty_reader.h \
17.50 lemon/network_simplex.h \
17.51 + lemon/pairing_heap.h \
17.52 lemon/path.h \
17.53 + lemon/planarity.h \
17.54 lemon/preflow.h \
17.55 + lemon/quad_heap.h \
17.56 lemon/radix_heap.h \
17.57 lemon/radix_sort.h \
17.58 lemon/random.h \
17.59 lemon/smart_graph.h \
17.60 lemon/soplex.h \
17.61 + lemon/static_graph.h \
17.62 lemon/suurballe.h \
17.63 lemon/time_measure.h \
17.64 lemon/tolerance.h \
18.1 --- a/lemon/adaptors.h Tue Dec 20 17:44:38 2011 +0100
18.2 +++ b/lemon/adaptors.h Tue Dec 20 18:15:14 2011 +0100
18.3 @@ -2,7 +2,7 @@
18.4 *
18.5 * This file is a part of LEMON, a generic C++ optimization library.
18.6 *
18.7 - * Copyright (C) 2003-2009
18.8 + * Copyright (C) 2003-2010
18.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
18.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
18.11 *
18.12 @@ -360,6 +360,9 @@
18.13 /// by adding or removing nodes or arcs, unless the \c GR template
18.14 /// parameter is set to be \c const.
18.15 ///
18.16 + /// This class provides item counting in the same time as the adapted
18.17 + /// digraph structure.
18.18 + ///
18.19 /// \tparam DGR The type of the adapted digraph.
18.20 /// It must conform to the \ref concepts::Digraph "Digraph" concept.
18.21 /// It can also be specified to be \c const.
18.22 @@ -418,7 +421,7 @@
18.23 void initialize(DGR& digraph, NF& node_filter, AF& arc_filter) {
18.24 Parent::initialize(digraph);
18.25 _node_filter = &node_filter;
18.26 - _arc_filter = &arc_filter;
18.27 + _arc_filter = &arc_filter;
18.28 }
18.29
18.30 public:
18.31 @@ -505,11 +508,11 @@
18.32 public:
18.33
18.34 template <typename V>
18.35 - class NodeMap
18.36 - : public SubMapExtender<SubDigraphBase<DGR, NF, AF, ch>,
18.37 - LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, NodeMap<V>)> {
18.38 + class NodeMap
18.39 + : public SubMapExtender<SubDigraphBase<DGR, NF, AF, ch>,
18.40 + LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, NodeMap<V>)> {
18.41 typedef SubMapExtender<SubDigraphBase<DGR, NF, AF, ch>,
18.42 - LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, NodeMap<V>)> Parent;
18.43 + LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, NodeMap<V>)> Parent;
18.44
18.45 public:
18.46 typedef V Value;
18.47 @@ -532,9 +535,9 @@
18.48 };
18.49
18.50 template <typename V>
18.51 - class ArcMap
18.52 + class ArcMap
18.53 : public SubMapExtender<SubDigraphBase<DGR, NF, AF, ch>,
18.54 - LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, ArcMap<V>)> {
18.55 + LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, ArcMap<V>)> {
18.56 typedef SubMapExtender<SubDigraphBase<DGR, NF, AF, ch>,
18.57 LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, ArcMap<V>)> Parent;
18.58
18.59 @@ -579,7 +582,7 @@
18.60 void initialize(DGR& digraph, NF& node_filter, AF& arc_filter) {
18.61 Parent::initialize(digraph);
18.62 _node_filter = &node_filter;
18.63 - _arc_filter = &arc_filter;
18.64 + _arc_filter = &arc_filter;
18.65 }
18.66
18.67 public:
18.68 @@ -648,10 +651,10 @@
18.69 }
18.70
18.71 template <typename V>
18.72 - class NodeMap
18.73 + class NodeMap
18.74 : public SubMapExtender<SubDigraphBase<DGR, NF, AF, false>,
18.75 LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, NodeMap<V>)> {
18.76 - typedef SubMapExtender<SubDigraphBase<DGR, NF, AF, false>,
18.77 + typedef SubMapExtender<SubDigraphBase<DGR, NF, AF, false>,
18.78 LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, NodeMap<V>)> Parent;
18.79
18.80 public:
18.81 @@ -675,7 +678,7 @@
18.82 };
18.83
18.84 template <typename V>
18.85 - class ArcMap
18.86 + class ArcMap
18.87 : public SubMapExtender<SubDigraphBase<DGR, NF, AF, false>,
18.88 LEMON_SCOPE_FIX(DigraphAdaptorBase<DGR>, ArcMap<V>)> {
18.89 typedef SubMapExtender<SubDigraphBase<DGR, NF, AF, false>,
18.90 @@ -719,6 +722,8 @@
18.91 /// by adding or removing nodes or arcs, unless the \c GR template
18.92 /// parameter is set to be \c const.
18.93 ///
18.94 + /// This class provides only linear time counting for nodes and arcs.
18.95 + ///
18.96 /// \tparam DGR The type of the adapted digraph.
18.97 /// It must conform to the \ref concepts::Digraph "Digraph" concept.
18.98 /// It can also be specified to be \c const.
18.99 @@ -1016,10 +1021,10 @@
18.100 }
18.101
18.102 template <typename V>
18.103 - class NodeMap
18.104 + class NodeMap
18.105 : public SubMapExtender<SubGraphBase<GR, NF, EF, ch>,
18.106 LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, NodeMap<V>)> {
18.107 - typedef SubMapExtender<SubGraphBase<GR, NF, EF, ch>,
18.108 + typedef SubMapExtender<SubGraphBase<GR, NF, EF, ch>,
18.109 LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, NodeMap<V>)> Parent;
18.110
18.111 public:
18.112 @@ -1043,10 +1048,10 @@
18.113 };
18.114
18.115 template <typename V>
18.116 - class ArcMap
18.117 + class ArcMap
18.118 : public SubMapExtender<SubGraphBase<GR, NF, EF, ch>,
18.119 LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, ArcMap<V>)> {
18.120 - typedef SubMapExtender<SubGraphBase<GR, NF, EF, ch>,
18.121 + typedef SubMapExtender<SubGraphBase<GR, NF, EF, ch>,
18.122 LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, ArcMap<V>)> Parent;
18.123
18.124 public:
18.125 @@ -1070,10 +1075,10 @@
18.126 };
18.127
18.128 template <typename V>
18.129 - class EdgeMap
18.130 + class EdgeMap
18.131 : public SubMapExtender<SubGraphBase<GR, NF, EF, ch>,
18.132 LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, EdgeMap<V>)> {
18.133 - typedef SubMapExtender<SubGraphBase<GR, NF, EF, ch>,
18.134 + typedef SubMapExtender<SubGraphBase<GR, NF, EF, ch>,
18.135 LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, EdgeMap<V>)> Parent;
18.136
18.137 public:
18.138 @@ -1112,8 +1117,8 @@
18.139 protected:
18.140 NF* _node_filter;
18.141 EF* _edge_filter;
18.142 - SubGraphBase()
18.143 - : Parent(), _node_filter(0), _edge_filter(0) { }
18.144 + SubGraphBase()
18.145 + : Parent(), _node_filter(0), _edge_filter(0) { }
18.146
18.147 void initialize(GR& graph, NF& node_filter, EF& edge_filter) {
18.148 Parent::initialize(graph);
18.149 @@ -1214,10 +1219,10 @@
18.150 }
18.151
18.152 template <typename V>
18.153 - class NodeMap
18.154 + class NodeMap
18.155 : public SubMapExtender<SubGraphBase<GR, NF, EF, false>,
18.156 LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, NodeMap<V>)> {
18.157 - typedef SubMapExtender<SubGraphBase<GR, NF, EF, false>,
18.158 + typedef SubMapExtender<SubGraphBase<GR, NF, EF, false>,
18.159 LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, NodeMap<V>)> Parent;
18.160
18.161 public:
18.162 @@ -1241,10 +1246,10 @@
18.163 };
18.164
18.165 template <typename V>
18.166 - class ArcMap
18.167 + class ArcMap
18.168 : public SubMapExtender<SubGraphBase<GR, NF, EF, false>,
18.169 LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, ArcMap<V>)> {
18.170 - typedef SubMapExtender<SubGraphBase<GR, NF, EF, false>,
18.171 + typedef SubMapExtender<SubGraphBase<GR, NF, EF, false>,
18.172 LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, ArcMap<V>)> Parent;
18.173
18.174 public:
18.175 @@ -1268,11 +1273,11 @@
18.176 };
18.177
18.178 template <typename V>
18.179 - class EdgeMap
18.180 + class EdgeMap
18.181 : public SubMapExtender<SubGraphBase<GR, NF, EF, false>,
18.182 LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, EdgeMap<V>)> {
18.183 - typedef SubMapExtender<SubGraphBase<GR, NF, EF, false>,
18.184 - LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, EdgeMap<V>)> Parent;
18.185 + typedef SubMapExtender<SubGraphBase<GR, NF, EF, false>,
18.186 + LEMON_SCOPE_FIX(GraphAdaptorBase<GR>, EdgeMap<V>)> Parent;
18.187
18.188 public:
18.189 typedef V Value;
18.190 @@ -1314,6 +1319,8 @@
18.191 /// by adding or removing nodes or edges, unless the \c GR template
18.192 /// parameter is set to be \c const.
18.193 ///
18.194 + /// This class provides only linear time counting for nodes, edges and arcs.
18.195 + ///
18.196 /// \tparam GR The type of the adapted graph.
18.197 /// It must conform to the \ref concepts::Graph "Graph" concept.
18.198 /// It can also be specified to be \c const.
18.199 @@ -1471,6 +1478,8 @@
18.200 /// by adding or removing nodes or arcs/edges, unless the \c GR template
18.201 /// parameter is set to be \c const.
18.202 ///
18.203 + /// This class provides only linear time item counting.
18.204 + ///
18.205 /// \tparam GR The type of the adapted digraph or graph.
18.206 /// It must conform to the \ref concepts::Digraph "Digraph" concept
18.207 /// or the \ref concepts::Graph "Graph" concept.
18.208 @@ -1495,7 +1504,7 @@
18.209 true> > {
18.210 #endif
18.211 typedef DigraphAdaptorExtender<
18.212 - SubDigraphBase<GR, NF, ConstMap<typename GR::Arc, Const<bool, true> >,
18.213 + SubDigraphBase<GR, NF, ConstMap<typename GR::Arc, Const<bool, true> >,
18.214 true> > Parent;
18.215
18.216 public:
18.217 @@ -1516,7 +1525,7 @@
18.218 ///
18.219 /// Creates a subgraph for the given digraph or graph with the
18.220 /// given node filter map.
18.221 - FilterNodes(GR& graph, NF& node_filter)
18.222 + FilterNodes(GR& graph, NF& node_filter)
18.223 : Parent(), const_true_map()
18.224 {
18.225 Parent::initialize(graph, node_filter, const_true_map);
18.226 @@ -1554,11 +1563,11 @@
18.227 class FilterNodes<GR, NF,
18.228 typename enable_if<UndirectedTagIndicator<GR> >::type> :
18.229 public GraphAdaptorExtender<
18.230 - SubGraphBase<GR, NF, ConstMap<typename GR::Edge, Const<bool, true> >,
18.231 + SubGraphBase<GR, NF, ConstMap<typename GR::Edge, Const<bool, true> >,
18.232 true> > {
18.233
18.234 typedef GraphAdaptorExtender<
18.235 - SubGraphBase<GR, NF, ConstMap<typename GR::Edge, Const<bool, true> >,
18.236 + SubGraphBase<GR, NF, ConstMap<typename GR::Edge, Const<bool, true> >,
18.237 true> > Parent;
18.238
18.239 public:
18.240 @@ -1619,6 +1628,8 @@
18.241 /// by adding or removing nodes or arcs, unless the \c GR template
18.242 /// parameter is set to be \c const.
18.243 ///
18.244 + /// This class provides only linear time counting for nodes and arcs.
18.245 + ///
18.246 /// \tparam DGR The type of the adapted digraph.
18.247 /// It must conform to the \ref concepts::Digraph "Digraph" concept.
18.248 /// It can also be specified to be \c const.
18.249 @@ -1642,7 +1653,7 @@
18.250 AF, false> > {
18.251 #endif
18.252 typedef DigraphAdaptorExtender<
18.253 - SubDigraphBase<DGR, ConstMap<typename DGR::Node, Const<bool, true> >,
18.254 + SubDigraphBase<DGR, ConstMap<typename DGR::Node, Const<bool, true> >,
18.255 AF, false> > Parent;
18.256
18.257 public:
18.258 @@ -1729,6 +1740,8 @@
18.259 /// by adding or removing nodes or edges, unless the \c GR template
18.260 /// parameter is set to be \c const.
18.261 ///
18.262 + /// This class provides only linear time counting for nodes, edges and arcs.
18.263 + ///
18.264 /// \tparam GR The type of the adapted graph.
18.265 /// It must conform to the \ref concepts::Graph "Graph" concept.
18.266 /// It can also be specified to be \c const.
18.267 @@ -1748,11 +1761,11 @@
18.268 typename EF = typename GR::template EdgeMap<bool> >
18.269 class FilterEdges :
18.270 public GraphAdaptorExtender<
18.271 - SubGraphBase<GR, ConstMap<typename GR::Node, Const<bool, true> >,
18.272 + SubGraphBase<GR, ConstMap<typename GR::Node, Const<bool, true> >,
18.273 EF, false> > {
18.274 #endif
18.275 typedef GraphAdaptorExtender<
18.276 - SubGraphBase<GR, ConstMap<typename GR::Node, Const<bool, true > >,
18.277 + SubGraphBase<GR, ConstMap<typename GR::Node, Const<bool, true > >,
18.278 EF, false> > Parent;
18.279
18.280 public:
18.281 @@ -1777,7 +1790,7 @@
18.282 ///
18.283 /// Creates a subgraph for the given graph with the given edge
18.284 /// filter map.
18.285 - FilterEdges(GR& graph, EF& edge_filter)
18.286 + FilterEdges(GR& graph, EF& edge_filter)
18.287 : Parent(), const_true_map() {
18.288 Parent::initialize(graph, const_true_map, edge_filter);
18.289 }
18.290 @@ -1845,7 +1858,7 @@
18.291 Edge _edge;
18.292 bool _forward;
18.293
18.294 - Arc(const Edge& edge, bool forward)
18.295 + Arc(const Edge& edge, bool forward)
18.296 : _edge(edge), _forward(forward) {}
18.297
18.298 public:
18.299 @@ -2085,7 +2098,7 @@
18.300 _forward(*adaptor._digraph), _backward(*adaptor._digraph) {}
18.301
18.302 ArcMapBase(const UndirectorBase<DGR>& adaptor, const V& value)
18.303 - : _forward(*adaptor._digraph, value),
18.304 + : _forward(*adaptor._digraph, value),
18.305 _backward(*adaptor._digraph, value) {}
18.306
18.307 void set(const Arc& a, const V& value) {
18.308 @@ -2203,7 +2216,7 @@
18.309
18.310 typedef typename ItemSetTraits<DGR, Edge>::ItemNotifier EdgeNotifier;
18.311 EdgeNotifier& notifier(Edge) const { return _digraph->notifier(Edge()); }
18.312 -
18.313 +
18.314 typedef EdgeNotifier ArcNotifier;
18.315 ArcNotifier& notifier(Arc) const { return _digraph->notifier(Edge()); }
18.316
18.317 @@ -2232,6 +2245,9 @@
18.318 /// by adding or removing nodes or edges, unless the \c GR template
18.319 /// parameter is set to be \c const.
18.320 ///
18.321 + /// This class provides item counting in the same time as the adapted
18.322 + /// digraph structure.
18.323 + ///
18.324 /// \tparam DGR The type of the adapted digraph.
18.325 /// It must conform to the \ref concepts::Digraph "Digraph" concept.
18.326 /// It can also be specified to be \c const.
18.327 @@ -2535,6 +2551,9 @@
18.328 /// by adding or removing nodes or arcs, unless the \c GR template
18.329 /// parameter is set to be \c const.
18.330 ///
18.331 + /// This class provides item counting in the same time as the adapted
18.332 + /// graph structure.
18.333 + ///
18.334 /// \tparam GR The type of the adapted graph.
18.335 /// It must conform to the \ref concepts::Graph "Graph" concept.
18.336 /// It can also be specified to be \c const.
18.337 @@ -2678,6 +2697,8 @@
18.338 /// arcs).
18.339 /// This class conforms to the \ref concepts::Digraph "Digraph" concept.
18.340 ///
18.341 + /// This class provides only linear time counting for nodes and arcs.
18.342 + ///
18.343 /// \tparam DGR The type of the adapted digraph.
18.344 /// It must conform to the \ref concepts::Digraph "Digraph" concept.
18.345 /// It is implicitly \c const.
18.346 @@ -2707,7 +2728,7 @@
18.347 typename CM = typename DGR::template ArcMap<int>,
18.348 typename FM = CM,
18.349 typename TL = Tolerance<typename CM::Value> >
18.350 - class ResidualDigraph
18.351 + class ResidualDigraph
18.352 : public SubDigraph<
18.353 Undirector<const DGR>,
18.354 ConstMap<typename DGR::Node, Const<bool, true> >,
18.355 @@ -2764,7 +2785,7 @@
18.356 /// digraph, the capacity map, the flow map, and a tolerance object.
18.357 ResidualDigraph(const DGR& digraph, const CM& capacity,
18.358 FM& flow, const TL& tolerance = Tolerance())
18.359 - : Parent(), _capacity(&capacity), _flow(&flow),
18.360 + : Parent(), _capacity(&capacity), _flow(&flow),
18.361 _graph(digraph), _node_filter(),
18.362 _forward_filter(capacity, flow, tolerance),
18.363 _backward_filter(capacity, flow, tolerance),
18.364 @@ -2846,7 +2867,7 @@
18.365 typedef typename CapacityMap::Value Value;
18.366
18.367 /// Constructor
18.368 - ResidualCapacity(const ResidualDigraph<DGR, CM, FM, TL>& adaptor)
18.369 + ResidualCapacity(const ResidualDigraph<DGR, CM, FM, TL>& adaptor)
18.370 : _adaptor(&adaptor) {}
18.371
18.372 /// Returns the value associated with the given residual arc
18.373 @@ -3325,6 +3346,9 @@
18.374 /// costs/capacities of the original digraph to the \e bind \e arcs
18.375 /// in the adaptor.
18.376 ///
18.377 + /// This class provides item counting in the same time as the adapted
18.378 + /// digraph structure.
18.379 + ///
18.380 /// \tparam DGR The type of the adapted digraph.
18.381 /// It must conform to the \ref concepts::Digraph "Digraph" concept.
18.382 /// It is implicitly \c const.
18.383 @@ -3423,7 +3447,7 @@
18.384 /// This map adaptor class adapts two node maps of the original digraph
18.385 /// to get a node map of the split digraph.
18.386 /// Its value type is inherited from the first node map type (\c IN).
18.387 - /// \tparam IN The type of the node map for the in-nodes.
18.388 + /// \tparam IN The type of the node map for the in-nodes.
18.389 /// \tparam OUT The type of the node map for the out-nodes.
18.390 template <typename IN, typename OUT>
18.391 class CombinedNodeMap {
19.1 --- a/lemon/arg_parser.cc Tue Dec 20 17:44:38 2011 +0100
19.2 +++ b/lemon/arg_parser.cc Tue Dec 20 18:15:14 2011 +0100
19.3 @@ -2,7 +2,7 @@
19.4 *
19.5 * This file is a part of LEMON, a generic C++ optimization library.
19.6 *
19.7 - * Copyright (C) 2003-2009
19.8 + * Copyright (C) 2003-2010
19.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
19.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
19.11 *
19.12 @@ -20,14 +20,23 @@
19.13
19.14 namespace lemon {
19.15
19.16 + void ArgParser::_terminate(ArgParserException::Reason reason) const
19.17 + {
19.18 + if(_exit_on_problems)
19.19 + exit(1);
19.20 + else throw(ArgParserException(reason));
19.21 + }
19.22 +
19.23 +
19.24 void ArgParser::_showHelp(void *p)
19.25 {
19.26 (static_cast<ArgParser*>(p))->showHelp();
19.27 - exit(1);
19.28 + (static_cast<ArgParser*>(p))->_terminate(ArgParserException::HELP);
19.29 }
19.30
19.31 ArgParser::ArgParser(int argc, const char * const *argv)
19.32 - :_argc(argc), _argv(argv), _command_name(argv[0]) {
19.33 + :_argc(argc), _argv(argv), _command_name(argv[0]),
19.34 + _exit_on_problems(true) {
19.35 funcOption("-help","Print a short help message",_showHelp,this);
19.36 synonym("help","-help");
19.37 synonym("h","-help");
19.38 @@ -342,7 +351,7 @@
19.39 for(std::vector<OtherArg>::const_iterator i=_others_help.begin();
19.40 i!=_others_help.end();++i) showHelp(i);
19.41 for(Opts::const_iterator i=_opts.begin();i!=_opts.end();++i) showHelp(i);
19.42 - exit(1);
19.43 + _terminate(ArgParserException::HELP);
19.44 }
19.45
19.46
19.47 @@ -351,7 +360,7 @@
19.48 std::cerr << "\nUnknown option: " << arg << "\n";
19.49 std::cerr << "\nType '" << _command_name <<
19.50 " --help' to obtain a short summary on the usage.\n\n";
19.51 - exit(1);
19.52 + _terminate(ArgParserException::UNKNOWN_OPT);
19.53 }
19.54
19.55 void ArgParser::requiresValue(std::string arg, OptType t) const
19.56 @@ -414,7 +423,7 @@
19.57 if(!ok) {
19.58 std::cerr << "\nType '" << _command_name <<
19.59 " --help' to obtain a short summary on the usage.\n\n";
19.60 - exit(1);
19.61 + _terminate(ArgParserException::INVALID_OPT);
19.62 }
19.63 }
19.64
20.1 --- a/lemon/arg_parser.h Tue Dec 20 17:44:38 2011 +0100
20.2 +++ b/lemon/arg_parser.h Tue Dec 20 18:15:14 2011 +0100
20.3 @@ -2,7 +2,7 @@
20.4 *
20.5 * This file is a part of LEMON, a generic C++ optimization library.
20.6 *
20.7 - * Copyright (C) 2003-2009
20.8 + * Copyright (C) 2003-2010
20.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
20.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
20.11 *
20.12 @@ -34,6 +34,44 @@
20.13
20.14 namespace lemon {
20.15
20.16 + ///Exception used by ArgParser
20.17 + class ArgParserException : public Exception {
20.18 + public:
20.19 + enum Reason {
20.20 + HELP, /// <tt>--help</tt> option was given
20.21 + UNKNOWN_OPT, /// Unknown option was given
20.22 + INVALID_OPT /// Invalid combination of options
20.23 + };
20.24 +
20.25 + private:
20.26 + Reason _reason;
20.27 +
20.28 + public:
20.29 + ///Constructor
20.30 + ArgParserException(Reason r) throw() : _reason(r) {}
20.31 + ///Virtual destructor
20.32 + virtual ~ArgParserException() throw() {}
20.33 + ///A short description of the exception
20.34 + virtual const char* what() const throw() {
20.35 + switch(_reason)
20.36 + {
20.37 + case HELP:
20.38 + return "lemon::ArgParseException: ask for help";
20.39 + break;
20.40 + case UNKNOWN_OPT:
20.41 + return "lemon::ArgParseException: unknown option";
20.42 + break;
20.43 + case INVALID_OPT:
20.44 + return "lemon::ArgParseException: invalid combination of options";
20.45 + break;
20.46 + }
20.47 + return "";
20.48 + }
20.49 + ///Return the reason for the failure
20.50 + Reason reason() const {return _reason; }
20.51 + };
20.52 +
20.53 +
20.54 ///Command line arguments parser
20.55
20.56 ///\ingroup misc
20.57 @@ -116,6 +154,10 @@
20.58 const std::string &help,
20.59 void (*func)(void *),void *data);
20.60
20.61 + bool _exit_on_problems;
20.62 +
20.63 + void _terminate(ArgParserException::Reason reason) const;
20.64 +
20.65 public:
20.66
20.67 ///Constructor
20.68 @@ -380,6 +422,11 @@
20.69 ///not starting with a '-' character.
20.70 const std::vector<std::string> &files() const { return _file_args; }
20.71
20.72 + ///Throw instead of exit in case of problems
20.73 + void throwOnProblems()
20.74 + {
20.75 + _exit_on_problems=false;
20.76 + }
20.77 };
20.78 }
20.79
21.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
21.2 +++ b/lemon/bellman_ford.h Tue Dec 20 18:15:14 2011 +0100
21.3 @@ -0,0 +1,1165 @@
21.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
21.5 + *
21.6 + * This file is a part of LEMON, a generic C++ optimization library.
21.7 + *
21.8 + * Copyright (C) 2003-2010
21.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
21.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
21.11 + *
21.12 + * Permission to use, modify and distribute this software is granted
21.13 + * provided that this copyright notice appears in all copies. For
21.14 + * precise terms see the accompanying LICENSE file.
21.15 + *
21.16 + * This software is provided "AS IS" with no warranty of any kind,
21.17 + * express or implied, and with no claim as to its suitability for any
21.18 + * purpose.
21.19 + *
21.20 + */
21.21 +
21.22 +#ifndef LEMON_BELLMAN_FORD_H
21.23 +#define LEMON_BELLMAN_FORD_H
21.24 +
21.25 +/// \ingroup shortest_path
21.26 +/// \file
21.27 +/// \brief Bellman-Ford algorithm.
21.28 +
21.29 +#include <lemon/list_graph.h>
21.30 +#include <lemon/bits/path_dump.h>
21.31 +#include <lemon/core.h>
21.32 +#include <lemon/error.h>
21.33 +#include <lemon/maps.h>
21.34 +#include <lemon/tolerance.h>
21.35 +#include <lemon/path.h>
21.36 +
21.37 +#include <limits>
21.38 +
21.39 +namespace lemon {
21.40 +
21.41 + /// \brief Default operation traits for the BellmanFord algorithm class.
21.42 + ///
21.43 + /// This operation traits class defines all computational operations
21.44 + /// and constants that are used in the Bellman-Ford algorithm.
21.45 + /// The default implementation is based on the \c numeric_limits class.
21.46 + /// If the numeric type does not have infinity value, then the maximum
21.47 + /// value is used as extremal infinity value.
21.48 + ///
21.49 + /// \see BellmanFordToleranceOperationTraits
21.50 + template <
21.51 + typename V,
21.52 + bool has_inf = std::numeric_limits<V>::has_infinity>
21.53 + struct BellmanFordDefaultOperationTraits {
21.54 + /// \brief Value type for the algorithm.
21.55 + typedef V Value;
21.56 + /// \brief Gives back the zero value of the type.
21.57 + static Value zero() {
21.58 + return static_cast<Value>(0);
21.59 + }
21.60 + /// \brief Gives back the positive infinity value of the type.
21.61 + static Value infinity() {
21.62 + return std::numeric_limits<Value>::infinity();
21.63 + }
21.64 + /// \brief Gives back the sum of the given two elements.
21.65 + static Value plus(const Value& left, const Value& right) {
21.66 + return left + right;
21.67 + }
21.68 + /// \brief Gives back \c true only if the first value is less than
21.69 + /// the second.
21.70 + static bool less(const Value& left, const Value& right) {
21.71 + return left < right;
21.72 + }
21.73 + };
21.74 +
21.75 + template <typename V>
21.76 + struct BellmanFordDefaultOperationTraits<V, false> {
21.77 + typedef V Value;
21.78 + static Value zero() {
21.79 + return static_cast<Value>(0);
21.80 + }
21.81 + static Value infinity() {
21.82 + return std::numeric_limits<Value>::max();
21.83 + }
21.84 + static Value plus(const Value& left, const Value& right) {
21.85 + if (left == infinity() || right == infinity()) return infinity();
21.86 + return left + right;
21.87 + }
21.88 + static bool less(const Value& left, const Value& right) {
21.89 + return left < right;
21.90 + }
21.91 + };
21.92 +
21.93 + /// \brief Operation traits for the BellmanFord algorithm class
21.94 + /// using tolerance.
21.95 + ///
21.96 + /// This operation traits class defines all computational operations
21.97 + /// and constants that are used in the Bellman-Ford algorithm.
21.98 + /// The only difference between this implementation and
21.99 + /// \ref BellmanFordDefaultOperationTraits is that this class uses
21.100 + /// the \ref Tolerance "tolerance technique" in its \ref less()
21.101 + /// function.
21.102 + ///
21.103 + /// \tparam V The value type.
21.104 + /// \tparam eps The epsilon value for the \ref less() function.
21.105 + /// By default, it is the epsilon value used by \ref Tolerance
21.106 + /// "Tolerance<V>".
21.107 + ///
21.108 + /// \see BellmanFordDefaultOperationTraits
21.109 +#ifdef DOXYGEN
21.110 + template <typename V, V eps>
21.111 +#else
21.112 + template <
21.113 + typename V,
21.114 + V eps = Tolerance<V>::def_epsilon>
21.115 +#endif
21.116 + struct BellmanFordToleranceOperationTraits {
21.117 + /// \brief Value type for the algorithm.
21.118 + typedef V Value;
21.119 + /// \brief Gives back the zero value of the type.
21.120 + static Value zero() {
21.121 + return static_cast<Value>(0);
21.122 + }
21.123 + /// \brief Gives back the positive infinity value of the type.
21.124 + static Value infinity() {
21.125 + return std::numeric_limits<Value>::infinity();
21.126 + }
21.127 + /// \brief Gives back the sum of the given two elements.
21.128 + static Value plus(const Value& left, const Value& right) {
21.129 + return left + right;
21.130 + }
21.131 + /// \brief Gives back \c true only if the first value is less than
21.132 + /// the second.
21.133 + static bool less(const Value& left, const Value& right) {
21.134 + return left + eps < right;
21.135 + }
21.136 + };
21.137 +
21.138 + /// \brief Default traits class of BellmanFord class.
21.139 + ///
21.140 + /// Default traits class of BellmanFord class.
21.141 + /// \param GR The type of the digraph.
21.142 + /// \param LEN The type of the length map.
21.143 + template<typename GR, typename LEN>
21.144 + struct BellmanFordDefaultTraits {
21.145 + /// The type of the digraph the algorithm runs on.
21.146 + typedef GR Digraph;
21.147 +
21.148 + /// \brief The type of the map that stores the arc lengths.
21.149 + ///
21.150 + /// The type of the map that stores the arc lengths.
21.151 + /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
21.152 + typedef LEN LengthMap;
21.153 +
21.154 + /// The type of the arc lengths.
21.155 + typedef typename LEN::Value Value;
21.156 +
21.157 + /// \brief Operation traits for Bellman-Ford algorithm.
21.158 + ///
21.159 + /// It defines the used operations and the infinity value for the
21.160 + /// given \c Value type.
21.161 + /// \see BellmanFordDefaultOperationTraits,
21.162 + /// BellmanFordToleranceOperationTraits
21.163 + typedef BellmanFordDefaultOperationTraits<Value> OperationTraits;
21.164 +
21.165 + /// \brief The type of the map that stores the last arcs of the
21.166 + /// shortest paths.
21.167 + ///
21.168 + /// The type of the map that stores the last
21.169 + /// arcs of the shortest paths.
21.170 + /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
21.171 + typedef typename GR::template NodeMap<typename GR::Arc> PredMap;
21.172 +
21.173 + /// \brief Instantiates a \c PredMap.
21.174 + ///
21.175 + /// This function instantiates a \ref PredMap.
21.176 + /// \param g is the digraph to which we would like to define the
21.177 + /// \ref PredMap.
21.178 + static PredMap *createPredMap(const GR& g) {
21.179 + return new PredMap(g);
21.180 + }
21.181 +
21.182 + /// \brief The type of the map that stores the distances of the nodes.
21.183 + ///
21.184 + /// The type of the map that stores the distances of the nodes.
21.185 + /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
21.186 + typedef typename GR::template NodeMap<typename LEN::Value> DistMap;
21.187 +
21.188 + /// \brief Instantiates a \c DistMap.
21.189 + ///
21.190 + /// This function instantiates a \ref DistMap.
21.191 + /// \param g is the digraph to which we would like to define the
21.192 + /// \ref DistMap.
21.193 + static DistMap *createDistMap(const GR& g) {
21.194 + return new DistMap(g);
21.195 + }
21.196 +
21.197 + };
21.198 +
21.199 + /// \brief %BellmanFord algorithm class.
21.200 + ///
21.201 + /// \ingroup shortest_path
21.202 + /// This class provides an efficient implementation of the Bellman-Ford
21.203 + /// algorithm. The maximum time complexity of the algorithm is
21.204 + /// <tt>O(ne)</tt>.
21.205 + ///
21.206 + /// The Bellman-Ford algorithm solves the single-source shortest path
21.207 + /// problem when the arcs can have negative lengths, but the digraph
21.208 + /// should not contain directed cycles with negative total length.
21.209 + /// If all arc costs are non-negative, consider to use the Dijkstra
21.210 + /// algorithm instead, since it is more efficient.
21.211 + ///
21.212 + /// The arc lengths are passed to the algorithm using a
21.213 + /// \ref concepts::ReadMap "ReadMap", so it is easy to change it to any
21.214 + /// kind of length. The type of the length values is determined by the
21.215 + /// \ref concepts::ReadMap::Value "Value" type of the length map.
21.216 + ///
21.217 + /// There is also a \ref bellmanFord() "function-type interface" for the
21.218 + /// Bellman-Ford algorithm, which is convenient in the simplier cases and
21.219 + /// it can be used easier.
21.220 + ///
21.221 + /// \tparam GR The type of the digraph the algorithm runs on.
21.222 + /// The default type is \ref ListDigraph.
21.223 + /// \tparam LEN A \ref concepts::ReadMap "readable" arc map that specifies
21.224 + /// the lengths of the arcs. The default map type is
21.225 + /// \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
21.226 + /// \tparam TR The traits class that defines various types used by the
21.227 + /// algorithm. By default, it is \ref BellmanFordDefaultTraits
21.228 + /// "BellmanFordDefaultTraits<GR, LEN>".
21.229 + /// In most cases, this parameter should not be set directly,
21.230 + /// consider to use the named template parameters instead.
21.231 +#ifdef DOXYGEN
21.232 + template <typename GR, typename LEN, typename TR>
21.233 +#else
21.234 + template <typename GR=ListDigraph,
21.235 + typename LEN=typename GR::template ArcMap<int>,
21.236 + typename TR=BellmanFordDefaultTraits<GR,LEN> >
21.237 +#endif
21.238 + class BellmanFord {
21.239 + public:
21.240 +
21.241 + ///The type of the underlying digraph.
21.242 + typedef typename TR::Digraph Digraph;
21.243 +
21.244 + /// \brief The type of the arc lengths.
21.245 + typedef typename TR::LengthMap::Value Value;
21.246 + /// \brief The type of the map that stores the arc lengths.
21.247 + typedef typename TR::LengthMap LengthMap;
21.248 + /// \brief The type of the map that stores the last
21.249 + /// arcs of the shortest paths.
21.250 + typedef typename TR::PredMap PredMap;
21.251 + /// \brief The type of the map that stores the distances of the nodes.
21.252 + typedef typename TR::DistMap DistMap;
21.253 + /// The type of the paths.
21.254 + typedef PredMapPath<Digraph, PredMap> Path;
21.255 + ///\brief The \ref BellmanFordDefaultOperationTraits
21.256 + /// "operation traits class" of the algorithm.
21.257 + typedef typename TR::OperationTraits OperationTraits;
21.258 +
21.259 + ///The \ref BellmanFordDefaultTraits "traits class" of the algorithm.
21.260 + typedef TR Traits;
21.261 +
21.262 + private:
21.263 +
21.264 + typedef typename Digraph::Node Node;
21.265 + typedef typename Digraph::NodeIt NodeIt;
21.266 + typedef typename Digraph::Arc Arc;
21.267 + typedef typename Digraph::OutArcIt OutArcIt;
21.268 +
21.269 + // Pointer to the underlying digraph.
21.270 + const Digraph *_gr;
21.271 + // Pointer to the length map
21.272 + const LengthMap *_length;
21.273 + // Pointer to the map of predecessors arcs.
21.274 + PredMap *_pred;
21.275 + // Indicates if _pred is locally allocated (true) or not.
21.276 + bool _local_pred;
21.277 + // Pointer to the map of distances.
21.278 + DistMap *_dist;
21.279 + // Indicates if _dist is locally allocated (true) or not.
21.280 + bool _local_dist;
21.281 +
21.282 + typedef typename Digraph::template NodeMap<bool> MaskMap;
21.283 + MaskMap *_mask;
21.284 +
21.285 + std::vector<Node> _process;
21.286 +
21.287 + // Creates the maps if necessary.
21.288 + void create_maps() {
21.289 + if(!_pred) {
21.290 + _local_pred = true;
21.291 + _pred = Traits::createPredMap(*_gr);
21.292 + }
21.293 + if(!_dist) {
21.294 + _local_dist = true;
21.295 + _dist = Traits::createDistMap(*_gr);
21.296 + }
21.297 + if(!_mask) {
21.298 + _mask = new MaskMap(*_gr);
21.299 + }
21.300 + }
21.301 +
21.302 + public :
21.303 +
21.304 + typedef BellmanFord Create;
21.305 +
21.306 + /// \name Named Template Parameters
21.307 +
21.308 + ///@{
21.309 +
21.310 + template <class T>
21.311 + struct SetPredMapTraits : public Traits {
21.312 + typedef T PredMap;
21.313 + static PredMap *createPredMap(const Digraph&) {
21.314 + LEMON_ASSERT(false, "PredMap is not initialized");
21.315 + return 0; // ignore warnings
21.316 + }
21.317 + };
21.318 +
21.319 + /// \brief \ref named-templ-param "Named parameter" for setting
21.320 + /// \c PredMap type.
21.321 + ///
21.322 + /// \ref named-templ-param "Named parameter" for setting
21.323 + /// \c PredMap type.
21.324 + /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
21.325 + template <class T>
21.326 + struct SetPredMap
21.327 + : public BellmanFord< Digraph, LengthMap, SetPredMapTraits<T> > {
21.328 + typedef BellmanFord< Digraph, LengthMap, SetPredMapTraits<T> > Create;
21.329 + };
21.330 +
21.331 + template <class T>
21.332 + struct SetDistMapTraits : public Traits {
21.333 + typedef T DistMap;
21.334 + static DistMap *createDistMap(const Digraph&) {
21.335 + LEMON_ASSERT(false, "DistMap is not initialized");
21.336 + return 0; // ignore warnings
21.337 + }
21.338 + };
21.339 +
21.340 + /// \brief \ref named-templ-param "Named parameter" for setting
21.341 + /// \c DistMap type.
21.342 + ///
21.343 + /// \ref named-templ-param "Named parameter" for setting
21.344 + /// \c DistMap type.
21.345 + /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
21.346 + template <class T>
21.347 + struct SetDistMap
21.348 + : public BellmanFord< Digraph, LengthMap, SetDistMapTraits<T> > {
21.349 + typedef BellmanFord< Digraph, LengthMap, SetDistMapTraits<T> > Create;
21.350 + };
21.351 +
21.352 + template <class T>
21.353 + struct SetOperationTraitsTraits : public Traits {
21.354 + typedef T OperationTraits;
21.355 + };
21.356 +
21.357 + /// \brief \ref named-templ-param "Named parameter" for setting
21.358 + /// \c OperationTraits type.
21.359 + ///
21.360 + /// \ref named-templ-param "Named parameter" for setting
21.361 + /// \c OperationTraits type.
21.362 + /// For more information, see \ref BellmanFordDefaultOperationTraits.
21.363 + template <class T>
21.364 + struct SetOperationTraits
21.365 + : public BellmanFord< Digraph, LengthMap, SetOperationTraitsTraits<T> > {
21.366 + typedef BellmanFord< Digraph, LengthMap, SetOperationTraitsTraits<T> >
21.367 + Create;
21.368 + };
21.369 +
21.370 + ///@}
21.371 +
21.372 + protected:
21.373 +
21.374 + BellmanFord() {}
21.375 +
21.376 + public:
21.377 +
21.378 + /// \brief Constructor.
21.379 + ///
21.380 + /// Constructor.
21.381 + /// \param g The digraph the algorithm runs on.
21.382 + /// \param length The length map used by the algorithm.
21.383 + BellmanFord(const Digraph& g, const LengthMap& length) :
21.384 + _gr(&g), _length(&length),
21.385 + _pred(0), _local_pred(false),
21.386 + _dist(0), _local_dist(false), _mask(0) {}
21.387 +
21.388 + ///Destructor.
21.389 + ~BellmanFord() {
21.390 + if(_local_pred) delete _pred;
21.391 + if(_local_dist) delete _dist;
21.392 + if(_mask) delete _mask;
21.393 + }
21.394 +
21.395 + /// \brief Sets the length map.
21.396 + ///
21.397 + /// Sets the length map.
21.398 + /// \return <tt>(*this)</tt>
21.399 + BellmanFord &lengthMap(const LengthMap &map) {
21.400 + _length = ↦
21.401 + return *this;
21.402 + }
21.403 +
21.404 + /// \brief Sets the map that stores the predecessor arcs.
21.405 + ///
21.406 + /// Sets the map that stores the predecessor arcs.
21.407 + /// If you don't use this function before calling \ref run()
21.408 + /// or \ref init(), an instance will be allocated automatically.
21.409 + /// The destructor deallocates this automatically allocated map,
21.410 + /// of course.
21.411 + /// \return <tt>(*this)</tt>
21.412 + BellmanFord &predMap(PredMap &map) {
21.413 + if(_local_pred) {
21.414 + delete _pred;
21.415 + _local_pred=false;
21.416 + }
21.417 + _pred = ↦
21.418 + return *this;
21.419 + }
21.420 +
21.421 + /// \brief Sets the map that stores the distances of the nodes.
21.422 + ///
21.423 + /// Sets the map that stores the distances of the nodes calculated
21.424 + /// by the algorithm.
21.425 + /// If you don't use this function before calling \ref run()
21.426 + /// or \ref init(), an instance will be allocated automatically.
21.427 + /// The destructor deallocates this automatically allocated map,
21.428 + /// of course.
21.429 + /// \return <tt>(*this)</tt>
21.430 + BellmanFord &distMap(DistMap &map) {
21.431 + if(_local_dist) {
21.432 + delete _dist;
21.433 + _local_dist=false;
21.434 + }
21.435 + _dist = ↦
21.436 + return *this;
21.437 + }
21.438 +
21.439 + /// \name Execution Control
21.440 + /// The simplest way to execute the Bellman-Ford algorithm is to use
21.441 + /// one of the member functions called \ref run().\n
21.442 + /// If you need better control on the execution, you have to call
21.443 + /// \ref init() first, then you can add several source nodes
21.444 + /// with \ref addSource(). Finally the actual path computation can be
21.445 + /// performed with \ref start(), \ref checkedStart() or
21.446 + /// \ref limitedStart().
21.447 +
21.448 + ///@{
21.449 +
21.450 + /// \brief Initializes the internal data structures.
21.451 + ///
21.452 + /// Initializes the internal data structures. The optional parameter
21.453 + /// is the initial distance of each node.
21.454 + void init(const Value value = OperationTraits::infinity()) {
21.455 + create_maps();
21.456 + for (NodeIt it(*_gr); it != INVALID; ++it) {
21.457 + _pred->set(it, INVALID);
21.458 + _dist->set(it, value);
21.459 + }
21.460 + _process.clear();
21.461 + if (OperationTraits::less(value, OperationTraits::infinity())) {
21.462 + for (NodeIt it(*_gr); it != INVALID; ++it) {
21.463 + _process.push_back(it);
21.464 + _mask->set(it, true);
21.465 + }
21.466 + } else {
21.467 + for (NodeIt it(*_gr); it != INVALID; ++it) {
21.468 + _mask->set(it, false);
21.469 + }
21.470 + }
21.471 + }
21.472 +
21.473 + /// \brief Adds a new source node.
21.474 + ///
21.475 + /// This function adds a new source node. The optional second parameter
21.476 + /// is the initial distance of the node.
21.477 + void addSource(Node source, Value dst = OperationTraits::zero()) {
21.478 + _dist->set(source, dst);
21.479 + if (!(*_mask)[source]) {
21.480 + _process.push_back(source);
21.481 + _mask->set(source, true);
21.482 + }
21.483 + }
21.484 +
21.485 + /// \brief Executes one round from the Bellman-Ford algorithm.
21.486 + ///
21.487 + /// If the algoritm calculated the distances in the previous round
21.488 + /// exactly for the paths of at most \c k arcs, then this function
21.489 + /// will calculate the distances exactly for the paths of at most
21.490 + /// <tt>k+1</tt> arcs. Performing \c k iterations using this function
21.491 + /// calculates the shortest path distances exactly for the paths
21.492 + /// consisting of at most \c k arcs.
21.493 + ///
21.494 + /// \warning The paths with limited arc number cannot be retrieved
21.495 + /// easily with \ref path() or \ref predArc() functions. If you also
21.496 + /// need the shortest paths and not only the distances, you should
21.497 + /// store the \ref predMap() "predecessor map" after each iteration
21.498 + /// and build the path manually.
21.499 + ///
21.500 + /// \return \c true when the algorithm have not found more shorter
21.501 + /// paths.
21.502 + ///
21.503 + /// \see ActiveIt
21.504 + bool processNextRound() {
21.505 + for (int i = 0; i < int(_process.size()); ++i) {
21.506 + _mask->set(_process[i], false);
21.507 + }
21.508 + std::vector<Node> nextProcess;
21.509 + std::vector<Value> values(_process.size());
21.510 + for (int i = 0; i < int(_process.size()); ++i) {
21.511 + values[i] = (*_dist)[_process[i]];
21.512 + }
21.513 + for (int i = 0; i < int(_process.size()); ++i) {
21.514 + for (OutArcIt it(*_gr, _process[i]); it != INVALID; ++it) {
21.515 + Node target = _gr->target(it);
21.516 + Value relaxed = OperationTraits::plus(values[i], (*_length)[it]);
21.517 + if (OperationTraits::less(relaxed, (*_dist)[target])) {
21.518 + _pred->set(target, it);
21.519 + _dist->set(target, relaxed);
21.520 + if (!(*_mask)[target]) {
21.521 + _mask->set(target, true);
21.522 + nextProcess.push_back(target);
21.523 + }
21.524 + }
21.525 + }
21.526 + }
21.527 + _process.swap(nextProcess);
21.528 + return _process.empty();
21.529 + }
21.530 +
21.531 + /// \brief Executes one weak round from the Bellman-Ford algorithm.
21.532 + ///
21.533 + /// If the algorithm calculated the distances in the previous round
21.534 + /// at least for the paths of at most \c k arcs, then this function
21.535 + /// will calculate the distances at least for the paths of at most
21.536 + /// <tt>k+1</tt> arcs.
21.537 + /// This function does not make it possible to calculate the shortest
21.538 + /// path distances exactly for paths consisting of at most \c k arcs,
21.539 + /// this is why it is called weak round.
21.540 + ///
21.541 + /// \return \c true when the algorithm have not found more shorter
21.542 + /// paths.
21.543 + ///
21.544 + /// \see ActiveIt
21.545 + bool processNextWeakRound() {
21.546 + for (int i = 0; i < int(_process.size()); ++i) {
21.547 + _mask->set(_process[i], false);
21.548 + }
21.549 + std::vector<Node> nextProcess;
21.550 + for (int i = 0; i < int(_process.size()); ++i) {
21.551 + for (OutArcIt it(*_gr, _process[i]); it != INVALID; ++it) {
21.552 + Node target = _gr->target(it);
21.553 + Value relaxed =
21.554 + OperationTraits::plus((*_dist)[_process[i]], (*_length)[it]);
21.555 + if (OperationTraits::less(relaxed, (*_dist)[target])) {
21.556 + _pred->set(target, it);
21.557 + _dist->set(target, relaxed);
21.558 + if (!(*_mask)[target]) {
21.559 + _mask->set(target, true);
21.560 + nextProcess.push_back(target);
21.561 + }
21.562 + }
21.563 + }
21.564 + }
21.565 + _process.swap(nextProcess);
21.566 + return _process.empty();
21.567 + }
21.568 +
21.569 + /// \brief Executes the algorithm.
21.570 + ///
21.571 + /// Executes the algorithm.
21.572 + ///
21.573 + /// This method runs the Bellman-Ford algorithm from the root node(s)
21.574 + /// in order to compute the shortest path to each node.
21.575 + ///
21.576 + /// The algorithm computes
21.577 + /// - the shortest path tree (forest),
21.578 + /// - the distance of each node from the root(s).
21.579 + ///
21.580 + /// \pre init() must be called and at least one root node should be
21.581 + /// added with addSource() before using this function.
21.582 + void start() {
21.583 + int num = countNodes(*_gr) - 1;
21.584 + for (int i = 0; i < num; ++i) {
21.585 + if (processNextWeakRound()) break;
21.586 + }
21.587 + }
21.588 +
21.589 + /// \brief Executes the algorithm and checks the negative cycles.
21.590 + ///
21.591 + /// Executes the algorithm and checks the negative cycles.
21.592 + ///
21.593 + /// This method runs the Bellman-Ford algorithm from the root node(s)
21.594 + /// in order to compute the shortest path to each node and also checks
21.595 + /// if the digraph contains cycles with negative total length.
21.596 + ///
21.597 + /// The algorithm computes
21.598 + /// - the shortest path tree (forest),
21.599 + /// - the distance of each node from the root(s).
21.600 + ///
21.601 + /// \return \c false if there is a negative cycle in the digraph.
21.602 + ///
21.603 + /// \pre init() must be called and at least one root node should be
21.604 + /// added with addSource() before using this function.
21.605 + bool checkedStart() {
21.606 + int num = countNodes(*_gr);
21.607 + for (int i = 0; i < num; ++i) {
21.608 + if (processNextWeakRound()) return true;
21.609 + }
21.610 + return _process.empty();
21.611 + }
21.612 +
21.613 + /// \brief Executes the algorithm with arc number limit.
21.614 + ///
21.615 + /// Executes the algorithm with arc number limit.
21.616 + ///
21.617 + /// This method runs the Bellman-Ford algorithm from the root node(s)
21.618 + /// in order to compute the shortest path distance for each node
21.619 + /// using only the paths consisting of at most \c num arcs.
21.620 + ///
21.621 + /// The algorithm computes
21.622 + /// - the limited distance of each node from the root(s),
21.623 + /// - the predecessor arc for each node.
21.624 + ///
21.625 + /// \warning The paths with limited arc number cannot be retrieved
21.626 + /// easily with \ref path() or \ref predArc() functions. If you also
21.627 + /// need the shortest paths and not only the distances, you should
21.628 + /// store the \ref predMap() "predecessor map" after each iteration
21.629 + /// and build the path manually.
21.630 + ///
21.631 + /// \pre init() must be called and at least one root node should be
21.632 + /// added with addSource() before using this function.
21.633 + void limitedStart(int num) {
21.634 + for (int i = 0; i < num; ++i) {
21.635 + if (processNextRound()) break;
21.636 + }
21.637 + }
21.638 +
21.639 + /// \brief Runs the algorithm from the given root node.
21.640 + ///
21.641 + /// This method runs the Bellman-Ford algorithm from the given root
21.642 + /// node \c s in order to compute the shortest path to each node.
21.643 + ///
21.644 + /// The algorithm computes
21.645 + /// - the shortest path tree (forest),
21.646 + /// - the distance of each node from the root(s).
21.647 + ///
21.648 + /// \note bf.run(s) is just a shortcut of the following code.
21.649 + /// \code
21.650 + /// bf.init();
21.651 + /// bf.addSource(s);
21.652 + /// bf.start();
21.653 + /// \endcode
21.654 + void run(Node s) {
21.655 + init();
21.656 + addSource(s);
21.657 + start();
21.658 + }
21.659 +
21.660 + /// \brief Runs the algorithm from the given root node with arc
21.661 + /// number limit.
21.662 + ///
21.663 + /// This method runs the Bellman-Ford algorithm from the given root
21.664 + /// node \c s in order to compute the shortest path distance for each
21.665 + /// node using only the paths consisting of at most \c num arcs.
21.666 + ///
21.667 + /// The algorithm computes
21.668 + /// - the limited distance of each node from the root(s),
21.669 + /// - the predecessor arc for each node.
21.670 + ///
21.671 + /// \warning The paths with limited arc number cannot be retrieved
21.672 + /// easily with \ref path() or \ref predArc() functions. If you also
21.673 + /// need the shortest paths and not only the distances, you should
21.674 + /// store the \ref predMap() "predecessor map" after each iteration
21.675 + /// and build the path manually.
21.676 + ///
21.677 + /// \note bf.run(s, num) is just a shortcut of the following code.
21.678 + /// \code
21.679 + /// bf.init();
21.680 + /// bf.addSource(s);
21.681 + /// bf.limitedStart(num);
21.682 + /// \endcode
21.683 + void run(Node s, int num) {
21.684 + init();
21.685 + addSource(s);
21.686 + limitedStart(num);
21.687 + }
21.688 +
21.689 + ///@}
21.690 +
21.691 + /// \brief LEMON iterator for getting the active nodes.
21.692 + ///
21.693 + /// This class provides a common style LEMON iterator that traverses
21.694 + /// the active nodes of the Bellman-Ford algorithm after the last
21.695 + /// phase. These nodes should be checked in the next phase to
21.696 + /// find augmenting arcs outgoing from them.
21.697 + class ActiveIt {
21.698 + public:
21.699 +
21.700 + /// \brief Constructor.
21.701 + ///
21.702 + /// Constructor for getting the active nodes of the given BellmanFord
21.703 + /// instance.
21.704 + ActiveIt(const BellmanFord& algorithm) : _algorithm(&algorithm)
21.705 + {
21.706 + _index = _algorithm->_process.size() - 1;
21.707 + }
21.708 +
21.709 + /// \brief Invalid constructor.
21.710 + ///
21.711 + /// Invalid constructor.
21.712 + ActiveIt(Invalid) : _algorithm(0), _index(-1) {}
21.713 +
21.714 + /// \brief Conversion to \c Node.
21.715 + ///
21.716 + /// Conversion to \c Node.
21.717 + operator Node() const {
21.718 + return _index >= 0 ? _algorithm->_process[_index] : INVALID;
21.719 + }
21.720 +
21.721 + /// \brief Increment operator.
21.722 + ///
21.723 + /// Increment operator.
21.724 + ActiveIt& operator++() {
21.725 + --_index;
21.726 + return *this;
21.727 + }
21.728 +
21.729 + bool operator==(const ActiveIt& it) const {
21.730 + return static_cast<Node>(*this) == static_cast<Node>(it);
21.731 + }
21.732 + bool operator!=(const ActiveIt& it) const {
21.733 + return static_cast<Node>(*this) != static_cast<Node>(it);
21.734 + }
21.735 + bool operator<(const ActiveIt& it) const {
21.736 + return static_cast<Node>(*this) < static_cast<Node>(it);
21.737 + }
21.738 +
21.739 + private:
21.740 + const BellmanFord* _algorithm;
21.741 + int _index;
21.742 + };
21.743 +
21.744 + /// \name Query Functions
21.745 + /// The result of the Bellman-Ford algorithm can be obtained using these
21.746 + /// functions.\n
21.747 + /// Either \ref run() or \ref init() should be called before using them.
21.748 +
21.749 + ///@{
21.750 +
21.751 + /// \brief The shortest path to the given node.
21.752 + ///
21.753 + /// Gives back the shortest path to the given node from the root(s).
21.754 + ///
21.755 + /// \warning \c t should be reached from the root(s).
21.756 + ///
21.757 + /// \pre Either \ref run() or \ref init() must be called before
21.758 + /// using this function.
21.759 + Path path(Node t) const
21.760 + {
21.761 + return Path(*_gr, *_pred, t);
21.762 + }
21.763 +
21.764 + /// \brief The distance of the given node from the root(s).
21.765 + ///
21.766 + /// Returns the distance of the given node from the root(s).
21.767 + ///
21.768 + /// \warning If node \c v is not reached from the root(s), then
21.769 + /// the return value of this function is undefined.
21.770 + ///
21.771 + /// \pre Either \ref run() or \ref init() must be called before
21.772 + /// using this function.
21.773 + Value dist(Node v) const { return (*_dist)[v]; }
21.774 +
21.775 + /// \brief Returns the 'previous arc' of the shortest path tree for
21.776 + /// the given node.
21.777 + ///
21.778 + /// This function returns the 'previous arc' of the shortest path
21.779 + /// tree for node \c v, i.e. it returns the last arc of a
21.780 + /// shortest path from a root to \c v. It is \c INVALID if \c v
21.781 + /// is not reached from the root(s) or if \c v is a root.
21.782 + ///
21.783 + /// The shortest path tree used here is equal to the shortest path
21.784 + /// tree used in \ref predNode() and \ref predMap().
21.785 + ///
21.786 + /// \pre Either \ref run() or \ref init() must be called before
21.787 + /// using this function.
21.788 + Arc predArc(Node v) const { return (*_pred)[v]; }
21.789 +
21.790 + /// \brief Returns the 'previous node' of the shortest path tree for
21.791 + /// the given node.
21.792 + ///
21.793 + /// This function returns the 'previous node' of the shortest path
21.794 + /// tree for node \c v, i.e. it returns the last but one node of
21.795 + /// a shortest path from a root to \c v. It is \c INVALID if \c v
21.796 + /// is not reached from the root(s) or if \c v is a root.
21.797 + ///
21.798 + /// The shortest path tree used here is equal to the shortest path
21.799 + /// tree used in \ref predArc() and \ref predMap().
21.800 + ///
21.801 + /// \pre Either \ref run() or \ref init() must be called before
21.802 + /// using this function.
21.803 + Node predNode(Node v) const {
21.804 + return (*_pred)[v] == INVALID ? INVALID : _gr->source((*_pred)[v]);
21.805 + }
21.806 +
21.807 + /// \brief Returns a const reference to the node map that stores the
21.808 + /// distances of the nodes.
21.809 + ///
21.810 + /// Returns a const reference to the node map that stores the distances
21.811 + /// of the nodes calculated by the algorithm.
21.812 + ///
21.813 + /// \pre Either \ref run() or \ref init() must be called before
21.814 + /// using this function.
21.815 + const DistMap &distMap() const { return *_dist;}
21.816 +
21.817 + /// \brief Returns a const reference to the node map that stores the
21.818 + /// predecessor arcs.
21.819 + ///
21.820 + /// Returns a const reference to the node map that stores the predecessor
21.821 + /// arcs, which form the shortest path tree (forest).
21.822 + ///
21.823 + /// \pre Either \ref run() or \ref init() must be called before
21.824 + /// using this function.
21.825 + const PredMap &predMap() const { return *_pred; }
21.826 +
21.827 + /// \brief Checks if a node is reached from the root(s).
21.828 + ///
21.829 + /// Returns \c true if \c v is reached from the root(s).
21.830 + ///
21.831 + /// \pre Either \ref run() or \ref init() must be called before
21.832 + /// using this function.
21.833 + bool reached(Node v) const {
21.834 + return (*_dist)[v] != OperationTraits::infinity();
21.835 + }
21.836 +
21.837 + /// \brief Gives back a negative cycle.
21.838 + ///
21.839 + /// This function gives back a directed cycle with negative total
21.840 + /// length if the algorithm has already found one.
21.841 + /// Otherwise it gives back an empty path.
21.842 + lemon::Path<Digraph> negativeCycle() const {
21.843 + typename Digraph::template NodeMap<int> state(*_gr, -1);
21.844 + lemon::Path<Digraph> cycle;
21.845 + for (int i = 0; i < int(_process.size()); ++i) {
21.846 + if (state[_process[i]] != -1) continue;
21.847 + for (Node v = _process[i]; (*_pred)[v] != INVALID;
21.848 + v = _gr->source((*_pred)[v])) {
21.849 + if (state[v] == i) {
21.850 + cycle.addFront((*_pred)[v]);
21.851 + for (Node u = _gr->source((*_pred)[v]); u != v;
21.852 + u = _gr->source((*_pred)[u])) {
21.853 + cycle.addFront((*_pred)[u]);
21.854 + }
21.855 + return cycle;
21.856 + }
21.857 + else if (state[v] >= 0) {
21.858 + break;
21.859 + }
21.860 + state[v] = i;
21.861 + }
21.862 + }
21.863 + return cycle;
21.864 + }
21.865 +
21.866 + ///@}
21.867 + };
21.868 +
21.869 + /// \brief Default traits class of bellmanFord() function.
21.870 + ///
21.871 + /// Default traits class of bellmanFord() function.
21.872 + /// \tparam GR The type of the digraph.
21.873 + /// \tparam LEN The type of the length map.
21.874 + template <typename GR, typename LEN>
21.875 + struct BellmanFordWizardDefaultTraits {
21.876 + /// The type of the digraph the algorithm runs on.
21.877 + typedef GR Digraph;
21.878 +
21.879 + /// \brief The type of the map that stores the arc lengths.
21.880 + ///
21.881 + /// The type of the map that stores the arc lengths.
21.882 + /// It must meet the \ref concepts::ReadMap "ReadMap" concept.
21.883 + typedef LEN LengthMap;
21.884 +
21.885 + /// The type of the arc lengths.
21.886 + typedef typename LEN::Value Value;
21.887 +
21.888 + /// \brief Operation traits for Bellman-Ford algorithm.
21.889 + ///
21.890 + /// It defines the used operations and the infinity value for the
21.891 + /// given \c Value type.
21.892 + /// \see BellmanFordDefaultOperationTraits,
21.893 + /// BellmanFordToleranceOperationTraits
21.894 + typedef BellmanFordDefaultOperationTraits<Value> OperationTraits;
21.895 +
21.896 + /// \brief The type of the map that stores the last
21.897 + /// arcs of the shortest paths.
21.898 + ///
21.899 + /// The type of the map that stores the last arcs of the shortest paths.
21.900 + /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
21.901 + typedef typename GR::template NodeMap<typename GR::Arc> PredMap;
21.902 +
21.903 + /// \brief Instantiates a \c PredMap.
21.904 + ///
21.905 + /// This function instantiates a \ref PredMap.
21.906 + /// \param g is the digraph to which we would like to define the
21.907 + /// \ref PredMap.
21.908 + static PredMap *createPredMap(const GR &g) {
21.909 + return new PredMap(g);
21.910 + }
21.911 +
21.912 + /// \brief The type of the map that stores the distances of the nodes.
21.913 + ///
21.914 + /// The type of the map that stores the distances of the nodes.
21.915 + /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
21.916 + typedef typename GR::template NodeMap<Value> DistMap;
21.917 +
21.918 + /// \brief Instantiates a \c DistMap.
21.919 + ///
21.920 + /// This function instantiates a \ref DistMap.
21.921 + /// \param g is the digraph to which we would like to define the
21.922 + /// \ref DistMap.
21.923 + static DistMap *createDistMap(const GR &g) {
21.924 + return new DistMap(g);
21.925 + }
21.926 +
21.927 + ///The type of the shortest paths.
21.928 +
21.929 + ///The type of the shortest paths.
21.930 + ///It must meet the \ref concepts::Path "Path" concept.
21.931 + typedef lemon::Path<Digraph> Path;
21.932 + };
21.933 +
21.934 + /// \brief Default traits class used by BellmanFordWizard.
21.935 + ///
21.936 + /// Default traits class used by BellmanFordWizard.
21.937 + /// \tparam GR The type of the digraph.
21.938 + /// \tparam LEN The type of the length map.
21.939 + template <typename GR, typename LEN>
21.940 + class BellmanFordWizardBase
21.941 + : public BellmanFordWizardDefaultTraits<GR, LEN> {
21.942 +
21.943 + typedef BellmanFordWizardDefaultTraits<GR, LEN> Base;
21.944 + protected:
21.945 + // Type of the nodes in the digraph.
21.946 + typedef typename Base::Digraph::Node Node;
21.947 +
21.948 + // Pointer to the underlying digraph.
21.949 + void *_graph;
21.950 + // Pointer to the length map
21.951 + void *_length;
21.952 + // Pointer to the map of predecessors arcs.
21.953 + void *_pred;
21.954 + // Pointer to the map of distances.
21.955 + void *_dist;
21.956 + //Pointer to the shortest path to the target node.
21.957 + void *_path;
21.958 + //Pointer to the distance of the target node.
21.959 + void *_di;
21.960 +
21.961 + public:
21.962 + /// Constructor.
21.963 +
21.964 + /// This constructor does not require parameters, it initiates
21.965 + /// all of the attributes to default values \c 0.
21.966 + BellmanFordWizardBase() :
21.967 + _graph(0), _length(0), _pred(0), _dist(0), _path(0), _di(0) {}
21.968 +
21.969 + /// Constructor.
21.970 +
21.971 + /// This constructor requires two parameters,
21.972 + /// others are initiated to \c 0.
21.973 + /// \param gr The digraph the algorithm runs on.
21.974 + /// \param len The length map.
21.975 + BellmanFordWizardBase(const GR& gr,
21.976 + const LEN& len) :
21.977 + _graph(reinterpret_cast<void*>(const_cast<GR*>(&gr))),
21.978 + _length(reinterpret_cast<void*>(const_cast<LEN*>(&len))),
21.979 + _pred(0), _dist(0), _path(0), _di(0) {}
21.980 +
21.981 + };
21.982 +
21.983 + /// \brief Auxiliary class for the function-type interface of the
21.984 + /// \ref BellmanFord "Bellman-Ford" algorithm.
21.985 + ///
21.986 + /// This auxiliary class is created to implement the
21.987 + /// \ref bellmanFord() "function-type interface" of the
21.988 + /// \ref BellmanFord "Bellman-Ford" algorithm.
21.989 + /// It does not have own \ref run() method, it uses the
21.990 + /// functions and features of the plain \ref BellmanFord.
21.991 + ///
21.992 + /// This class should only be used through the \ref bellmanFord()
21.993 + /// function, which makes it easier to use the algorithm.
21.994 + ///
21.995 + /// \tparam TR The traits class that defines various types used by the
21.996 + /// algorithm.
21.997 + template<class TR>
21.998 + class BellmanFordWizard : public TR {
21.999 + typedef TR Base;
21.1000 +
21.1001 + typedef typename TR::Digraph Digraph;
21.1002 +
21.1003 + typedef typename Digraph::Node Node;
21.1004 + typedef typename Digraph::NodeIt NodeIt;
21.1005 + typedef typename Digraph::Arc Arc;
21.1006 + typedef typename Digraph::OutArcIt ArcIt;
21.1007 +
21.1008 + typedef typename TR::LengthMap LengthMap;
21.1009 + typedef typename LengthMap::Value Value;
21.1010 + typedef typename TR::PredMap PredMap;
21.1011 + typedef typename TR::DistMap DistMap;
21.1012 + typedef typename TR::Path Path;
21.1013 +
21.1014 + public:
21.1015 + /// Constructor.
21.1016 + BellmanFordWizard() : TR() {}
21.1017 +
21.1018 + /// \brief Constructor that requires parameters.
21.1019 + ///
21.1020 + /// Constructor that requires parameters.
21.1021 + /// These parameters will be the default values for the traits class.
21.1022 + /// \param gr The digraph the algorithm runs on.
21.1023 + /// \param len The length map.
21.1024 + BellmanFordWizard(const Digraph& gr, const LengthMap& len)
21.1025 + : TR(gr, len) {}
21.1026 +
21.1027 + /// \brief Copy constructor
21.1028 + BellmanFordWizard(const TR &b) : TR(b) {}
21.1029 +
21.1030 + ~BellmanFordWizard() {}
21.1031 +
21.1032 + /// \brief Runs the Bellman-Ford algorithm from the given source node.
21.1033 + ///
21.1034 + /// This method runs the Bellman-Ford algorithm from the given source
21.1035 + /// node in order to compute the shortest path to each node.
21.1036 + void run(Node s) {
21.1037 + BellmanFord<Digraph,LengthMap,TR>
21.1038 + bf(*reinterpret_cast<const Digraph*>(Base::_graph),
21.1039 + *reinterpret_cast<const LengthMap*>(Base::_length));
21.1040 + if (Base::_pred) bf.predMap(*reinterpret_cast<PredMap*>(Base::_pred));
21.1041 + if (Base::_dist) bf.distMap(*reinterpret_cast<DistMap*>(Base::_dist));
21.1042 + bf.run(s);
21.1043 + }
21.1044 +
21.1045 + /// \brief Runs the Bellman-Ford algorithm to find the shortest path
21.1046 + /// between \c s and \c t.
21.1047 + ///
21.1048 + /// This method runs the Bellman-Ford algorithm from node \c s
21.1049 + /// in order to compute the shortest path to node \c t.
21.1050 + /// Actually, it computes the shortest path to each node, but using
21.1051 + /// this function you can retrieve the distance and the shortest path
21.1052 + /// for a single target node easier.
21.1053 + ///
21.1054 + /// \return \c true if \c t is reachable form \c s.
21.1055 + bool run(Node s, Node t) {
21.1056 + BellmanFord<Digraph,LengthMap,TR>
21.1057 + bf(*reinterpret_cast<const Digraph*>(Base::_graph),
21.1058 + *reinterpret_cast<const LengthMap*>(Base::_length));
21.1059 + if (Base::_pred) bf.predMap(*reinterpret_cast<PredMap*>(Base::_pred));
21.1060 + if (Base::_dist) bf.distMap(*reinterpret_cast<DistMap*>(Base::_dist));
21.1061 + bf.run(s);
21.1062 + if (Base::_path) *reinterpret_cast<Path*>(Base::_path) = bf.path(t);
21.1063 + if (Base::_di) *reinterpret_cast<Value*>(Base::_di) = bf.dist(t);
21.1064 + return bf.reached(t);
21.1065 + }
21.1066 +
21.1067 + template<class T>
21.1068 + struct SetPredMapBase : public Base {
21.1069 + typedef T PredMap;
21.1070 + static PredMap *createPredMap(const Digraph &) { return 0; };
21.1071 + SetPredMapBase(const TR &b) : TR(b) {}
21.1072 + };
21.1073 +
21.1074 + /// \brief \ref named-templ-param "Named parameter" for setting
21.1075 + /// the predecessor map.
21.1076 + ///
21.1077 + /// \ref named-templ-param "Named parameter" for setting
21.1078 + /// the map that stores the predecessor arcs of the nodes.
21.1079 + template<class T>
21.1080 + BellmanFordWizard<SetPredMapBase<T> > predMap(const T &t) {
21.1081 + Base::_pred=reinterpret_cast<void*>(const_cast<T*>(&t));
21.1082 + return BellmanFordWizard<SetPredMapBase<T> >(*this);
21.1083 + }
21.1084 +
21.1085 + template<class T>
21.1086 + struct SetDistMapBase : public Base {
21.1087 + typedef T DistMap;
21.1088 + static DistMap *createDistMap(const Digraph &) { return 0; };
21.1089 + SetDistMapBase(const TR &b) : TR(b) {}
21.1090 + };
21.1091 +
21.1092 + /// \brief \ref named-templ-param "Named parameter" for setting
21.1093 + /// the distance map.
21.1094 + ///
21.1095 + /// \ref named-templ-param "Named parameter" for setting
21.1096 + /// the map that stores the distances of the nodes calculated
21.1097 + /// by the algorithm.
21.1098 + template<class T>
21.1099 + BellmanFordWizard<SetDistMapBase<T> > distMap(const T &t) {
21.1100 + Base::_dist=reinterpret_cast<void*>(const_cast<T*>(&t));
21.1101 + return BellmanFordWizard<SetDistMapBase<T> >(*this);
21.1102 + }
21.1103 +
21.1104 + template<class T>
21.1105 + struct SetPathBase : public Base {
21.1106 + typedef T Path;
21.1107 + SetPathBase(const TR &b) : TR(b) {}
21.1108 + };
21.1109 +
21.1110 + /// \brief \ref named-func-param "Named parameter" for getting
21.1111 + /// the shortest path to the target node.
21.1112 + ///
21.1113 + /// \ref named-func-param "Named parameter" for getting
21.1114 + /// the shortest path to the target node.
21.1115 + template<class T>
21.1116 + BellmanFordWizard<SetPathBase<T> > path(const T &t)
21.1117 + {
21.1118 + Base::_path=reinterpret_cast<void*>(const_cast<T*>(&t));
21.1119 + return BellmanFordWizard<SetPathBase<T> >(*this);
21.1120 + }
21.1121 +
21.1122 + /// \brief \ref named-func-param "Named parameter" for getting
21.1123 + /// the distance of the target node.
21.1124 + ///
21.1125 + /// \ref named-func-param "Named parameter" for getting
21.1126 + /// the distance of the target node.
21.1127 + BellmanFordWizard dist(const Value &d)
21.1128 + {
21.1129 + Base::_di=reinterpret_cast<void*>(const_cast<Value*>(&d));
21.1130 + return *this;
21.1131 + }
21.1132 +
21.1133 + };
21.1134 +
21.1135 + /// \brief Function type interface for the \ref BellmanFord "Bellman-Ford"
21.1136 + /// algorithm.
21.1137 + ///
21.1138 + /// \ingroup shortest_path
21.1139 + /// Function type interface for the \ref BellmanFord "Bellman-Ford"
21.1140 + /// algorithm.
21.1141 + ///
21.1142 + /// This function also has several \ref named-templ-func-param
21.1143 + /// "named parameters", they are declared as the members of class
21.1144 + /// \ref BellmanFordWizard.
21.1145 + /// The following examples show how to use these parameters.
21.1146 + /// \code
21.1147 + /// // Compute shortest path from node s to each node
21.1148 + /// bellmanFord(g,length).predMap(preds).distMap(dists).run(s);
21.1149 + ///
21.1150 + /// // Compute shortest path from s to t
21.1151 + /// bool reached = bellmanFord(g,length).path(p).dist(d).run(s,t);
21.1152 + /// \endcode
21.1153 + /// \warning Don't forget to put the \ref BellmanFordWizard::run() "run()"
21.1154 + /// to the end of the parameter list.
21.1155 + /// \sa BellmanFordWizard
21.1156 + /// \sa BellmanFord
21.1157 + template<typename GR, typename LEN>
21.1158 + BellmanFordWizard<BellmanFordWizardBase<GR,LEN> >
21.1159 + bellmanFord(const GR& digraph,
21.1160 + const LEN& length)
21.1161 + {
21.1162 + return BellmanFordWizard<BellmanFordWizardBase<GR,LEN> >(digraph, length);
21.1163 + }
21.1164 +
21.1165 +} //END OF NAMESPACE LEMON
21.1166 +
21.1167 +#endif
21.1168 +
22.1 --- a/lemon/bfs.h Tue Dec 20 17:44:38 2011 +0100
22.2 +++ b/lemon/bfs.h Tue Dec 20 18:15:14 2011 +0100
22.3 @@ -2,7 +2,7 @@
22.4 *
22.5 * This file is a part of LEMON, a generic C++ optimization library.
22.6 *
22.7 - * Copyright (C) 2003-2009
22.8 + * Copyright (C) 2003-2010
22.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
22.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
22.11 *
22.12 @@ -47,7 +47,7 @@
22.13 ///
22.14 ///The type of the map that stores the predecessor
22.15 ///arcs of the shortest paths.
22.16 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
22.17 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
22.18 typedef typename Digraph::template NodeMap<typename Digraph::Arc> PredMap;
22.19 ///Instantiates a \c PredMap.
22.20
22.21 @@ -62,7 +62,8 @@
22.22 ///The type of the map that indicates which nodes are processed.
22.23
22.24 ///The type of the map that indicates which nodes are processed.
22.25 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
22.26 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
22.27 + ///By default, it is a NullMap.
22.28 typedef NullMap<typename Digraph::Node,bool> ProcessedMap;
22.29 ///Instantiates a \c ProcessedMap.
22.30
22.31 @@ -81,7 +82,8 @@
22.32 ///The type of the map that indicates which nodes are reached.
22.33
22.34 ///The type of the map that indicates which nodes are reached.
22.35 - ///It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
22.36 + ///It must conform to
22.37 + ///the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
22.38 typedef typename Digraph::template NodeMap<bool> ReachedMap;
22.39 ///Instantiates a \c ReachedMap.
22.40
22.41 @@ -96,7 +98,7 @@
22.42 ///The type of the map that stores the distances of the nodes.
22.43
22.44 ///The type of the map that stores the distances of the nodes.
22.45 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
22.46 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
22.47 typedef typename Digraph::template NodeMap<int> DistMap;
22.48 ///Instantiates a \c DistMap.
22.49
22.50 @@ -120,6 +122,11 @@
22.51 ///
22.52 ///\tparam GR The type of the digraph the algorithm runs on.
22.53 ///The default type is \ref ListDigraph.
22.54 + ///\tparam TR The traits class that defines various types used by the
22.55 + ///algorithm. By default, it is \ref BfsDefaultTraits
22.56 + ///"BfsDefaultTraits<GR>".
22.57 + ///In most cases, this parameter should not be set directly,
22.58 + ///consider to use the named template parameters instead.
22.59 #ifdef DOXYGEN
22.60 template <typename GR,
22.61 typename TR>
22.62 @@ -225,7 +232,7 @@
22.63 ///
22.64 ///\ref named-templ-param "Named parameter" for setting
22.65 ///\c PredMap type.
22.66 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
22.67 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
22.68 template <class T>
22.69 struct SetPredMap : public Bfs< Digraph, SetPredMapTraits<T> > {
22.70 typedef Bfs< Digraph, SetPredMapTraits<T> > Create;
22.71 @@ -245,7 +252,7 @@
22.72 ///
22.73 ///\ref named-templ-param "Named parameter" for setting
22.74 ///\c DistMap type.
22.75 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
22.76 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
22.77 template <class T>
22.78 struct SetDistMap : public Bfs< Digraph, SetDistMapTraits<T> > {
22.79 typedef Bfs< Digraph, SetDistMapTraits<T> > Create;
22.80 @@ -265,7 +272,8 @@
22.81 ///
22.82 ///\ref named-templ-param "Named parameter" for setting
22.83 ///\c ReachedMap type.
22.84 - ///It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
22.85 + ///It must conform to
22.86 + ///the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
22.87 template <class T>
22.88 struct SetReachedMap : public Bfs< Digraph, SetReachedMapTraits<T> > {
22.89 typedef Bfs< Digraph, SetReachedMapTraits<T> > Create;
22.90 @@ -285,7 +293,7 @@
22.91 ///
22.92 ///\ref named-templ-param "Named parameter" for setting
22.93 ///\c ProcessedMap type.
22.94 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
22.95 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
22.96 template <class T>
22.97 struct SetProcessedMap : public Bfs< Digraph, SetProcessedMapTraits<T> > {
22.98 typedef Bfs< Digraph, SetProcessedMapTraits<T> > Create;
22.99 @@ -413,8 +421,8 @@
22.100 ///\name Execution Control
22.101 ///The simplest way to execute the BFS algorithm is to use one of the
22.102 ///member functions called \ref run(Node) "run()".\n
22.103 - ///If you need more control on the execution, first you have to call
22.104 - ///\ref init(), then you can add several source nodes with
22.105 + ///If you need better control on the execution, you have to call
22.106 + ///\ref init() first, then you can add several source nodes with
22.107 ///\ref addSource(). Finally the actual path computation can be
22.108 ///performed with one of the \ref start() functions.
22.109
22.110 @@ -700,12 +708,8 @@
22.111
22.112 ///Runs the algorithm to visit all nodes in the digraph.
22.113
22.114 - ///This method runs the %BFS algorithm in order to
22.115 - ///compute the shortest path to each node.
22.116 - ///
22.117 - ///The algorithm computes
22.118 - ///- the shortest path tree (forest),
22.119 - ///- the distance of each node from the root(s).
22.120 + ///This method runs the %BFS algorithm in order to visit all nodes
22.121 + ///in the digraph.
22.122 ///
22.123 ///\note <tt>b.run(s)</tt> is just a shortcut of the following code.
22.124 ///\code
22.125 @@ -737,9 +741,9 @@
22.126
22.127 ///@{
22.128
22.129 - ///The shortest path to a node.
22.130 + ///The shortest path to the given node.
22.131
22.132 - ///Returns the shortest path to a node.
22.133 + ///Returns the shortest path to the given node from the root(s).
22.134 ///
22.135 ///\warning \c t should be reached from the root(s).
22.136 ///
22.137 @@ -747,9 +751,9 @@
22.138 ///must be called before using this function.
22.139 Path path(Node t) const { return Path(*G, *_pred, t); }
22.140
22.141 - ///The distance of a node from the root(s).
22.142 + ///The distance of the given node from the root(s).
22.143
22.144 - ///Returns the distance of a node from the root(s).
22.145 + ///Returns the distance of the given node from the root(s).
22.146 ///
22.147 ///\warning If node \c v is not reached from the root(s), then
22.148 ///the return value of this function is undefined.
22.149 @@ -758,29 +762,31 @@
22.150 ///must be called before using this function.
22.151 int dist(Node v) const { return (*_dist)[v]; }
22.152
22.153 - ///Returns the 'previous arc' of the shortest path tree for a node.
22.154 -
22.155 + ///\brief Returns the 'previous arc' of the shortest path tree for
22.156 + ///the given node.
22.157 + ///
22.158 ///This function returns the 'previous arc' of the shortest path
22.159 ///tree for the node \c v, i.e. it returns the last arc of a
22.160 ///shortest path from a root to \c v. It is \c INVALID if \c v
22.161 ///is not reached from the root(s) or if \c v is a root.
22.162 ///
22.163 ///The shortest path tree used here is equal to the shortest path
22.164 - ///tree used in \ref predNode().
22.165 + ///tree used in \ref predNode() and \ref predMap().
22.166 ///
22.167 ///\pre Either \ref run(Node) "run()" or \ref init()
22.168 ///must be called before using this function.
22.169 Arc predArc(Node v) const { return (*_pred)[v];}
22.170
22.171 - ///Returns the 'previous node' of the shortest path tree for a node.
22.172 -
22.173 + ///\brief Returns the 'previous node' of the shortest path tree for
22.174 + ///the given node.
22.175 + ///
22.176 ///This function returns the 'previous node' of the shortest path
22.177 ///tree for the node \c v, i.e. it returns the last but one node
22.178 - ///from a shortest path from a root to \c v. It is \c INVALID
22.179 + ///of a shortest path from a root to \c v. It is \c INVALID
22.180 ///if \c v is not reached from the root(s) or if \c v is a root.
22.181 ///
22.182 ///The shortest path tree used here is equal to the shortest path
22.183 - ///tree used in \ref predArc().
22.184 + ///tree used in \ref predArc() and \ref predMap().
22.185 ///
22.186 ///\pre Either \ref run(Node) "run()" or \ref init()
22.187 ///must be called before using this function.
22.188 @@ -801,13 +807,13 @@
22.189 ///predecessor arcs.
22.190 ///
22.191 ///Returns a const reference to the node map that stores the predecessor
22.192 - ///arcs, which form the shortest path tree.
22.193 + ///arcs, which form the shortest path tree (forest).
22.194 ///
22.195 ///\pre Either \ref run(Node) "run()" or \ref init()
22.196 ///must be called before using this function.
22.197 const PredMap &predMap() const { return *_pred;}
22.198
22.199 - ///Checks if a node is reached from the root(s).
22.200 + ///Checks if the given node is reached from the root(s).
22.201
22.202 ///Returns \c true if \c v is reached from the root(s).
22.203 ///
22.204 @@ -833,7 +839,7 @@
22.205 ///
22.206 ///The type of the map that stores the predecessor
22.207 ///arcs of the shortest paths.
22.208 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
22.209 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
22.210 typedef typename Digraph::template NodeMap<typename Digraph::Arc> PredMap;
22.211 ///Instantiates a PredMap.
22.212
22.213 @@ -848,8 +854,8 @@
22.214 ///The type of the map that indicates which nodes are processed.
22.215
22.216 ///The type of the map that indicates which nodes are processed.
22.217 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
22.218 - ///By default it is a NullMap.
22.219 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
22.220 + ///By default, it is a NullMap.
22.221 typedef NullMap<typename Digraph::Node,bool> ProcessedMap;
22.222 ///Instantiates a ProcessedMap.
22.223
22.224 @@ -868,7 +874,8 @@
22.225 ///The type of the map that indicates which nodes are reached.
22.226
22.227 ///The type of the map that indicates which nodes are reached.
22.228 - ///It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
22.229 + ///It must conform to
22.230 + ///the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
22.231 typedef typename Digraph::template NodeMap<bool> ReachedMap;
22.232 ///Instantiates a ReachedMap.
22.233
22.234 @@ -883,7 +890,7 @@
22.235 ///The type of the map that stores the distances of the nodes.
22.236
22.237 ///The type of the map that stores the distances of the nodes.
22.238 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
22.239 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
22.240 typedef typename Digraph::template NodeMap<int> DistMap;
22.241 ///Instantiates a DistMap.
22.242
22.243 @@ -898,18 +905,14 @@
22.244 ///The type of the shortest paths.
22.245
22.246 ///The type of the shortest paths.
22.247 - ///It must meet the \ref concepts::Path "Path" concept.
22.248 + ///It must conform to the \ref concepts::Path "Path" concept.
22.249 typedef lemon::Path<Digraph> Path;
22.250 };
22.251
22.252 /// Default traits class used by BfsWizard
22.253
22.254 - /// To make it easier to use Bfs algorithm
22.255 - /// we have created a wizard class.
22.256 - /// This \ref BfsWizard class needs default traits,
22.257 - /// as well as the \ref Bfs class.
22.258 - /// The \ref BfsWizardBase is a class to be the default traits of the
22.259 - /// \ref BfsWizard class.
22.260 + /// Default traits class used by BfsWizard.
22.261 + /// \tparam GR The type of the digraph.
22.262 template<class GR>
22.263 class BfsWizardBase : public BfsWizardDefaultTraits<GR>
22.264 {
22.265 @@ -937,7 +940,7 @@
22.266 public:
22.267 /// Constructor.
22.268
22.269 - /// This constructor does not require parameters, therefore it initiates
22.270 + /// This constructor does not require parameters, it initiates
22.271 /// all of the attributes to \c 0.
22.272 BfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0),
22.273 _dist(0), _path(0), _di(0) {}
22.274 @@ -962,12 +965,14 @@
22.275 ///
22.276 /// This class should only be used through the \ref bfs() function,
22.277 /// which makes it easier to use the algorithm.
22.278 + ///
22.279 + /// \tparam TR The traits class that defines various types used by the
22.280 + /// algorithm.
22.281 template<class TR>
22.282 class BfsWizard : public TR
22.283 {
22.284 typedef TR Base;
22.285
22.286 - ///The type of the digraph the algorithm runs on.
22.287 typedef typename TR::Digraph Digraph;
22.288
22.289 typedef typename Digraph::Node Node;
22.290 @@ -975,16 +980,10 @@
22.291 typedef typename Digraph::Arc Arc;
22.292 typedef typename Digraph::OutArcIt OutArcIt;
22.293
22.294 - ///\brief The type of the map that stores the predecessor
22.295 - ///arcs of the shortest paths.
22.296 typedef typename TR::PredMap PredMap;
22.297 - ///\brief The type of the map that stores the distances of the nodes.
22.298 typedef typename TR::DistMap DistMap;
22.299 - ///\brief The type of the map that indicates which nodes are reached.
22.300 typedef typename TR::ReachedMap ReachedMap;
22.301 - ///\brief The type of the map that indicates which nodes are processed.
22.302 typedef typename TR::ProcessedMap ProcessedMap;
22.303 - ///The type of the shortest paths
22.304 typedef typename TR::Path Path;
22.305
22.306 public:
22.307 @@ -1054,8 +1053,8 @@
22.308
22.309 ///Runs BFS algorithm to visit all nodes in the digraph.
22.310
22.311 - ///This method runs BFS algorithm in order to compute
22.312 - ///the shortest path to each node.
22.313 + ///This method runs BFS algorithm in order to visit all nodes
22.314 + ///in the digraph.
22.315 void run()
22.316 {
22.317 run(INVALID);
22.318 @@ -1067,11 +1066,12 @@
22.319 static PredMap *createPredMap(const Digraph &) { return 0; };
22.320 SetPredMapBase(const TR &b) : TR(b) {}
22.321 };
22.322 - ///\brief \ref named-func-param "Named parameter"
22.323 - ///for setting PredMap object.
22.324 +
22.325 + ///\brief \ref named-templ-param "Named parameter" for setting
22.326 + ///the predecessor map.
22.327 ///
22.328 - ///\ref named-func-param "Named parameter"
22.329 - ///for setting PredMap object.
22.330 + ///\ref named-templ-param "Named parameter" function for setting
22.331 + ///the map that stores the predecessor arcs of the nodes.
22.332 template<class T>
22.333 BfsWizard<SetPredMapBase<T> > predMap(const T &t)
22.334 {
22.335 @@ -1085,11 +1085,12 @@
22.336 static ReachedMap *createReachedMap(const Digraph &) { return 0; };
22.337 SetReachedMapBase(const TR &b) : TR(b) {}
22.338 };
22.339 - ///\brief \ref named-func-param "Named parameter"
22.340 - ///for setting ReachedMap object.
22.341 +
22.342 + ///\brief \ref named-templ-param "Named parameter" for setting
22.343 + ///the reached map.
22.344 ///
22.345 - /// \ref named-func-param "Named parameter"
22.346 - ///for setting ReachedMap object.
22.347 + ///\ref named-templ-param "Named parameter" function for setting
22.348 + ///the map that indicates which nodes are reached.
22.349 template<class T>
22.350 BfsWizard<SetReachedMapBase<T> > reachedMap(const T &t)
22.351 {
22.352 @@ -1103,11 +1104,13 @@
22.353 static DistMap *createDistMap(const Digraph &) { return 0; };
22.354 SetDistMapBase(const TR &b) : TR(b) {}
22.355 };
22.356 - ///\brief \ref named-func-param "Named parameter"
22.357 - ///for setting DistMap object.
22.358 +
22.359 + ///\brief \ref named-templ-param "Named parameter" for setting
22.360 + ///the distance map.
22.361 ///
22.362 - /// \ref named-func-param "Named parameter"
22.363 - ///for setting DistMap object.
22.364 + ///\ref named-templ-param "Named parameter" function for setting
22.365 + ///the map that stores the distances of the nodes calculated
22.366 + ///by the algorithm.
22.367 template<class T>
22.368 BfsWizard<SetDistMapBase<T> > distMap(const T &t)
22.369 {
22.370 @@ -1121,11 +1124,12 @@
22.371 static ProcessedMap *createProcessedMap(const Digraph &) { return 0; };
22.372 SetProcessedMapBase(const TR &b) : TR(b) {}
22.373 };
22.374 - ///\brief \ref named-func-param "Named parameter"
22.375 - ///for setting ProcessedMap object.
22.376 +
22.377 + ///\brief \ref named-func-param "Named parameter" for setting
22.378 + ///the processed map.
22.379 ///
22.380 - /// \ref named-func-param "Named parameter"
22.381 - ///for setting ProcessedMap object.
22.382 + ///\ref named-templ-param "Named parameter" function for setting
22.383 + ///the map that indicates which nodes are processed.
22.384 template<class T>
22.385 BfsWizard<SetProcessedMapBase<T> > processedMap(const T &t)
22.386 {
22.387 @@ -1264,7 +1268,8 @@
22.388 /// \brief The type of the map that indicates which nodes are reached.
22.389 ///
22.390 /// The type of the map that indicates which nodes are reached.
22.391 - /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
22.392 + /// It must conform to
22.393 + ///the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
22.394 typedef typename Digraph::template NodeMap<bool> ReachedMap;
22.395
22.396 /// \brief Instantiates a ReachedMap.
22.397 @@ -1302,11 +1307,11 @@
22.398 /// \ref BfsVisitor "BfsVisitor<GR>" is an empty visitor, which
22.399 /// does not observe the BFS events. If you want to observe the BFS
22.400 /// events, you should implement your own visitor class.
22.401 - /// \tparam TR Traits class to set various data types used by the
22.402 - /// algorithm. The default traits class is
22.403 - /// \ref BfsVisitDefaultTraits "BfsVisitDefaultTraits<GR>".
22.404 - /// See \ref BfsVisitDefaultTraits for the documentation of
22.405 - /// a BFS visit traits class.
22.406 + /// \tparam TR The traits class that defines various types used by the
22.407 + /// algorithm. By default, it is \ref BfsVisitDefaultTraits
22.408 + /// "BfsVisitDefaultTraits<GR>".
22.409 + /// In most cases, this parameter should not be set directly,
22.410 + /// consider to use the named template parameters instead.
22.411 #ifdef DOXYGEN
22.412 template <typename GR, typename VS, typename TR>
22.413 #else
22.414 @@ -1425,8 +1430,8 @@
22.415 /// \name Execution Control
22.416 /// The simplest way to execute the BFS algorithm is to use one of the
22.417 /// member functions called \ref run(Node) "run()".\n
22.418 - /// If you need more control on the execution, first you have to call
22.419 - /// \ref init(), then you can add several source nodes with
22.420 + /// If you need better control on the execution, you have to call
22.421 + /// \ref init() first, then you can add several source nodes with
22.422 /// \ref addSource(). Finally the actual path computation can be
22.423 /// performed with one of the \ref start() functions.
22.424
22.425 @@ -1698,12 +1703,8 @@
22.426
22.427 /// \brief Runs the algorithm to visit all nodes in the digraph.
22.428 ///
22.429 - /// This method runs the %BFS algorithm in order to
22.430 - /// compute the shortest path to each node.
22.431 - ///
22.432 - /// The algorithm computes
22.433 - /// - the shortest path tree (forest),
22.434 - /// - the distance of each node from the root(s).
22.435 + /// This method runs the %BFS algorithm in order to visit all nodes
22.436 + /// in the digraph.
22.437 ///
22.438 /// \note <tt>b.run(s)</tt> is just a shortcut of the following code.
22.439 ///\code
22.440 @@ -1735,7 +1736,7 @@
22.441
22.442 ///@{
22.443
22.444 - /// \brief Checks if a node is reached from the root(s).
22.445 + /// \brief Checks if the given node is reached from the root(s).
22.446 ///
22.447 /// Returns \c true if \c v is reached from the root(s).
22.448 ///
23.1 --- a/lemon/bin_heap.h Tue Dec 20 17:44:38 2011 +0100
23.2 +++ b/lemon/bin_heap.h Tue Dec 20 18:15:14 2011 +0100
23.3 @@ -19,9 +19,9 @@
23.4 #ifndef LEMON_BIN_HEAP_H
23.5 #define LEMON_BIN_HEAP_H
23.6
23.7 -///\ingroup auxdat
23.8 +///\ingroup heaps
23.9 ///\file
23.10 -///\brief Binary Heap implementation.
23.11 +///\brief Binary heap implementation.
23.12
23.13 #include <vector>
23.14 #include <utility>
23.15 @@ -29,45 +29,41 @@
23.16
23.17 namespace lemon {
23.18
23.19 - ///\ingroup auxdat
23.20 + /// \ingroup heaps
23.21 ///
23.22 - ///\brief A Binary Heap implementation.
23.23 + /// \brief Binary heap data structure.
23.24 ///
23.25 - ///This class implements the \e binary \e heap data structure.
23.26 + /// This class implements the \e binary \e heap data structure.
23.27 + /// It fully conforms to the \ref concepts::Heap "heap concept".
23.28 ///
23.29 - ///A \e heap is a data structure for storing items with specified values
23.30 - ///called \e priorities in such a way that finding the item with minimum
23.31 - ///priority is efficient. \c CMP specifies the ordering of the priorities.
23.32 - ///In a heap one can change the priority of an item, add or erase an
23.33 - ///item, etc.
23.34 - ///
23.35 - ///\tparam PR Type of the priority of the items.
23.36 - ///\tparam IM A read and writable item map with int values, used internally
23.37 - ///to handle the cross references.
23.38 - ///\tparam CMP A functor class for the ordering of the priorities.
23.39 - ///The default is \c std::less<PR>.
23.40 - ///
23.41 - ///\sa FibHeap
23.42 - ///\sa Dijkstra
23.43 + /// \tparam PR Type of the priorities of the items.
23.44 + /// \tparam IM A read-writable item map with \c int values, used
23.45 + /// internally to handle the cross references.
23.46 + /// \tparam CMP A functor class for comparing the priorities.
23.47 + /// The default is \c std::less<PR>.
23.48 +#ifdef DOXYGEN
23.49 + template <typename PR, typename IM, typename CMP>
23.50 +#else
23.51 template <typename PR, typename IM, typename CMP = std::less<PR> >
23.52 +#endif
23.53 class BinHeap {
23.54 + public:
23.55
23.56 - public:
23.57 - ///\e
23.58 + /// Type of the item-int map.
23.59 typedef IM ItemIntMap;
23.60 - ///\e
23.61 + /// Type of the priorities.
23.62 typedef PR Prio;
23.63 - ///\e
23.64 + /// Type of the items stored in the heap.
23.65 typedef typename ItemIntMap::Key Item;
23.66 - ///\e
23.67 + /// Type of the item-priority pairs.
23.68 typedef std::pair<Item,Prio> Pair;
23.69 - ///\e
23.70 + /// Functor type for comparing the priorities.
23.71 typedef CMP Compare;
23.72
23.73 - /// \brief Type to represent the items states.
23.74 + /// \brief Type to represent the states of the items.
23.75 ///
23.76 - /// Each Item element have a state associated to it. It may be "in heap",
23.77 - /// "pre heap" or "post heap". The latter two are indifferent from the
23.78 + /// Each item has a state associated to it. It can be "in heap",
23.79 + /// "pre-heap" or "post-heap". The latter two are indifferent from the
23.80 /// heap's point of view, but may be useful to the user.
23.81 ///
23.82 /// The item-int map must be initialized in such way that it assigns
23.83 @@ -84,42 +80,43 @@
23.84 ItemIntMap &_iim;
23.85
23.86 public:
23.87 - /// \brief The constructor.
23.88 +
23.89 + /// \brief Constructor.
23.90 ///
23.91 - /// The constructor.
23.92 - /// \param map should be given to the constructor, since it is used
23.93 - /// internally to handle the cross references. The value of the map
23.94 - /// must be \c PRE_HEAP (<tt>-1</tt>) for every item.
23.95 + /// Constructor.
23.96 + /// \param map A map that assigns \c int values to the items.
23.97 + /// It is used internally to handle the cross references.
23.98 + /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
23.99 explicit BinHeap(ItemIntMap &map) : _iim(map) {}
23.100
23.101 - /// \brief The constructor.
23.102 + /// \brief Constructor.
23.103 ///
23.104 - /// The constructor.
23.105 - /// \param map should be given to the constructor, since it is used
23.106 - /// internally to handle the cross references. The value of the map
23.107 - /// should be PRE_HEAP (-1) for each element.
23.108 - ///
23.109 - /// \param comp The comparator function object.
23.110 + /// Constructor.
23.111 + /// \param map A map that assigns \c int values to the items.
23.112 + /// It is used internally to handle the cross references.
23.113 + /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
23.114 + /// \param comp The function object used for comparing the priorities.
23.115 BinHeap(ItemIntMap &map, const Compare &comp)
23.116 : _iim(map), _comp(comp) {}
23.117
23.118
23.119 - /// The number of items stored in the heap.
23.120 + /// \brief The number of items stored in the heap.
23.121 ///
23.122 - /// \brief Returns the number of items stored in the heap.
23.123 + /// This function returns the number of items stored in the heap.
23.124 int size() const { return _data.size(); }
23.125
23.126 - /// \brief Checks if the heap stores no items.
23.127 + /// \brief Check if the heap is empty.
23.128 ///
23.129 - /// Returns \c true if and only if the heap stores no items.
23.130 + /// This function returns \c true if the heap is empty.
23.131 bool empty() const { return _data.empty(); }
23.132
23.133 - /// \brief Make empty this heap.
23.134 + /// \brief Make the heap empty.
23.135 ///
23.136 - /// Make empty this heap. It does not change the cross reference map.
23.137 - /// If you want to reuse what is not surely empty you should first clear
23.138 - /// the heap and after that you should set the cross reference map for
23.139 - /// each item to \c PRE_HEAP.
23.140 + /// This functon makes the heap empty.
23.141 + /// It does not change the cross reference map. If you want to reuse
23.142 + /// a heap that is not surely empty, you should first clear it and
23.143 + /// then you should set the cross reference map to \c PRE_HEAP
23.144 + /// for each item.
23.145 void clear() {
23.146 _data.clear();
23.147 }
23.148 @@ -127,12 +124,12 @@
23.149 private:
23.150 static int parent(int i) { return (i-1)/2; }
23.151
23.152 - static int second_child(int i) { return 2*i+2; }
23.153 + static int secondChild(int i) { return 2*i+2; }
23.154 bool less(const Pair &p1, const Pair &p2) const {
23.155 return _comp(p1.second, p2.second);
23.156 }
23.157
23.158 - int bubble_up(int hole, Pair p) {
23.159 + int bubbleUp(int hole, Pair p) {
23.160 int par = parent(hole);
23.161 while( hole>0 && less(p,_data[par]) ) {
23.162 move(_data[par],hole);
23.163 @@ -143,8 +140,8 @@
23.164 return hole;
23.165 }
23.166
23.167 - int bubble_down(int hole, Pair p, int length) {
23.168 - int child = second_child(hole);
23.169 + int bubbleDown(int hole, Pair p, int length) {
23.170 + int child = secondChild(hole);
23.171 while(child < length) {
23.172 if( less(_data[child-1], _data[child]) ) {
23.173 --child;
23.174 @@ -153,7 +150,7 @@
23.175 goto ok;
23.176 move(_data[child], hole);
23.177 hole = child;
23.178 - child = second_child(hole);
23.179 + child = secondChild(hole);
23.180 }
23.181 child--;
23.182 if( child<length && less(_data[child], p) ) {
23.183 @@ -171,87 +168,91 @@
23.184 }
23.185
23.186 public:
23.187 +
23.188 /// \brief Insert a pair of item and priority into the heap.
23.189 ///
23.190 - /// Adds \c p.first to the heap with priority \c p.second.
23.191 + /// This function inserts \c p.first to the heap with priority
23.192 + /// \c p.second.
23.193 /// \param p The pair to insert.
23.194 + /// \pre \c p.first must not be stored in the heap.
23.195 void push(const Pair &p) {
23.196 int n = _data.size();
23.197 _data.resize(n+1);
23.198 - bubble_up(n, p);
23.199 + bubbleUp(n, p);
23.200 }
23.201
23.202 - /// \brief Insert an item into the heap with the given heap.
23.203 + /// \brief Insert an item into the heap with the given priority.
23.204 ///
23.205 - /// Adds \c i to the heap with priority \c p.
23.206 + /// This function inserts the given item into the heap with the
23.207 + /// given priority.
23.208 /// \param i The item to insert.
23.209 /// \param p The priority of the item.
23.210 + /// \pre \e i must not be stored in the heap.
23.211 void push(const Item &i, const Prio &p) { push(Pair(i,p)); }
23.212
23.213 - /// \brief Returns the item with minimum priority relative to \c Compare.
23.214 + /// \brief Return the item having minimum priority.
23.215 ///
23.216 - /// This method returns the item with minimum priority relative to \c
23.217 - /// Compare.
23.218 - /// \pre The heap must be nonempty.
23.219 + /// This function returns the item having minimum priority.
23.220 + /// \pre The heap must be non-empty.
23.221 Item top() const {
23.222 return _data[0].first;
23.223 }
23.224
23.225 - /// \brief Returns the minimum priority relative to \c Compare.
23.226 + /// \brief The minimum priority.
23.227 ///
23.228 - /// It returns the minimum priority relative to \c Compare.
23.229 - /// \pre The heap must be nonempty.
23.230 + /// This function returns the minimum priority.
23.231 + /// \pre The heap must be non-empty.
23.232 Prio prio() const {
23.233 return _data[0].second;
23.234 }
23.235
23.236 - /// \brief Deletes the item with minimum priority relative to \c Compare.
23.237 + /// \brief Remove the item having minimum priority.
23.238 ///
23.239 - /// This method deletes the item with minimum priority relative to \c
23.240 - /// Compare from the heap.
23.241 + /// This function removes the item having minimum priority.
23.242 /// \pre The heap must be non-empty.
23.243 void pop() {
23.244 int n = _data.size()-1;
23.245 _iim.set(_data[0].first, POST_HEAP);
23.246 if (n > 0) {
23.247 - bubble_down(0, _data[n], n);
23.248 + bubbleDown(0, _data[n], n);
23.249 }
23.250 _data.pop_back();
23.251 }
23.252
23.253 - /// \brief Deletes \c i from the heap.
23.254 + /// \brief Remove the given item from the heap.
23.255 ///
23.256 - /// This method deletes item \c i from the heap.
23.257 - /// \param i The item to erase.
23.258 - /// \pre The item should be in the heap.
23.259 + /// This function removes the given item from the heap if it is
23.260 + /// already stored.
23.261 + /// \param i The item to delete.
23.262 + /// \pre \e i must be in the heap.
23.263 void erase(const Item &i) {
23.264 int h = _iim[i];
23.265 int n = _data.size()-1;
23.266 _iim.set(_data[h].first, POST_HEAP);
23.267 if( h < n ) {
23.268 - if ( bubble_up(h, _data[n]) == h) {
23.269 - bubble_down(h, _data[n], n);
23.270 + if ( bubbleUp(h, _data[n]) == h) {
23.271 + bubbleDown(h, _data[n], n);
23.272 }
23.273 }
23.274 _data.pop_back();
23.275 }
23.276
23.277 -
23.278 - /// \brief Returns the priority of \c i.
23.279 + /// \brief The priority of the given item.
23.280 ///
23.281 - /// This function returns the priority of item \c i.
23.282 + /// This function returns the priority of the given item.
23.283 /// \param i The item.
23.284 - /// \pre \c i must be in the heap.
23.285 + /// \pre \e i must be in the heap.
23.286 Prio operator[](const Item &i) const {
23.287 int idx = _iim[i];
23.288 return _data[idx].second;
23.289 }
23.290
23.291 - /// \brief \c i gets to the heap with priority \c p independently
23.292 - /// if \c i was already there.
23.293 + /// \brief Set the priority of an item or insert it, if it is
23.294 + /// not stored in the heap.
23.295 ///
23.296 - /// This method calls \ref push(\c i, \c p) if \c i is not stored
23.297 - /// in the heap and sets the priority of \c i to \c p otherwise.
23.298 + /// This method sets the priority of the given item if it is
23.299 + /// already stored in the heap. Otherwise it inserts the given
23.300 + /// item into the heap with the given priority.
23.301 /// \param i The item.
23.302 /// \param p The priority.
23.303 void set(const Item &i, const Prio &p) {
23.304 @@ -260,44 +261,42 @@
23.305 push(i,p);
23.306 }
23.307 else if( _comp(p, _data[idx].second) ) {
23.308 - bubble_up(idx, Pair(i,p));
23.309 + bubbleUp(idx, Pair(i,p));
23.310 }
23.311 else {
23.312 - bubble_down(idx, Pair(i,p), _data.size());
23.313 + bubbleDown(idx, Pair(i,p), _data.size());
23.314 }
23.315 }
23.316
23.317 - /// \brief Decreases the priority of \c i to \c p.
23.318 + /// \brief Decrease the priority of an item to the given value.
23.319 ///
23.320 - /// This method decreases the priority of item \c i to \c p.
23.321 + /// This function decreases the priority of an item to the given value.
23.322 /// \param i The item.
23.323 /// \param p The priority.
23.324 - /// \pre \c i must be stored in the heap with priority at least \c
23.325 - /// p relative to \c Compare.
23.326 + /// \pre \e i must be stored in the heap with priority at least \e p.
23.327 void decrease(const Item &i, const Prio &p) {
23.328 int idx = _iim[i];
23.329 - bubble_up(idx, Pair(i,p));
23.330 + bubbleUp(idx, Pair(i,p));
23.331 }
23.332
23.333 - /// \brief Increases the priority of \c i to \c p.
23.334 + /// \brief Increase the priority of an item to the given value.
23.335 ///
23.336 - /// This method sets the priority of item \c i to \c p.
23.337 + /// This function increases the priority of an item to the given value.
23.338 /// \param i The item.
23.339 /// \param p The priority.
23.340 - /// \pre \c i must be stored in the heap with priority at most \c
23.341 - /// p relative to \c Compare.
23.342 + /// \pre \e i must be stored in the heap with priority at most \e p.
23.343 void increase(const Item &i, const Prio &p) {
23.344 int idx = _iim[i];
23.345 - bubble_down(idx, Pair(i,p), _data.size());
23.346 + bubbleDown(idx, Pair(i,p), _data.size());
23.347 }
23.348
23.349 - /// \brief Returns if \c item is in, has already been in, or has
23.350 - /// never been in the heap.
23.351 + /// \brief Return the state of an item.
23.352 ///
23.353 - /// This method returns PRE_HEAP if \c item has never been in the
23.354 - /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
23.355 - /// otherwise. In the latter case it is possible that \c item will
23.356 - /// get back to the heap again.
23.357 + /// This method returns \c PRE_HEAP if the given item has never
23.358 + /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
23.359 + /// and \c POST_HEAP otherwise.
23.360 + /// In the latter case it is possible that the item will get back
23.361 + /// to the heap again.
23.362 /// \param i The item.
23.363 State state(const Item &i) const {
23.364 int s = _iim[i];
23.365 @@ -306,11 +305,11 @@
23.366 return State(s);
23.367 }
23.368
23.369 - /// \brief Sets the state of the \c item in the heap.
23.370 + /// \brief Set the state of an item in the heap.
23.371 ///
23.372 - /// Sets the state of the \c item in the heap. It can be used to
23.373 - /// manually clear the heap when it is important to achive the
23.374 - /// better time complexity.
23.375 + /// This function sets the state of the given item in the heap.
23.376 + /// It can be used to manually clear the heap when it is important
23.377 + /// to achive better time complexity.
23.378 /// \param i The item.
23.379 /// \param st The state. It should not be \c IN_HEAP.
23.380 void state(const Item& i, State st) {
23.381 @@ -327,12 +326,13 @@
23.382 }
23.383 }
23.384
23.385 - /// \brief Replaces an item in the heap.
23.386 + /// \brief Replace an item in the heap.
23.387 ///
23.388 - /// The \c i item is replaced with \c j item. The \c i item should
23.389 - /// be in the heap, while the \c j should be out of the heap. The
23.390 - /// \c i item will out of the heap and \c j will be in the heap
23.391 - /// with the same prioriority as prevoiusly the \c i item.
23.392 + /// This function replaces item \c i with item \c j.
23.393 + /// Item \c i must be in the heap, while \c j must be out of the heap.
23.394 + /// After calling this method, item \c i will be out of the
23.395 + /// heap and \c j will be in the heap with the same prioriority
23.396 + /// as item \c i had before.
23.397 void replace(const Item& i, const Item& j) {
23.398 int idx = _iim[i];
23.399 _iim.set(i, _iim[j]);
24.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
24.2 +++ b/lemon/binomial_heap.h Tue Dec 20 18:15:14 2011 +0100
24.3 @@ -0,0 +1,445 @@
24.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
24.5 + *
24.6 + * This file is a part of LEMON, a generic C++ optimization library.
24.7 + *
24.8 + * Copyright (C) 2003-2010
24.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
24.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
24.11 + *
24.12 + * Permission to use, modify and distribute this software is granted
24.13 + * provided that this copyright notice appears in all copies. For
24.14 + * precise terms see the accompanying LICENSE file.
24.15 + *
24.16 + * This software is provided "AS IS" with no warranty of any kind,
24.17 + * express or implied, and with no claim as to its suitability for any
24.18 + * purpose.
24.19 + *
24.20 + */
24.21 +
24.22 +#ifndef LEMON_BINOMIAL_HEAP_H
24.23 +#define LEMON_BINOMIAL_HEAP_H
24.24 +
24.25 +///\file
24.26 +///\ingroup heaps
24.27 +///\brief Binomial Heap implementation.
24.28 +
24.29 +#include <vector>
24.30 +#include <utility>
24.31 +#include <functional>
24.32 +#include <lemon/math.h>
24.33 +#include <lemon/counter.h>
24.34 +
24.35 +namespace lemon {
24.36 +
24.37 + /// \ingroup heaps
24.38 + ///
24.39 + ///\brief Binomial heap data structure.
24.40 + ///
24.41 + /// This class implements the \e binomial \e heap data structure.
24.42 + /// It fully conforms to the \ref concepts::Heap "heap concept".
24.43 + ///
24.44 + /// The methods \ref increase() and \ref erase() are not efficient
24.45 + /// in a binomial heap. In case of many calls of these operations,
24.46 + /// it is better to use other heap structure, e.g. \ref BinHeap
24.47 + /// "binary heap".
24.48 + ///
24.49 + /// \tparam PR Type of the priorities of the items.
24.50 + /// \tparam IM A read-writable item map with \c int values, used
24.51 + /// internally to handle the cross references.
24.52 + /// \tparam CMP A functor class for comparing the priorities.
24.53 + /// The default is \c std::less<PR>.
24.54 +#ifdef DOXYGEN
24.55 + template <typename PR, typename IM, typename CMP>
24.56 +#else
24.57 + template <typename PR, typename IM, typename CMP = std::less<PR> >
24.58 +#endif
24.59 + class BinomialHeap {
24.60 + public:
24.61 + /// Type of the item-int map.
24.62 + typedef IM ItemIntMap;
24.63 + /// Type of the priorities.
24.64 + typedef PR Prio;
24.65 + /// Type of the items stored in the heap.
24.66 + typedef typename ItemIntMap::Key Item;
24.67 + /// Functor type for comparing the priorities.
24.68 + typedef CMP Compare;
24.69 +
24.70 + /// \brief Type to represent the states of the items.
24.71 + ///
24.72 + /// Each item has a state associated to it. It can be "in heap",
24.73 + /// "pre-heap" or "post-heap". The latter two are indifferent from the
24.74 + /// heap's point of view, but may be useful to the user.
24.75 + ///
24.76 + /// The item-int map must be initialized in such way that it assigns
24.77 + /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
24.78 + enum State {
24.79 + IN_HEAP = 0, ///< = 0.
24.80 + PRE_HEAP = -1, ///< = -1.
24.81 + POST_HEAP = -2 ///< = -2.
24.82 + };
24.83 +
24.84 + private:
24.85 + class Store;
24.86 +
24.87 + std::vector<Store> _data;
24.88 + int _min, _head;
24.89 + ItemIntMap &_iim;
24.90 + Compare _comp;
24.91 + int _num_items;
24.92 +
24.93 + public:
24.94 + /// \brief Constructor.
24.95 + ///
24.96 + /// Constructor.
24.97 + /// \param map A map that assigns \c int values to the items.
24.98 + /// It is used internally to handle the cross references.
24.99 + /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
24.100 + explicit BinomialHeap(ItemIntMap &map)
24.101 + : _min(0), _head(-1), _iim(map), _num_items(0) {}
24.102 +
24.103 + /// \brief Constructor.
24.104 + ///
24.105 + /// Constructor.
24.106 + /// \param map A map that assigns \c int values to the items.
24.107 + /// It is used internally to handle the cross references.
24.108 + /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
24.109 + /// \param comp The function object used for comparing the priorities.
24.110 + BinomialHeap(ItemIntMap &map, const Compare &comp)
24.111 + : _min(0), _head(-1), _iim(map), _comp(comp), _num_items(0) {}
24.112 +
24.113 + /// \brief The number of items stored in the heap.
24.114 + ///
24.115 + /// This function returns the number of items stored in the heap.
24.116 + int size() const { return _num_items; }
24.117 +
24.118 + /// \brief Check if the heap is empty.
24.119 + ///
24.120 + /// This function returns \c true if the heap is empty.
24.121 + bool empty() const { return _num_items==0; }
24.122 +
24.123 + /// \brief Make the heap empty.
24.124 + ///
24.125 + /// This functon makes the heap empty.
24.126 + /// It does not change the cross reference map. If you want to reuse
24.127 + /// a heap that is not surely empty, you should first clear it and
24.128 + /// then you should set the cross reference map to \c PRE_HEAP
24.129 + /// for each item.
24.130 + void clear() {
24.131 + _data.clear(); _min=0; _num_items=0; _head=-1;
24.132 + }
24.133 +
24.134 + /// \brief Set the priority of an item or insert it, if it is
24.135 + /// not stored in the heap.
24.136 + ///
24.137 + /// This method sets the priority of the given item if it is
24.138 + /// already stored in the heap. Otherwise it inserts the given
24.139 + /// item into the heap with the given priority.
24.140 + /// \param item The item.
24.141 + /// \param value The priority.
24.142 + void set (const Item& item, const Prio& value) {
24.143 + int i=_iim[item];
24.144 + if ( i >= 0 && _data[i].in ) {
24.145 + if ( _comp(value, _data[i].prio) ) decrease(item, value);
24.146 + if ( _comp(_data[i].prio, value) ) increase(item, value);
24.147 + } else push(item, value);
24.148 + }
24.149 +
24.150 + /// \brief Insert an item into the heap with the given priority.
24.151 + ///
24.152 + /// This function inserts the given item into the heap with the
24.153 + /// given priority.
24.154 + /// \param item The item to insert.
24.155 + /// \param value The priority of the item.
24.156 + /// \pre \e item must not be stored in the heap.
24.157 + void push (const Item& item, const Prio& value) {
24.158 + int i=_iim[item];
24.159 + if ( i<0 ) {
24.160 + int s=_data.size();
24.161 + _iim.set( item,s );
24.162 + Store st;
24.163 + st.name=item;
24.164 + st.prio=value;
24.165 + _data.push_back(st);
24.166 + i=s;
24.167 + }
24.168 + else {
24.169 + _data[i].parent=_data[i].right_neighbor=_data[i].child=-1;
24.170 + _data[i].degree=0;
24.171 + _data[i].in=true;
24.172 + _data[i].prio=value;
24.173 + }
24.174 +
24.175 + if( 0==_num_items ) {
24.176 + _head=i;
24.177 + _min=i;
24.178 + } else {
24.179 + merge(i);
24.180 + if( _comp(_data[i].prio, _data[_min].prio) ) _min=i;
24.181 + }
24.182 + ++_num_items;
24.183 + }
24.184 +
24.185 + /// \brief Return the item having minimum priority.
24.186 + ///
24.187 + /// This function returns the item having minimum priority.
24.188 + /// \pre The heap must be non-empty.
24.189 + Item top() const { return _data[_min].name; }
24.190 +
24.191 + /// \brief The minimum priority.
24.192 + ///
24.193 + /// This function returns the minimum priority.
24.194 + /// \pre The heap must be non-empty.
24.195 + Prio prio() const { return _data[_min].prio; }
24.196 +
24.197 + /// \brief The priority of the given item.
24.198 + ///
24.199 + /// This function returns the priority of the given item.
24.200 + /// \param item The item.
24.201 + /// \pre \e item must be in the heap.
24.202 + const Prio& operator[](const Item& item) const {
24.203 + return _data[_iim[item]].prio;
24.204 + }
24.205 +
24.206 + /// \brief Remove the item having minimum priority.
24.207 + ///
24.208 + /// This function removes the item having minimum priority.
24.209 + /// \pre The heap must be non-empty.
24.210 + void pop() {
24.211 + _data[_min].in=false;
24.212 +
24.213 + int head_child=-1;
24.214 + if ( _data[_min].child!=-1 ) {
24.215 + int child=_data[_min].child;
24.216 + int neighb;
24.217 + while( child!=-1 ) {
24.218 + neighb=_data[child].right_neighbor;
24.219 + _data[child].parent=-1;
24.220 + _data[child].right_neighbor=head_child;
24.221 + head_child=child;
24.222 + child=neighb;
24.223 + }
24.224 + }
24.225 +
24.226 + if ( _data[_head].right_neighbor==-1 ) {
24.227 + // there was only one root
24.228 + _head=head_child;
24.229 + }
24.230 + else {
24.231 + // there were more roots
24.232 + if( _head!=_min ) { unlace(_min); }
24.233 + else { _head=_data[_head].right_neighbor; }
24.234 + merge(head_child);
24.235 + }
24.236 + _min=findMin();
24.237 + --_num_items;
24.238 + }
24.239 +
24.240 + /// \brief Remove the given item from the heap.
24.241 + ///
24.242 + /// This function removes the given item from the heap if it is
24.243 + /// already stored.
24.244 + /// \param item The item to delete.
24.245 + /// \pre \e item must be in the heap.
24.246 + void erase (const Item& item) {
24.247 + int i=_iim[item];
24.248 + if ( i >= 0 && _data[i].in ) {
24.249 + decrease( item, _data[_min].prio-1 );
24.250 + pop();
24.251 + }
24.252 + }
24.253 +
24.254 + /// \brief Decrease the priority of an item to the given value.
24.255 + ///
24.256 + /// This function decreases the priority of an item to the given value.
24.257 + /// \param item The item.
24.258 + /// \param value The priority.
24.259 + /// \pre \e item must be stored in the heap with priority at least \e value.
24.260 + void decrease (Item item, const Prio& value) {
24.261 + int i=_iim[item];
24.262 + int p=_data[i].parent;
24.263 + _data[i].prio=value;
24.264 +
24.265 + while( p!=-1 && _comp(value, _data[p].prio) ) {
24.266 + _data[i].name=_data[p].name;
24.267 + _data[i].prio=_data[p].prio;
24.268 + _data[p].name=item;
24.269 + _data[p].prio=value;
24.270 + _iim[_data[i].name]=i;
24.271 + i=p;
24.272 + p=_data[p].parent;
24.273 + }
24.274 + _iim[item]=i;
24.275 + if ( _comp(value, _data[_min].prio) ) _min=i;
24.276 + }
24.277 +
24.278 + /// \brief Increase the priority of an item to the given value.
24.279 + ///
24.280 + /// This function increases the priority of an item to the given value.
24.281 + /// \param item The item.
24.282 + /// \param value The priority.
24.283 + /// \pre \e item must be stored in the heap with priority at most \e value.
24.284 + void increase (Item item, const Prio& value) {
24.285 + erase(item);
24.286 + push(item, value);
24.287 + }
24.288 +
24.289 + /// \brief Return the state of an item.
24.290 + ///
24.291 + /// This method returns \c PRE_HEAP if the given item has never
24.292 + /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
24.293 + /// and \c POST_HEAP otherwise.
24.294 + /// In the latter case it is possible that the item will get back
24.295 + /// to the heap again.
24.296 + /// \param item The item.
24.297 + State state(const Item &item) const {
24.298 + int i=_iim[item];
24.299 + if( i>=0 ) {
24.300 + if ( _data[i].in ) i=0;
24.301 + else i=-2;
24.302 + }
24.303 + return State(i);
24.304 + }
24.305 +
24.306 + /// \brief Set the state of an item in the heap.
24.307 + ///
24.308 + /// This function sets the state of the given item in the heap.
24.309 + /// It can be used to manually clear the heap when it is important
24.310 + /// to achive better time complexity.
24.311 + /// \param i The item.
24.312 + /// \param st The state. It should not be \c IN_HEAP.
24.313 + void state(const Item& i, State st) {
24.314 + switch (st) {
24.315 + case POST_HEAP:
24.316 + case PRE_HEAP:
24.317 + if (state(i) == IN_HEAP) {
24.318 + erase(i);
24.319 + }
24.320 + _iim[i] = st;
24.321 + break;
24.322 + case IN_HEAP:
24.323 + break;
24.324 + }
24.325 + }
24.326 +
24.327 + private:
24.328 +
24.329 + // Find the minimum of the roots
24.330 + int findMin() {
24.331 + if( _head!=-1 ) {
24.332 + int min_loc=_head, min_val=_data[_head].prio;
24.333 + for( int x=_data[_head].right_neighbor; x!=-1;
24.334 + x=_data[x].right_neighbor ) {
24.335 + if( _comp( _data[x].prio,min_val ) ) {
24.336 + min_val=_data[x].prio;
24.337 + min_loc=x;
24.338 + }
24.339 + }
24.340 + return min_loc;
24.341 + }
24.342 + else return -1;
24.343 + }
24.344 +
24.345 + // Merge the heap with another heap starting at the given position
24.346 + void merge(int a) {
24.347 + if( _head==-1 || a==-1 ) return;
24.348 + if( _data[a].right_neighbor==-1 &&
24.349 + _data[a].degree<=_data[_head].degree ) {
24.350 + _data[a].right_neighbor=_head;
24.351 + _head=a;
24.352 + } else {
24.353 + interleave(a);
24.354 + }
24.355 + if( _data[_head].right_neighbor==-1 ) return;
24.356 +
24.357 + int x=_head;
24.358 + int x_prev=-1, x_next=_data[x].right_neighbor;
24.359 + while( x_next!=-1 ) {
24.360 + if( _data[x].degree!=_data[x_next].degree ||
24.361 + ( _data[x_next].right_neighbor!=-1 &&
24.362 + _data[_data[x_next].right_neighbor].degree==_data[x].degree ) ) {
24.363 + x_prev=x;
24.364 + x=x_next;
24.365 + }
24.366 + else {
24.367 + if( _comp(_data[x_next].prio,_data[x].prio) ) {
24.368 + if( x_prev==-1 ) {
24.369 + _head=x_next;
24.370 + } else {
24.371 + _data[x_prev].right_neighbor=x_next;
24.372 + }
24.373 + fuse(x,x_next);
24.374 + x=x_next;
24.375 + }
24.376 + else {
24.377 + _data[x].right_neighbor=_data[x_next].right_neighbor;
24.378 + fuse(x_next,x);
24.379 + }
24.380 + }
24.381 + x_next=_data[x].right_neighbor;
24.382 + }
24.383 + }
24.384 +
24.385 + // Interleave the elements of the given list into the list of the roots
24.386 + void interleave(int a) {
24.387 + int p=_head, q=a;
24.388 + int curr=_data.size();
24.389 + _data.push_back(Store());
24.390 +
24.391 + while( p!=-1 || q!=-1 ) {
24.392 + if( q==-1 || ( p!=-1 && _data[p].degree<_data[q].degree ) ) {
24.393 + _data[curr].right_neighbor=p;
24.394 + curr=p;
24.395 + p=_data[p].right_neighbor;
24.396 + }
24.397 + else {
24.398 + _data[curr].right_neighbor=q;
24.399 + curr=q;
24.400 + q=_data[q].right_neighbor;
24.401 + }
24.402 + }
24.403 +
24.404 + _head=_data.back().right_neighbor;
24.405 + _data.pop_back();
24.406 + }
24.407 +
24.408 + // Lace node a under node b
24.409 + void fuse(int a, int b) {
24.410 + _data[a].parent=b;
24.411 + _data[a].right_neighbor=_data[b].child;
24.412 + _data[b].child=a;
24.413 +
24.414 + ++_data[b].degree;
24.415 + }
24.416 +
24.417 + // Unlace node a (if it has siblings)
24.418 + void unlace(int a) {
24.419 + int neighb=_data[a].right_neighbor;
24.420 + int other=_head;
24.421 +
24.422 + while( _data[other].right_neighbor!=a )
24.423 + other=_data[other].right_neighbor;
24.424 + _data[other].right_neighbor=neighb;
24.425 + }
24.426 +
24.427 + private:
24.428 +
24.429 + class Store {
24.430 + friend class BinomialHeap;
24.431 +
24.432 + Item name;
24.433 + int parent;
24.434 + int right_neighbor;
24.435 + int child;
24.436 + int degree;
24.437 + bool in;
24.438 + Prio prio;
24.439 +
24.440 + Store() : parent(-1), right_neighbor(-1), child(-1), degree(0),
24.441 + in(true) {}
24.442 + };
24.443 + };
24.444 +
24.445 +} //namespace lemon
24.446 +
24.447 +#endif //LEMON_BINOMIAL_HEAP_H
24.448 +
25.1 --- a/lemon/bits/array_map.h Tue Dec 20 17:44:38 2011 +0100
25.2 +++ b/lemon/bits/array_map.h Tue Dec 20 18:15:14 2011 +0100
25.3 @@ -2,7 +2,7 @@
25.4 *
25.5 * This file is a part of LEMON, a generic C++ optimization library.
25.6 *
25.7 - * Copyright (C) 2003-2009
25.8 + * Copyright (C) 2003-2010
25.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
25.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
25.11 *
25.12 @@ -70,7 +70,7 @@
25.13 typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier;
25.14
25.15 private:
25.16 -
25.17 +
25.18 // The MapBase of the Map which imlements the core regisitry function.
25.19 typedef typename Notifier::ObserverBase Parent;
25.20
26.1 --- a/lemon/bits/default_map.h Tue Dec 20 17:44:38 2011 +0100
26.2 +++ b/lemon/bits/default_map.h Tue Dec 20 18:15:14 2011 +0100
26.3 @@ -2,7 +2,7 @@
26.4 *
26.5 * This file is a part of LEMON, a generic C++ optimization library.
26.6 *
26.7 - * Copyright (C) 2003-2009
26.8 + * Copyright (C) 2003-2010
26.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
26.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
26.11 *
26.12 @@ -157,7 +157,7 @@
26.13
26.14 public:
26.15 typedef DefaultMap<_Graph, _Item, _Value> Map;
26.16 -
26.17 +
26.18 typedef typename Parent::GraphType GraphType;
26.19 typedef typename Parent::Value Value;
26.20
27.1 --- a/lemon/bits/edge_set_extender.h Tue Dec 20 17:44:38 2011 +0100
27.2 +++ b/lemon/bits/edge_set_extender.h Tue Dec 20 18:15:14 2011 +0100
27.3 @@ -1,8 +1,8 @@
27.4 -/* -*- C++ -*-
27.5 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
27.6 *
27.7 - * This file is a part of LEMON, a generic C++ optimization library
27.8 + * This file is a part of LEMON, a generic C++ optimization library.
27.9 *
27.10 - * Copyright (C) 2003-2008
27.11 + * Copyright (C) 2003-2010
27.12 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
27.13 * (Egervary Research Group on Combinatorial Optimization, EGRES).
27.14 *
27.15 @@ -63,11 +63,11 @@
27.16
27.17 Node oppositeNode(const Node &n, const Arc &e) const {
27.18 if (n == Parent::source(e))
27.19 - return Parent::target(e);
27.20 + return Parent::target(e);
27.21 else if(n==Parent::target(e))
27.22 - return Parent::source(e);
27.23 + return Parent::source(e);
27.24 else
27.25 - return INVALID;
27.26 + return INVALID;
27.27 }
27.28
27.29
27.30 @@ -91,7 +91,7 @@
27.31
27.32 // Iterable extensions
27.33
27.34 - class NodeIt : public Node {
27.35 + class NodeIt : public Node {
27.36 const Digraph* digraph;
27.37 public:
27.38
27.39 @@ -100,21 +100,21 @@
27.40 NodeIt(Invalid i) : Node(i) { }
27.41
27.42 explicit NodeIt(const Digraph& _graph) : digraph(&_graph) {
27.43 - _graph.first(static_cast<Node&>(*this));
27.44 + _graph.first(static_cast<Node&>(*this));
27.45 }
27.46
27.47 - NodeIt(const Digraph& _graph, const Node& node)
27.48 - : Node(node), digraph(&_graph) {}
27.49 + NodeIt(const Digraph& _graph, const Node& node)
27.50 + : Node(node), digraph(&_graph) {}
27.51
27.52 - NodeIt& operator++() {
27.53 - digraph->next(*this);
27.54 - return *this;
27.55 + NodeIt& operator++() {
27.56 + digraph->next(*this);
27.57 + return *this;
27.58 }
27.59
27.60 };
27.61
27.62
27.63 - class ArcIt : public Arc {
27.64 + class ArcIt : public Arc {
27.65 const Digraph* digraph;
27.66 public:
27.67
27.68 @@ -123,21 +123,21 @@
27.69 ArcIt(Invalid i) : Arc(i) { }
27.70
27.71 explicit ArcIt(const Digraph& _graph) : digraph(&_graph) {
27.72 - _graph.first(static_cast<Arc&>(*this));
27.73 + _graph.first(static_cast<Arc&>(*this));
27.74 }
27.75
27.76 - ArcIt(const Digraph& _graph, const Arc& e) :
27.77 - Arc(e), digraph(&_graph) { }
27.78 + ArcIt(const Digraph& _graph, const Arc& e) :
27.79 + Arc(e), digraph(&_graph) { }
27.80
27.81 - ArcIt& operator++() {
27.82 - digraph->next(*this);
27.83 - return *this;
27.84 + ArcIt& operator++() {
27.85 + digraph->next(*this);
27.86 + return *this;
27.87 }
27.88
27.89 };
27.90
27.91
27.92 - class OutArcIt : public Arc {
27.93 + class OutArcIt : public Arc {
27.94 const Digraph* digraph;
27.95 public:
27.96
27.97 @@ -145,23 +145,23 @@
27.98
27.99 OutArcIt(Invalid i) : Arc(i) { }
27.100
27.101 - OutArcIt(const Digraph& _graph, const Node& node)
27.102 - : digraph(&_graph) {
27.103 - _graph.firstOut(*this, node);
27.104 + OutArcIt(const Digraph& _graph, const Node& node)
27.105 + : digraph(&_graph) {
27.106 + _graph.firstOut(*this, node);
27.107 }
27.108
27.109 - OutArcIt(const Digraph& _graph, const Arc& arc)
27.110 - : Arc(arc), digraph(&_graph) {}
27.111 + OutArcIt(const Digraph& _graph, const Arc& arc)
27.112 + : Arc(arc), digraph(&_graph) {}
27.113
27.114 - OutArcIt& operator++() {
27.115 - digraph->nextOut(*this);
27.116 - return *this;
27.117 + OutArcIt& operator++() {
27.118 + digraph->nextOut(*this);
27.119 + return *this;
27.120 }
27.121
27.122 };
27.123
27.124
27.125 - class InArcIt : public Arc {
27.126 + class InArcIt : public Arc {
27.127 const Digraph* digraph;
27.128 public:
27.129
27.130 @@ -169,17 +169,17 @@
27.131
27.132 InArcIt(Invalid i) : Arc(i) { }
27.133
27.134 - InArcIt(const Digraph& _graph, const Node& node)
27.135 - : digraph(&_graph) {
27.136 - _graph.firstIn(*this, node);
27.137 + InArcIt(const Digraph& _graph, const Node& node)
27.138 + : digraph(&_graph) {
27.139 + _graph.firstIn(*this, node);
27.140 }
27.141
27.142 - InArcIt(const Digraph& _graph, const Arc& arc) :
27.143 - Arc(arc), digraph(&_graph) {}
27.144 + InArcIt(const Digraph& _graph, const Arc& arc) :
27.145 + Arc(arc), digraph(&_graph) {}
27.146
27.147 - InArcIt& operator++() {
27.148 - digraph->nextIn(*this);
27.149 - return *this;
27.150 + InArcIt& operator++() {
27.151 + digraph->nextIn(*this);
27.152 + return *this;
27.153 }
27.154
27.155 };
27.156 @@ -215,26 +215,26 @@
27.157 using Parent::first;
27.158
27.159 // Mappable extension
27.160 -
27.161 +
27.162 template <typename _Value>
27.163 - class ArcMap
27.164 + class ArcMap
27.165 : public MapExtender<DefaultMap<Digraph, Arc, _Value> > {
27.166 typedef MapExtender<DefaultMap<Digraph, Arc, _Value> > Parent;
27.167
27.168 public:
27.169 - explicit ArcMap(const Digraph& _g)
27.170 - : Parent(_g) {}
27.171 - ArcMap(const Digraph& _g, const _Value& _v)
27.172 - : Parent(_g, _v) {}
27.173 + explicit ArcMap(const Digraph& _g)
27.174 + : Parent(_g) {}
27.175 + ArcMap(const Digraph& _g, const _Value& _v)
27.176 + : Parent(_g, _v) {}
27.177
27.178 ArcMap& operator=(const ArcMap& cmap) {
27.179 - return operator=<ArcMap>(cmap);
27.180 + return operator=<ArcMap>(cmap);
27.181 }
27.182
27.183 template <typename CMap>
27.184 ArcMap& operator=(const CMap& cmap) {
27.185 Parent::operator=(cmap);
27.186 - return *this;
27.187 + return *this;
27.188 }
27.189
27.190 };
27.191 @@ -247,7 +247,7 @@
27.192 notifier(Arc()).add(arc);
27.193 return arc;
27.194 }
27.195 -
27.196 +
27.197 void clear() {
27.198 notifier(Arc()).clear();
27.199 Parent::clear();
27.200 @@ -312,11 +312,11 @@
27.201
27.202 Node oppositeNode(const Node &n, const Edge &e) const {
27.203 if( n == Parent::u(e))
27.204 - return Parent::v(e);
27.205 + return Parent::v(e);
27.206 else if( n == Parent::v(e))
27.207 - return Parent::u(e);
27.208 + return Parent::u(e);
27.209 else
27.210 - return INVALID;
27.211 + return INVALID;
27.212 }
27.213
27.214 Arc oppositeArc(const Arc &e) const {
27.215 @@ -340,7 +340,7 @@
27.216 public:
27.217
27.218 using Parent::notifier;
27.219 -
27.220 +
27.221 ArcNotifier& notifier(Arc) const {
27.222 return arc_notifier;
27.223 }
27.224 @@ -350,7 +350,7 @@
27.225 }
27.226
27.227
27.228 - class NodeIt : public Node {
27.229 + class NodeIt : public Node {
27.230 const Graph* graph;
27.231 public:
27.232
27.233 @@ -359,21 +359,21 @@
27.234 NodeIt(Invalid i) : Node(i) { }
27.235
27.236 explicit NodeIt(const Graph& _graph) : graph(&_graph) {
27.237 - _graph.first(static_cast<Node&>(*this));
27.238 + _graph.first(static_cast<Node&>(*this));
27.239 }
27.240
27.241 - NodeIt(const Graph& _graph, const Node& node)
27.242 - : Node(node), graph(&_graph) {}
27.243 + NodeIt(const Graph& _graph, const Node& node)
27.244 + : Node(node), graph(&_graph) {}
27.245
27.246 - NodeIt& operator++() {
27.247 - graph->next(*this);
27.248 - return *this;
27.249 + NodeIt& operator++() {
27.250 + graph->next(*this);
27.251 + return *this;
27.252 }
27.253
27.254 };
27.255
27.256
27.257 - class ArcIt : public Arc {
27.258 + class ArcIt : public Arc {
27.259 const Graph* graph;
27.260 public:
27.261
27.262 @@ -382,21 +382,21 @@
27.263 ArcIt(Invalid i) : Arc(i) { }
27.264
27.265 explicit ArcIt(const Graph& _graph) : graph(&_graph) {
27.266 - _graph.first(static_cast<Arc&>(*this));
27.267 + _graph.first(static_cast<Arc&>(*this));
27.268 }
27.269
27.270 - ArcIt(const Graph& _graph, const Arc& e) :
27.271 - Arc(e), graph(&_graph) { }
27.272 + ArcIt(const Graph& _graph, const Arc& e) :
27.273 + Arc(e), graph(&_graph) { }
27.274
27.275 - ArcIt& operator++() {
27.276 - graph->next(*this);
27.277 - return *this;
27.278 + ArcIt& operator++() {
27.279 + graph->next(*this);
27.280 + return *this;
27.281 }
27.282
27.283 };
27.284
27.285
27.286 - class OutArcIt : public Arc {
27.287 + class OutArcIt : public Arc {
27.288 const Graph* graph;
27.289 public:
27.290
27.291 @@ -404,23 +404,23 @@
27.292
27.293 OutArcIt(Invalid i) : Arc(i) { }
27.294
27.295 - OutArcIt(const Graph& _graph, const Node& node)
27.296 - : graph(&_graph) {
27.297 - _graph.firstOut(*this, node);
27.298 + OutArcIt(const Graph& _graph, const Node& node)
27.299 + : graph(&_graph) {
27.300 + _graph.firstOut(*this, node);
27.301 }
27.302
27.303 - OutArcIt(const Graph& _graph, const Arc& arc)
27.304 - : Arc(arc), graph(&_graph) {}
27.305 + OutArcIt(const Graph& _graph, const Arc& arc)
27.306 + : Arc(arc), graph(&_graph) {}
27.307
27.308 - OutArcIt& operator++() {
27.309 - graph->nextOut(*this);
27.310 - return *this;
27.311 + OutArcIt& operator++() {
27.312 + graph->nextOut(*this);
27.313 + return *this;
27.314 }
27.315
27.316 };
27.317
27.318
27.319 - class InArcIt : public Arc {
27.320 + class InArcIt : public Arc {
27.321 const Graph* graph;
27.322 public:
27.323
27.324 @@ -428,23 +428,23 @@
27.325
27.326 InArcIt(Invalid i) : Arc(i) { }
27.327
27.328 - InArcIt(const Graph& _graph, const Node& node)
27.329 - : graph(&_graph) {
27.330 - _graph.firstIn(*this, node);
27.331 + InArcIt(const Graph& _graph, const Node& node)
27.332 + : graph(&_graph) {
27.333 + _graph.firstIn(*this, node);
27.334 }
27.335
27.336 - InArcIt(const Graph& _graph, const Arc& arc) :
27.337 - Arc(arc), graph(&_graph) {}
27.338 + InArcIt(const Graph& _graph, const Arc& arc) :
27.339 + Arc(arc), graph(&_graph) {}
27.340
27.341 - InArcIt& operator++() {
27.342 - graph->nextIn(*this);
27.343 - return *this;
27.344 + InArcIt& operator++() {
27.345 + graph->nextIn(*this);
27.346 + return *this;
27.347 }
27.348
27.349 };
27.350
27.351
27.352 - class EdgeIt : public Parent::Edge {
27.353 + class EdgeIt : public Parent::Edge {
27.354 const Graph* graph;
27.355 public:
27.356
27.357 @@ -453,15 +453,15 @@
27.358 EdgeIt(Invalid i) : Edge(i) { }
27.359
27.360 explicit EdgeIt(const Graph& _graph) : graph(&_graph) {
27.361 - _graph.first(static_cast<Edge&>(*this));
27.362 + _graph.first(static_cast<Edge&>(*this));
27.363 }
27.364
27.365 - EdgeIt(const Graph& _graph, const Edge& e) :
27.366 - Edge(e), graph(&_graph) { }
27.367 + EdgeIt(const Graph& _graph, const Edge& e) :
27.368 + Edge(e), graph(&_graph) { }
27.369
27.370 - EdgeIt& operator++() {
27.371 - graph->next(*this);
27.372 - return *this;
27.373 + EdgeIt& operator++() {
27.374 + graph->next(*this);
27.375 + return *this;
27.376 }
27.377
27.378 };
27.379 @@ -477,17 +477,17 @@
27.380 IncEdgeIt(Invalid i) : Edge(i), direction(false) { }
27.381
27.382 IncEdgeIt(const Graph& _graph, const Node &n) : graph(&_graph) {
27.383 - _graph.firstInc(*this, direction, n);
27.384 + _graph.firstInc(*this, direction, n);
27.385 }
27.386
27.387 IncEdgeIt(const Graph& _graph, const Edge &ue, const Node &n)
27.388 - : graph(&_graph), Edge(ue) {
27.389 - direction = (_graph.source(ue) == n);
27.390 + : graph(&_graph), Edge(ue) {
27.391 + direction = (_graph.source(ue) == n);
27.392 }
27.393
27.394 IncEdgeIt& operator++() {
27.395 - graph->nextInc(*this, direction);
27.396 - return *this;
27.397 + graph->nextInc(*this, direction);
27.398 + return *this;
27.399 }
27.400 };
27.401
27.402 @@ -534,49 +534,49 @@
27.403
27.404
27.405 template <typename _Value>
27.406 - class ArcMap
27.407 + class ArcMap
27.408 : public MapExtender<DefaultMap<Graph, Arc, _Value> > {
27.409 typedef MapExtender<DefaultMap<Graph, Arc, _Value> > Parent;
27.410
27.411 public:
27.412 - explicit ArcMap(const Graph& _g)
27.413 - : Parent(_g) {}
27.414 - ArcMap(const Graph& _g, const _Value& _v)
27.415 - : Parent(_g, _v) {}
27.416 + explicit ArcMap(const Graph& _g)
27.417 + : Parent(_g) {}
27.418 + ArcMap(const Graph& _g, const _Value& _v)
27.419 + : Parent(_g, _v) {}
27.420
27.421 ArcMap& operator=(const ArcMap& cmap) {
27.422 - return operator=<ArcMap>(cmap);
27.423 + return operator=<ArcMap>(cmap);
27.424 }
27.425
27.426 template <typename CMap>
27.427 ArcMap& operator=(const CMap& cmap) {
27.428 Parent::operator=(cmap);
27.429 - return *this;
27.430 + return *this;
27.431 }
27.432
27.433 };
27.434
27.435
27.436 template <typename _Value>
27.437 - class EdgeMap
27.438 + class EdgeMap
27.439 : public MapExtender<DefaultMap<Graph, Edge, _Value> > {
27.440 typedef MapExtender<DefaultMap<Graph, Edge, _Value> > Parent;
27.441
27.442 public:
27.443 - explicit EdgeMap(const Graph& _g)
27.444 - : Parent(_g) {}
27.445 + explicit EdgeMap(const Graph& _g)
27.446 + : Parent(_g) {}
27.447
27.448 - EdgeMap(const Graph& _g, const _Value& _v)
27.449 - : Parent(_g, _v) {}
27.450 + EdgeMap(const Graph& _g, const _Value& _v)
27.451 + : Parent(_g, _v) {}
27.452
27.453 EdgeMap& operator=(const EdgeMap& cmap) {
27.454 - return operator=<EdgeMap>(cmap);
27.455 + return operator=<EdgeMap>(cmap);
27.456 }
27.457
27.458 template <typename CMap>
27.459 EdgeMap& operator=(const CMap& cmap) {
27.460 Parent::operator=(cmap);
27.461 - return *this;
27.462 + return *this;
27.463 }
27.464
27.465 };
27.466 @@ -593,7 +593,7 @@
27.467 notifier(Arc()).add(arcs);
27.468 return edge;
27.469 }
27.470 -
27.471 +
27.472 void clear() {
27.473 notifier(Arc()).clear();
27.474 notifier(Edge()).clear();
27.475 @@ -619,7 +619,7 @@
27.476 edge_notifier.clear();
27.477 arc_notifier.clear();
27.478 }
27.479 -
27.480 +
27.481 };
27.482
27.483 }
28.1 --- a/lemon/bits/graph_extender.h Tue Dec 20 17:44:38 2011 +0100
28.2 +++ b/lemon/bits/graph_extender.h Tue Dec 20 18:15:14 2011 +0100
28.3 @@ -56,11 +56,11 @@
28.4 return Parent::maxArcId();
28.5 }
28.6
28.7 - Node fromId(int id, Node) const {
28.8 + static Node fromId(int id, Node) {
28.9 return Parent::nodeFromId(id);
28.10 }
28.11
28.12 - Arc fromId(int id, Arc) const {
28.13 + static Arc fromId(int id, Arc) {
28.14 return Parent::arcFromId(id);
28.15 }
28.16
28.17 @@ -355,15 +355,15 @@
28.18 return Parent::maxEdgeId();
28.19 }
28.20
28.21 - Node fromId(int id, Node) const {
28.22 + static Node fromId(int id, Node) {
28.23 return Parent::nodeFromId(id);
28.24 }
28.25
28.26 - Arc fromId(int id, Arc) const {
28.27 + static Arc fromId(int id, Arc) {
28.28 return Parent::arcFromId(id);
28.29 }
28.30
28.31 - Edge fromId(int id, Edge) const {
28.32 + static Edge fromId(int id, Edge) {
28.33 return Parent::edgeFromId(id);
28.34 }
28.35
29.1 --- a/lemon/bits/solver_bits.h Tue Dec 20 17:44:38 2011 +0100
29.2 +++ b/lemon/bits/solver_bits.h Tue Dec 20 18:15:14 2011 +0100
29.3 @@ -2,7 +2,7 @@
29.4 *
29.5 * This file is a part of LEMON, a generic C++ optimization library.
29.6 *
29.7 - * Copyright (C) 2003-2008
29.8 + * Copyright (C) 2003-2010
29.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
29.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
29.11 *
30.1 --- a/lemon/bits/windows.cc Tue Dec 20 17:44:38 2011 +0100
30.2 +++ b/lemon/bits/windows.cc Tue Dec 20 18:15:14 2011 +0100
30.3 @@ -2,7 +2,7 @@
30.4 *
30.5 * This file is a part of LEMON, a generic C++ optimization library.
30.6 *
30.7 - * Copyright (C) 2003-2009
30.8 + * Copyright (C) 2003-2010
30.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
30.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
30.11 *
30.12 @@ -98,7 +98,7 @@
30.13 SYSTEMTIME time;
30.14 GetSystemTime(&time);
30.15 char buf1[11], buf2[9], buf3[5];
30.16 - if (GetDateFormat(MY_LOCALE, 0, &time,
30.17 + if (GetDateFormat(MY_LOCALE, 0, &time,
30.18 ("ddd MMM dd"), buf1, 11) &&
30.19 GetTimeFormat(MY_LOCALE, 0, &time,
30.20 ("HH':'mm':'ss"), buf2, 9) &&
31.1 --- a/lemon/bucket_heap.h Tue Dec 20 17:44:38 2011 +0100
31.2 +++ b/lemon/bucket_heap.h Tue Dec 20 18:15:14 2011 +0100
31.3 @@ -2,7 +2,7 @@
31.4 *
31.5 * This file is a part of LEMON, a generic C++ optimization library.
31.6 *
31.7 - * Copyright (C) 2003-2009
31.8 + * Copyright (C) 2003-2010
31.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
31.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
31.11 *
31.12 @@ -19,9 +19,9 @@
31.13 #ifndef LEMON_BUCKET_HEAP_H
31.14 #define LEMON_BUCKET_HEAP_H
31.15
31.16 -///\ingroup auxdat
31.17 +///\ingroup heaps
31.18 ///\file
31.19 -///\brief Bucket Heap implementation.
31.20 +///\brief Bucket heap implementation.
31.21
31.22 #include <vector>
31.23 #include <utility>
31.24 @@ -53,35 +53,41 @@
31.25
31.26 }
31.27
31.28 - /// \ingroup auxdat
31.29 + /// \ingroup heaps
31.30 ///
31.31 - /// \brief A Bucket Heap implementation.
31.32 + /// \brief Bucket heap data structure.
31.33 ///
31.34 - /// This class implements the \e bucket \e heap data structure. A \e heap
31.35 - /// is a data structure for storing items with specified values called \e
31.36 - /// priorities in such a way that finding the item with minimum priority is
31.37 - /// efficient. The bucket heap is very simple implementation, it can store
31.38 - /// only integer priorities and it stores for each priority in the
31.39 - /// \f$ [0..C) \f$ range a list of items. So it should be used only when
31.40 - /// the priorities are small. It is not intended to use as dijkstra heap.
31.41 + /// This class implements the \e bucket \e heap data structure.
31.42 + /// It practically conforms to the \ref concepts::Heap "heap concept",
31.43 + /// but it has some limitations.
31.44 ///
31.45 - /// \param IM A read and write Item int map, used internally
31.46 - /// to handle the cross references.
31.47 - /// \param MIN If the given parameter is false then instead of the
31.48 - /// minimum value the maximum can be retrivied with the top() and
31.49 - /// prio() member functions.
31.50 + /// The bucket heap is a very simple structure. It can store only
31.51 + /// \c int priorities and it maintains a list of items for each priority
31.52 + /// in the range <tt>[0..C)</tt>. So it should only be used when the
31.53 + /// priorities are small. It is not intended to use as a Dijkstra heap.
31.54 + ///
31.55 + /// \tparam IM A read-writable item map with \c int values, used
31.56 + /// internally to handle the cross references.
31.57 + /// \tparam MIN Indicate if the heap is a \e min-heap or a \e max-heap.
31.58 + /// The default is \e min-heap. If this parameter is set to \c false,
31.59 + /// then the comparison is reversed, so the top(), prio() and pop()
31.60 + /// functions deal with the item having maximum priority instead of the
31.61 + /// minimum.
31.62 + ///
31.63 + /// \sa SimpleBucketHeap
31.64 template <typename IM, bool MIN = true>
31.65 class BucketHeap {
31.66
31.67 public:
31.68 - /// \e
31.69 - typedef typename IM::Key Item;
31.70 - /// \e
31.71 +
31.72 + /// Type of the item-int map.
31.73 + typedef IM ItemIntMap;
31.74 + /// Type of the priorities.
31.75 typedef int Prio;
31.76 - /// \e
31.77 - typedef std::pair<Item, Prio> Pair;
31.78 - /// \e
31.79 - typedef IM ItemIntMap;
31.80 + /// Type of the items stored in the heap.
31.81 + typedef typename ItemIntMap::Key Item;
31.82 + /// Type of the item-priority pairs.
31.83 + typedef std::pair<Item,Prio> Pair;
31.84
31.85 private:
31.86
31.87 @@ -89,10 +95,10 @@
31.88
31.89 public:
31.90
31.91 - /// \brief Type to represent the items states.
31.92 + /// \brief Type to represent the states of the items.
31.93 ///
31.94 - /// Each Item element have a state associated to it. It may be "in heap",
31.95 - /// "pre heap" or "post heap". The latter two are indifferent from the
31.96 + /// Each item has a state associated to it. It can be "in heap",
31.97 + /// "pre-heap" or "post-heap". The latter two are indifferent from the
31.98 /// heap's point of view, but may be useful to the user.
31.99 ///
31.100 /// The item-int map must be initialized in such way that it assigns
31.101 @@ -104,37 +110,39 @@
31.102 };
31.103
31.104 public:
31.105 - /// \brief The constructor.
31.106 +
31.107 + /// \brief Constructor.
31.108 ///
31.109 - /// The constructor.
31.110 - /// \param map should be given to the constructor, since it is used
31.111 - /// internally to handle the cross references. The value of the map
31.112 - /// should be PRE_HEAP (-1) for each element.
31.113 + /// Constructor.
31.114 + /// \param map A map that assigns \c int values to the items.
31.115 + /// It is used internally to handle the cross references.
31.116 + /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
31.117 explicit BucketHeap(ItemIntMap &map) : _iim(map), _minimum(0) {}
31.118
31.119 - /// The number of items stored in the heap.
31.120 + /// \brief The number of items stored in the heap.
31.121 ///
31.122 - /// \brief Returns the number of items stored in the heap.
31.123 + /// This function returns the number of items stored in the heap.
31.124 int size() const { return _data.size(); }
31.125
31.126 - /// \brief Checks if the heap stores no items.
31.127 + /// \brief Check if the heap is empty.
31.128 ///
31.129 - /// Returns \c true if and only if the heap stores no items.
31.130 + /// This function returns \c true if the heap is empty.
31.131 bool empty() const { return _data.empty(); }
31.132
31.133 - /// \brief Make empty this heap.
31.134 + /// \brief Make the heap empty.
31.135 ///
31.136 - /// Make empty this heap. It does not change the cross reference
31.137 - /// map. If you want to reuse a heap what is not surely empty you
31.138 - /// should first clear the heap and after that you should set the
31.139 - /// cross reference map for each item to \c PRE_HEAP.
31.140 + /// This functon makes the heap empty.
31.141 + /// It does not change the cross reference map. If you want to reuse
31.142 + /// a heap that is not surely empty, you should first clear it and
31.143 + /// then you should set the cross reference map to \c PRE_HEAP
31.144 + /// for each item.
31.145 void clear() {
31.146 _data.clear(); _first.clear(); _minimum = 0;
31.147 }
31.148
31.149 private:
31.150
31.151 - void relocate_last(int idx) {
31.152 + void relocateLast(int idx) {
31.153 if (idx + 1 < int(_data.size())) {
31.154 _data[idx] = _data.back();
31.155 if (_data[idx].prev != -1) {
31.156 @@ -174,19 +182,24 @@
31.157 }
31.158
31.159 public:
31.160 +
31.161 /// \brief Insert a pair of item and priority into the heap.
31.162 ///
31.163 - /// Adds \c p.first to the heap with priority \c p.second.
31.164 + /// This function inserts \c p.first to the heap with priority
31.165 + /// \c p.second.
31.166 /// \param p The pair to insert.
31.167 + /// \pre \c p.first must not be stored in the heap.
31.168 void push(const Pair& p) {
31.169 push(p.first, p.second);
31.170 }
31.171
31.172 /// \brief Insert an item into the heap with the given priority.
31.173 ///
31.174 - /// Adds \c i to the heap with priority \c p.
31.175 + /// This function inserts the given item into the heap with the
31.176 + /// given priority.
31.177 /// \param i The item to insert.
31.178 /// \param p The priority of the item.
31.179 + /// \pre \e i must not be stored in the heap.
31.180 void push(const Item &i, const Prio &p) {
31.181 int idx = _data.size();
31.182 _iim[i] = idx;
31.183 @@ -197,10 +210,10 @@
31.184 }
31.185 }
31.186
31.187 - /// \brief Returns the item with minimum priority.
31.188 + /// \brief Return the item having minimum priority.
31.189 ///
31.190 - /// This method returns the item with minimum priority.
31.191 - /// \pre The heap must be nonempty.
31.192 + /// This function returns the item having minimum priority.
31.193 + /// \pre The heap must be non-empty.
31.194 Item top() const {
31.195 while (_first[_minimum] == -1) {
31.196 Direction::increase(_minimum);
31.197 @@ -208,10 +221,10 @@
31.198 return _data[_first[_minimum]].item;
31.199 }
31.200
31.201 - /// \brief Returns the minimum priority.
31.202 + /// \brief The minimum priority.
31.203 ///
31.204 - /// It returns the minimum priority.
31.205 - /// \pre The heap must be nonempty.
31.206 + /// This function returns the minimum priority.
31.207 + /// \pre The heap must be non-empty.
31.208 Prio prio() const {
31.209 while (_first[_minimum] == -1) {
31.210 Direction::increase(_minimum);
31.211 @@ -219,9 +232,9 @@
31.212 return _minimum;
31.213 }
31.214
31.215 - /// \brief Deletes the item with minimum priority.
31.216 + /// \brief Remove the item having minimum priority.
31.217 ///
31.218 - /// This method deletes the item with minimum priority from the heap.
31.219 + /// This function removes the item having minimum priority.
31.220 /// \pre The heap must be non-empty.
31.221 void pop() {
31.222 while (_first[_minimum] == -1) {
31.223 @@ -230,37 +243,38 @@
31.224 int idx = _first[_minimum];
31.225 _iim[_data[idx].item] = -2;
31.226 unlace(idx);
31.227 - relocate_last(idx);
31.228 + relocateLast(idx);
31.229 }
31.230
31.231 - /// \brief Deletes \c i from the heap.
31.232 + /// \brief Remove the given item from the heap.
31.233 ///
31.234 - /// This method deletes item \c i from the heap, if \c i was
31.235 - /// already stored in the heap.
31.236 - /// \param i The item to erase.
31.237 + /// This function removes the given item from the heap if it is
31.238 + /// already stored.
31.239 + /// \param i The item to delete.
31.240 + /// \pre \e i must be in the heap.
31.241 void erase(const Item &i) {
31.242 int idx = _iim[i];
31.243 _iim[_data[idx].item] = -2;
31.244 unlace(idx);
31.245 - relocate_last(idx);
31.246 + relocateLast(idx);
31.247 }
31.248
31.249 -
31.250 - /// \brief Returns the priority of \c i.
31.251 + /// \brief The priority of the given item.
31.252 ///
31.253 - /// This function returns the priority of item \c i.
31.254 - /// \pre \c i must be in the heap.
31.255 + /// This function returns the priority of the given item.
31.256 /// \param i The item.
31.257 + /// \pre \e i must be in the heap.
31.258 Prio operator[](const Item &i) const {
31.259 int idx = _iim[i];
31.260 return _data[idx].value;
31.261 }
31.262
31.263 - /// \brief \c i gets to the heap with priority \c p independently
31.264 - /// if \c i was already there.
31.265 + /// \brief Set the priority of an item or insert it, if it is
31.266 + /// not stored in the heap.
31.267 ///
31.268 - /// This method calls \ref push(\c i, \c p) if \c i is not stored
31.269 - /// in the heap and sets the priority of \c i to \c p otherwise.
31.270 + /// This method sets the priority of the given item if it is
31.271 + /// already stored in the heap. Otherwise it inserts the given
31.272 + /// item into the heap with the given priority.
31.273 /// \param i The item.
31.274 /// \param p The priority.
31.275 void set(const Item &i, const Prio &p) {
31.276 @@ -274,13 +288,12 @@
31.277 }
31.278 }
31.279
31.280 - /// \brief Decreases the priority of \c i to \c p.
31.281 + /// \brief Decrease the priority of an item to the given value.
31.282 ///
31.283 - /// This method decreases the priority of item \c i to \c p.
31.284 - /// \pre \c i must be stored in the heap with priority at least \c
31.285 - /// p relative to \c Compare.
31.286 + /// This function decreases the priority of an item to the given value.
31.287 /// \param i The item.
31.288 /// \param p The priority.
31.289 + /// \pre \e i must be stored in the heap with priority at least \e p.
31.290 void decrease(const Item &i, const Prio &p) {
31.291 int idx = _iim[i];
31.292 unlace(idx);
31.293 @@ -291,13 +304,12 @@
31.294 lace(idx);
31.295 }
31.296
31.297 - /// \brief Increases the priority of \c i to \c p.
31.298 + /// \brief Increase the priority of an item to the given value.
31.299 ///
31.300 - /// This method sets the priority of item \c i to \c p.
31.301 - /// \pre \c i must be stored in the heap with priority at most \c
31.302 - /// p relative to \c Compare.
31.303 + /// This function increases the priority of an item to the given value.
31.304 /// \param i The item.
31.305 /// \param p The priority.
31.306 + /// \pre \e i must be stored in the heap with priority at most \e p.
31.307 void increase(const Item &i, const Prio &p) {
31.308 int idx = _iim[i];
31.309 unlace(idx);
31.310 @@ -305,13 +317,13 @@
31.311 lace(idx);
31.312 }
31.313
31.314 - /// \brief Returns if \c item is in, has already been in, or has
31.315 - /// never been in the heap.
31.316 + /// \brief Return the state of an item.
31.317 ///
31.318 - /// This method returns PRE_HEAP if \c item has never been in the
31.319 - /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
31.320 - /// otherwise. In the latter case it is possible that \c item will
31.321 - /// get back to the heap again.
31.322 + /// This method returns \c PRE_HEAP if the given item has never
31.323 + /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
31.324 + /// and \c POST_HEAP otherwise.
31.325 + /// In the latter case it is possible that the item will get back
31.326 + /// to the heap again.
31.327 /// \param i The item.
31.328 State state(const Item &i) const {
31.329 int idx = _iim[i];
31.330 @@ -319,11 +331,11 @@
31.331 return State(idx);
31.332 }
31.333
31.334 - /// \brief Sets the state of the \c item in the heap.
31.335 + /// \brief Set the state of an item in the heap.
31.336 ///
31.337 - /// Sets the state of the \c item in the heap. It can be used to
31.338 - /// manually clear the heap when it is important to achive the
31.339 - /// better time complexity.
31.340 + /// This function sets the state of the given item in the heap.
31.341 + /// It can be used to manually clear the heap when it is important
31.342 + /// to achive better time complexity.
31.343 /// \param i The item.
31.344 /// \param st The state. It should not be \c IN_HEAP.
31.345 void state(const Item& i, State st) {
31.346 @@ -359,33 +371,44 @@
31.347
31.348 }; // class BucketHeap
31.349
31.350 - /// \ingroup auxdat
31.351 + /// \ingroup heaps
31.352 ///
31.353 - /// \brief A Simplified Bucket Heap implementation.
31.354 + /// \brief Simplified bucket heap data structure.
31.355 ///
31.356 /// This class implements a simplified \e bucket \e heap data
31.357 - /// structure. It does not provide some functionality but it faster
31.358 - /// and simplier data structure than the BucketHeap. The main
31.359 - /// difference is that the BucketHeap stores for every key a double
31.360 - /// linked list while this class stores just simple lists. In the
31.361 - /// other way it does not support erasing each elements just the
31.362 - /// minimal and it does not supports key increasing, decreasing.
31.363 + /// structure. It does not provide some functionality, but it is
31.364 + /// faster and simpler than BucketHeap. The main difference is
31.365 + /// that BucketHeap stores a doubly-linked list for each key while
31.366 + /// this class stores only simply-linked lists. It supports erasing
31.367 + /// only for the item having minimum priority and it does not support
31.368 + /// key increasing and decreasing.
31.369 ///
31.370 - /// \param IM A read and write Item int map, used internally
31.371 - /// to handle the cross references.
31.372 - /// \param MIN If the given parameter is false then instead of the
31.373 - /// minimum value the maximum can be retrivied with the top() and
31.374 - /// prio() member functions.
31.375 + /// Note that this implementation does not conform to the
31.376 + /// \ref concepts::Heap "heap concept" due to the lack of some
31.377 + /// functionality.
31.378 + ///
31.379 + /// \tparam IM A read-writable item map with \c int values, used
31.380 + /// internally to handle the cross references.
31.381 + /// \tparam MIN Indicate if the heap is a \e min-heap or a \e max-heap.
31.382 + /// The default is \e min-heap. If this parameter is set to \c false,
31.383 + /// then the comparison is reversed, so the top(), prio() and pop()
31.384 + /// functions deal with the item having maximum priority instead of the
31.385 + /// minimum.
31.386 ///
31.387 /// \sa BucketHeap
31.388 template <typename IM, bool MIN = true >
31.389 class SimpleBucketHeap {
31.390
31.391 public:
31.392 - typedef typename IM::Key Item;
31.393 +
31.394 + /// Type of the item-int map.
31.395 + typedef IM ItemIntMap;
31.396 + /// Type of the priorities.
31.397 typedef int Prio;
31.398 - typedef std::pair<Item, Prio> Pair;
31.399 - typedef IM ItemIntMap;
31.400 + /// Type of the items stored in the heap.
31.401 + typedef typename ItemIntMap::Key Item;
31.402 + /// Type of the item-priority pairs.
31.403 + typedef std::pair<Item,Prio> Pair;
31.404
31.405 private:
31.406
31.407 @@ -393,10 +416,10 @@
31.408
31.409 public:
31.410
31.411 - /// \brief Type to represent the items states.
31.412 + /// \brief Type to represent the states of the items.
31.413 ///
31.414 - /// Each Item element have a state associated to it. It may be "in heap",
31.415 - /// "pre heap" or "post heap". The latter two are indifferent from the
31.416 + /// Each item has a state associated to it. It can be "in heap",
31.417 + /// "pre-heap" or "post-heap". The latter two are indifferent from the
31.418 /// heap's point of view, but may be useful to the user.
31.419 ///
31.420 /// The item-int map must be initialized in such way that it assigns
31.421 @@ -409,48 +432,53 @@
31.422
31.423 public:
31.424
31.425 - /// \brief The constructor.
31.426 + /// \brief Constructor.
31.427 ///
31.428 - /// The constructor.
31.429 - /// \param map should be given to the constructor, since it is used
31.430 - /// internally to handle the cross references. The value of the map
31.431 - /// should be PRE_HEAP (-1) for each element.
31.432 + /// Constructor.
31.433 + /// \param map A map that assigns \c int values to the items.
31.434 + /// It is used internally to handle the cross references.
31.435 + /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
31.436 explicit SimpleBucketHeap(ItemIntMap &map)
31.437 : _iim(map), _free(-1), _num(0), _minimum(0) {}
31.438
31.439 - /// \brief Returns the number of items stored in the heap.
31.440 + /// \brief The number of items stored in the heap.
31.441 ///
31.442 - /// The number of items stored in the heap.
31.443 + /// This function returns the number of items stored in the heap.
31.444 int size() const { return _num; }
31.445
31.446 - /// \brief Checks if the heap stores no items.
31.447 + /// \brief Check if the heap is empty.
31.448 ///
31.449 - /// Returns \c true if and only if the heap stores no items.
31.450 + /// This function returns \c true if the heap is empty.
31.451 bool empty() const { return _num == 0; }
31.452
31.453 - /// \brief Make empty this heap.
31.454 + /// \brief Make the heap empty.
31.455 ///
31.456 - /// Make empty this heap. It does not change the cross reference
31.457 - /// map. If you want to reuse a heap what is not surely empty you
31.458 - /// should first clear the heap and after that you should set the
31.459 - /// cross reference map for each item to \c PRE_HEAP.
31.460 + /// This functon makes the heap empty.
31.461 + /// It does not change the cross reference map. If you want to reuse
31.462 + /// a heap that is not surely empty, you should first clear it and
31.463 + /// then you should set the cross reference map to \c PRE_HEAP
31.464 + /// for each item.
31.465 void clear() {
31.466 _data.clear(); _first.clear(); _free = -1; _num = 0; _minimum = 0;
31.467 }
31.468
31.469 /// \brief Insert a pair of item and priority into the heap.
31.470 ///
31.471 - /// Adds \c p.first to the heap with priority \c p.second.
31.472 + /// This function inserts \c p.first to the heap with priority
31.473 + /// \c p.second.
31.474 /// \param p The pair to insert.
31.475 + /// \pre \c p.first must not be stored in the heap.
31.476 void push(const Pair& p) {
31.477 push(p.first, p.second);
31.478 }
31.479
31.480 /// \brief Insert an item into the heap with the given priority.
31.481 ///
31.482 - /// Adds \c i to the heap with priority \c p.
31.483 + /// This function inserts the given item into the heap with the
31.484 + /// given priority.
31.485 /// \param i The item to insert.
31.486 /// \param p The priority of the item.
31.487 + /// \pre \e i must not be stored in the heap.
31.488 void push(const Item &i, const Prio &p) {
31.489 int idx;
31.490 if (_free == -1) {
31.491 @@ -471,10 +499,10 @@
31.492 ++_num;
31.493 }
31.494
31.495 - /// \brief Returns the item with minimum priority.
31.496 + /// \brief Return the item having minimum priority.
31.497 ///
31.498 - /// This method returns the item with minimum priority.
31.499 - /// \pre The heap must be nonempty.
31.500 + /// This function returns the item having minimum priority.
31.501 + /// \pre The heap must be non-empty.
31.502 Item top() const {
31.503 while (_first[_minimum] == -1) {
31.504 Direction::increase(_minimum);
31.505 @@ -482,10 +510,10 @@
31.506 return _data[_first[_minimum]].item;
31.507 }
31.508
31.509 - /// \brief Returns the minimum priority.
31.510 + /// \brief The minimum priority.
31.511 ///
31.512 - /// It returns the minimum priority.
31.513 - /// \pre The heap must be nonempty.
31.514 + /// This function returns the minimum priority.
31.515 + /// \pre The heap must be non-empty.
31.516 Prio prio() const {
31.517 while (_first[_minimum] == -1) {
31.518 Direction::increase(_minimum);
31.519 @@ -493,9 +521,9 @@
31.520 return _minimum;
31.521 }
31.522
31.523 - /// \brief Deletes the item with minimum priority.
31.524 + /// \brief Remove the item having minimum priority.
31.525 ///
31.526 - /// This method deletes the item with minimum priority from the heap.
31.527 + /// This function removes the item having minimum priority.
31.528 /// \pre The heap must be non-empty.
31.529 void pop() {
31.530 while (_first[_minimum] == -1) {
31.531 @@ -509,16 +537,15 @@
31.532 --_num;
31.533 }
31.534
31.535 - /// \brief Returns the priority of \c i.
31.536 + /// \brief The priority of the given item.
31.537 ///
31.538 - /// This function returns the priority of item \c i.
31.539 - /// \warning This operator is not a constant time function
31.540 - /// because it scans the whole data structure to find the proper
31.541 - /// value.
31.542 - /// \pre \c i must be in the heap.
31.543 + /// This function returns the priority of the given item.
31.544 /// \param i The item.
31.545 + /// \pre \e i must be in the heap.
31.546 + /// \warning This operator is not a constant time function because
31.547 + /// it scans the whole data structure to find the proper value.
31.548 Prio operator[](const Item &i) const {
31.549 - for (int k = 0; k < _first.size(); ++k) {
31.550 + for (int k = 0; k < int(_first.size()); ++k) {
31.551 int idx = _first[k];
31.552 while (idx != -1) {
31.553 if (_data[idx].item == i) {
31.554 @@ -530,13 +557,13 @@
31.555 return -1;
31.556 }
31.557
31.558 - /// \brief Returns if \c item is in, has already been in, or has
31.559 - /// never been in the heap.
31.560 + /// \brief Return the state of an item.
31.561 ///
31.562 - /// This method returns PRE_HEAP if \c item has never been in the
31.563 - /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
31.564 - /// otherwise. In the latter case it is possible that \c item will
31.565 - /// get back to the heap again.
31.566 + /// This method returns \c PRE_HEAP if the given item has never
31.567 + /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
31.568 + /// and \c POST_HEAP otherwise.
31.569 + /// In the latter case it is possible that the item will get back
31.570 + /// to the heap again.
31.571 /// \param i The item.
31.572 State state(const Item &i) const {
31.573 int idx = _iim[i];
32.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
32.2 +++ b/lemon/capacity_scaling.h Tue Dec 20 18:15:14 2011 +0100
32.3 @@ -0,0 +1,990 @@
32.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
32.5 + *
32.6 + * This file is a part of LEMON, a generic C++ optimization library.
32.7 + *
32.8 + * Copyright (C) 2003-2010
32.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
32.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
32.11 + *
32.12 + * Permission to use, modify and distribute this software is granted
32.13 + * provided that this copyright notice appears in all copies. For
32.14 + * precise terms see the accompanying LICENSE file.
32.15 + *
32.16 + * This software is provided "AS IS" with no warranty of any kind,
32.17 + * express or implied, and with no claim as to its suitability for any
32.18 + * purpose.
32.19 + *
32.20 + */
32.21 +
32.22 +#ifndef LEMON_CAPACITY_SCALING_H
32.23 +#define LEMON_CAPACITY_SCALING_H
32.24 +
32.25 +/// \ingroup min_cost_flow_algs
32.26 +///
32.27 +/// \file
32.28 +/// \brief Capacity Scaling algorithm for finding a minimum cost flow.
32.29 +
32.30 +#include <vector>
32.31 +#include <limits>
32.32 +#include <lemon/core.h>
32.33 +#include <lemon/bin_heap.h>
32.34 +
32.35 +namespace lemon {
32.36 +
32.37 + /// \brief Default traits class of CapacityScaling algorithm.
32.38 + ///
32.39 + /// Default traits class of CapacityScaling algorithm.
32.40 + /// \tparam GR Digraph type.
32.41 + /// \tparam V The number type used for flow amounts, capacity bounds
32.42 + /// and supply values. By default it is \c int.
32.43 + /// \tparam C The number type used for costs and potentials.
32.44 + /// By default it is the same as \c V.
32.45 + template <typename GR, typename V = int, typename C = V>
32.46 + struct CapacityScalingDefaultTraits
32.47 + {
32.48 + /// The type of the digraph
32.49 + typedef GR Digraph;
32.50 + /// The type of the flow amounts, capacity bounds and supply values
32.51 + typedef V Value;
32.52 + /// The type of the arc costs
32.53 + typedef C Cost;
32.54 +
32.55 + /// \brief The type of the heap used for internal Dijkstra computations.
32.56 + ///
32.57 + /// The type of the heap used for internal Dijkstra computations.
32.58 + /// It must conform to the \ref lemon::concepts::Heap "Heap" concept,
32.59 + /// its priority type must be \c Cost and its cross reference type
32.60 + /// must be \ref RangeMap "RangeMap<int>".
32.61 + typedef BinHeap<Cost, RangeMap<int> > Heap;
32.62 + };
32.63 +
32.64 + /// \addtogroup min_cost_flow_algs
32.65 + /// @{
32.66 +
32.67 + /// \brief Implementation of the Capacity Scaling algorithm for
32.68 + /// finding a \ref min_cost_flow "minimum cost flow".
32.69 + ///
32.70 + /// \ref CapacityScaling implements the capacity scaling version
32.71 + /// of the successive shortest path algorithm for finding a
32.72 + /// \ref min_cost_flow "minimum cost flow" \ref amo93networkflows,
32.73 + /// \ref edmondskarp72theoretical. It is an efficient dual
32.74 + /// solution method.
32.75 + ///
32.76 + /// Most of the parameters of the problem (except for the digraph)
32.77 + /// can be given using separate functions, and the algorithm can be
32.78 + /// executed using the \ref run() function. If some parameters are not
32.79 + /// specified, then default values will be used.
32.80 + ///
32.81 + /// \tparam GR The digraph type the algorithm runs on.
32.82 + /// \tparam V The number type used for flow amounts, capacity bounds
32.83 + /// and supply values in the algorithm. By default, it is \c int.
32.84 + /// \tparam C The number type used for costs and potentials in the
32.85 + /// algorithm. By default, it is the same as \c V.
32.86 + /// \tparam TR The traits class that defines various types used by the
32.87 + /// algorithm. By default, it is \ref CapacityScalingDefaultTraits
32.88 + /// "CapacityScalingDefaultTraits<GR, V, C>".
32.89 + /// In most cases, this parameter should not be set directly,
32.90 + /// consider to use the named template parameters instead.
32.91 + ///
32.92 + /// \warning Both number types must be signed and all input data must
32.93 + /// be integer.
32.94 + /// \warning This algorithm does not support negative costs for such
32.95 + /// arcs that have infinite upper bound.
32.96 +#ifdef DOXYGEN
32.97 + template <typename GR, typename V, typename C, typename TR>
32.98 +#else
32.99 + template < typename GR, typename V = int, typename C = V,
32.100 + typename TR = CapacityScalingDefaultTraits<GR, V, C> >
32.101 +#endif
32.102 + class CapacityScaling
32.103 + {
32.104 + public:
32.105 +
32.106 + /// The type of the digraph
32.107 + typedef typename TR::Digraph Digraph;
32.108 + /// The type of the flow amounts, capacity bounds and supply values
32.109 + typedef typename TR::Value Value;
32.110 + /// The type of the arc costs
32.111 + typedef typename TR::Cost Cost;
32.112 +
32.113 + /// The type of the heap used for internal Dijkstra computations
32.114 + typedef typename TR::Heap Heap;
32.115 +
32.116 + /// The \ref CapacityScalingDefaultTraits "traits class" of the algorithm
32.117 + typedef TR Traits;
32.118 +
32.119 + public:
32.120 +
32.121 + /// \brief Problem type constants for the \c run() function.
32.122 + ///
32.123 + /// Enum type containing the problem type constants that can be
32.124 + /// returned by the \ref run() function of the algorithm.
32.125 + enum ProblemType {
32.126 + /// The problem has no feasible solution (flow).
32.127 + INFEASIBLE,
32.128 + /// The problem has optimal solution (i.e. it is feasible and
32.129 + /// bounded), and the algorithm has found optimal flow and node
32.130 + /// potentials (primal and dual solutions).
32.131 + OPTIMAL,
32.132 + /// The digraph contains an arc of negative cost and infinite
32.133 + /// upper bound. It means that the objective function is unbounded
32.134 + /// on that arc, however, note that it could actually be bounded
32.135 + /// over the feasible flows, but this algroithm cannot handle
32.136 + /// these cases.
32.137 + UNBOUNDED
32.138 + };
32.139 +
32.140 + private:
32.141 +
32.142 + TEMPLATE_DIGRAPH_TYPEDEFS(GR);
32.143 +
32.144 + typedef std::vector<int> IntVector;
32.145 + typedef std::vector<Value> ValueVector;
32.146 + typedef std::vector<Cost> CostVector;
32.147 + typedef std::vector<char> BoolVector;
32.148 + // Note: vector<char> is used instead of vector<bool> for efficiency reasons
32.149 +
32.150 + private:
32.151 +
32.152 + // Data related to the underlying digraph
32.153 + const GR &_graph;
32.154 + int _node_num;
32.155 + int _arc_num;
32.156 + int _res_arc_num;
32.157 + int _root;
32.158 +
32.159 + // Parameters of the problem
32.160 + bool _have_lower;
32.161 + Value _sum_supply;
32.162 +
32.163 + // Data structures for storing the digraph
32.164 + IntNodeMap _node_id;
32.165 + IntArcMap _arc_idf;
32.166 + IntArcMap _arc_idb;
32.167 + IntVector _first_out;
32.168 + BoolVector _forward;
32.169 + IntVector _source;
32.170 + IntVector _target;
32.171 + IntVector _reverse;
32.172 +
32.173 + // Node and arc data
32.174 + ValueVector _lower;
32.175 + ValueVector _upper;
32.176 + CostVector _cost;
32.177 + ValueVector _supply;
32.178 +
32.179 + ValueVector _res_cap;
32.180 + CostVector _pi;
32.181 + ValueVector _excess;
32.182 + IntVector _excess_nodes;
32.183 + IntVector _deficit_nodes;
32.184 +
32.185 + Value _delta;
32.186 + int _factor;
32.187 + IntVector _pred;
32.188 +
32.189 + public:
32.190 +
32.191 + /// \brief Constant for infinite upper bounds (capacities).
32.192 + ///
32.193 + /// Constant for infinite upper bounds (capacities).
32.194 + /// It is \c std::numeric_limits<Value>::infinity() if available,
32.195 + /// \c std::numeric_limits<Value>::max() otherwise.
32.196 + const Value INF;
32.197 +
32.198 + private:
32.199 +
32.200 + // Special implementation of the Dijkstra algorithm for finding
32.201 + // shortest paths in the residual network of the digraph with
32.202 + // respect to the reduced arc costs and modifying the node
32.203 + // potentials according to the found distance labels.
32.204 + class ResidualDijkstra
32.205 + {
32.206 + private:
32.207 +
32.208 + int _node_num;
32.209 + bool _geq;
32.210 + const IntVector &_first_out;
32.211 + const IntVector &_target;
32.212 + const CostVector &_cost;
32.213 + const ValueVector &_res_cap;
32.214 + const ValueVector &_excess;
32.215 + CostVector &_pi;
32.216 + IntVector &_pred;
32.217 +
32.218 + IntVector _proc_nodes;
32.219 + CostVector _dist;
32.220 +
32.221 + public:
32.222 +
32.223 + ResidualDijkstra(CapacityScaling& cs) :
32.224 + _node_num(cs._node_num), _geq(cs._sum_supply < 0),
32.225 + _first_out(cs._first_out), _target(cs._target), _cost(cs._cost),
32.226 + _res_cap(cs._res_cap), _excess(cs._excess), _pi(cs._pi),
32.227 + _pred(cs._pred), _dist(cs._node_num)
32.228 + {}
32.229 +
32.230 + int run(int s, Value delta = 1) {
32.231 + RangeMap<int> heap_cross_ref(_node_num, Heap::PRE_HEAP);
32.232 + Heap heap(heap_cross_ref);
32.233 + heap.push(s, 0);
32.234 + _pred[s] = -1;
32.235 + _proc_nodes.clear();
32.236 +
32.237 + // Process nodes
32.238 + while (!heap.empty() && _excess[heap.top()] > -delta) {
32.239 + int u = heap.top(), v;
32.240 + Cost d = heap.prio() + _pi[u], dn;
32.241 + _dist[u] = heap.prio();
32.242 + _proc_nodes.push_back(u);
32.243 + heap.pop();
32.244 +
32.245 + // Traverse outgoing residual arcs
32.246 + int last_out = _geq ? _first_out[u+1] : _first_out[u+1] - 1;
32.247 + for (int a = _first_out[u]; a != last_out; ++a) {
32.248 + if (_res_cap[a] < delta) continue;
32.249 + v = _target[a];
32.250 + switch (heap.state(v)) {
32.251 + case Heap::PRE_HEAP:
32.252 + heap.push(v, d + _cost[a] - _pi[v]);
32.253 + _pred[v] = a;
32.254 + break;
32.255 + case Heap::IN_HEAP:
32.256 + dn = d + _cost[a] - _pi[v];
32.257 + if (dn < heap[v]) {
32.258 + heap.decrease(v, dn);
32.259 + _pred[v] = a;
32.260 + }
32.261 + break;
32.262 + case Heap::POST_HEAP:
32.263 + break;
32.264 + }
32.265 + }
32.266 + }
32.267 + if (heap.empty()) return -1;
32.268 +
32.269 + // Update potentials of processed nodes
32.270 + int t = heap.top();
32.271 + Cost dt = heap.prio();
32.272 + for (int i = 0; i < int(_proc_nodes.size()); ++i) {
32.273 + _pi[_proc_nodes[i]] += _dist[_proc_nodes[i]] - dt;
32.274 + }
32.275 +
32.276 + return t;
32.277 + }
32.278 +
32.279 + }; //class ResidualDijkstra
32.280 +
32.281 + public:
32.282 +
32.283 + /// \name Named Template Parameters
32.284 + /// @{
32.285 +
32.286 + template <typename T>
32.287 + struct SetHeapTraits : public Traits {
32.288 + typedef T Heap;
32.289 + };
32.290 +
32.291 + /// \brief \ref named-templ-param "Named parameter" for setting
32.292 + /// \c Heap type.
32.293 + ///
32.294 + /// \ref named-templ-param "Named parameter" for setting \c Heap
32.295 + /// type, which is used for internal Dijkstra computations.
32.296 + /// It must conform to the \ref lemon::concepts::Heap "Heap" concept,
32.297 + /// its priority type must be \c Cost and its cross reference type
32.298 + /// must be \ref RangeMap "RangeMap<int>".
32.299 + template <typename T>
32.300 + struct SetHeap
32.301 + : public CapacityScaling<GR, V, C, SetHeapTraits<T> > {
32.302 + typedef CapacityScaling<GR, V, C, SetHeapTraits<T> > Create;
32.303 + };
32.304 +
32.305 + /// @}
32.306 +
32.307 + protected:
32.308 +
32.309 + CapacityScaling() {}
32.310 +
32.311 + public:
32.312 +
32.313 + /// \brief Constructor.
32.314 + ///
32.315 + /// The constructor of the class.
32.316 + ///
32.317 + /// \param graph The digraph the algorithm runs on.
32.318 + CapacityScaling(const GR& graph) :
32.319 + _graph(graph), _node_id(graph), _arc_idf(graph), _arc_idb(graph),
32.320 + INF(std::numeric_limits<Value>::has_infinity ?
32.321 + std::numeric_limits<Value>::infinity() :
32.322 + std::numeric_limits<Value>::max())
32.323 + {
32.324 + // Check the number types
32.325 + LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
32.326 + "The flow type of CapacityScaling must be signed");
32.327 + LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
32.328 + "The cost type of CapacityScaling must be signed");
32.329 +
32.330 + // Reset data structures
32.331 + reset();
32.332 + }
32.333 +
32.334 + /// \name Parameters
32.335 + /// The parameters of the algorithm can be specified using these
32.336 + /// functions.
32.337 +
32.338 + /// @{
32.339 +
32.340 + /// \brief Set the lower bounds on the arcs.
32.341 + ///
32.342 + /// This function sets the lower bounds on the arcs.
32.343 + /// If it is not used before calling \ref run(), the lower bounds
32.344 + /// will be set to zero on all arcs.
32.345 + ///
32.346 + /// \param map An arc map storing the lower bounds.
32.347 + /// Its \c Value type must be convertible to the \c Value type
32.348 + /// of the algorithm.
32.349 + ///
32.350 + /// \return <tt>(*this)</tt>
32.351 + template <typename LowerMap>
32.352 + CapacityScaling& lowerMap(const LowerMap& map) {
32.353 + _have_lower = true;
32.354 + for (ArcIt a(_graph); a != INVALID; ++a) {
32.355 + _lower[_arc_idf[a]] = map[a];
32.356 + _lower[_arc_idb[a]] = map[a];
32.357 + }
32.358 + return *this;
32.359 + }
32.360 +
32.361 + /// \brief Set the upper bounds (capacities) on the arcs.
32.362 + ///
32.363 + /// This function sets the upper bounds (capacities) on the arcs.
32.364 + /// If it is not used before calling \ref run(), the upper bounds
32.365 + /// will be set to \ref INF on all arcs (i.e. the flow value will be
32.366 + /// unbounded from above).
32.367 + ///
32.368 + /// \param map An arc map storing the upper bounds.
32.369 + /// Its \c Value type must be convertible to the \c Value type
32.370 + /// of the algorithm.
32.371 + ///
32.372 + /// \return <tt>(*this)</tt>
32.373 + template<typename UpperMap>
32.374 + CapacityScaling& upperMap(const UpperMap& map) {
32.375 + for (ArcIt a(_graph); a != INVALID; ++a) {
32.376 + _upper[_arc_idf[a]] = map[a];
32.377 + }
32.378 + return *this;
32.379 + }
32.380 +
32.381 + /// \brief Set the costs of the arcs.
32.382 + ///
32.383 + /// This function sets the costs of the arcs.
32.384 + /// If it is not used before calling \ref run(), the costs
32.385 + /// will be set to \c 1 on all arcs.
32.386 + ///
32.387 + /// \param map An arc map storing the costs.
32.388 + /// Its \c Value type must be convertible to the \c Cost type
32.389 + /// of the algorithm.
32.390 + ///
32.391 + /// \return <tt>(*this)</tt>
32.392 + template<typename CostMap>
32.393 + CapacityScaling& costMap(const CostMap& map) {
32.394 + for (ArcIt a(_graph); a != INVALID; ++a) {
32.395 + _cost[_arc_idf[a]] = map[a];
32.396 + _cost[_arc_idb[a]] = -map[a];
32.397 + }
32.398 + return *this;
32.399 + }
32.400 +
32.401 + /// \brief Set the supply values of the nodes.
32.402 + ///
32.403 + /// This function sets the supply values of the nodes.
32.404 + /// If neither this function nor \ref stSupply() is used before
32.405 + /// calling \ref run(), the supply of each node will be set to zero.
32.406 + ///
32.407 + /// \param map A node map storing the supply values.
32.408 + /// Its \c Value type must be convertible to the \c Value type
32.409 + /// of the algorithm.
32.410 + ///
32.411 + /// \return <tt>(*this)</tt>
32.412 + template<typename SupplyMap>
32.413 + CapacityScaling& supplyMap(const SupplyMap& map) {
32.414 + for (NodeIt n(_graph); n != INVALID; ++n) {
32.415 + _supply[_node_id[n]] = map[n];
32.416 + }
32.417 + return *this;
32.418 + }
32.419 +
32.420 + /// \brief Set single source and target nodes and a supply value.
32.421 + ///
32.422 + /// This function sets a single source node and a single target node
32.423 + /// and the required flow value.
32.424 + /// If neither this function nor \ref supplyMap() is used before
32.425 + /// calling \ref run(), the supply of each node will be set to zero.
32.426 + ///
32.427 + /// Using this function has the same effect as using \ref supplyMap()
32.428 + /// with such a map in which \c k is assigned to \c s, \c -k is
32.429 + /// assigned to \c t and all other nodes have zero supply value.
32.430 + ///
32.431 + /// \param s The source node.
32.432 + /// \param t The target node.
32.433 + /// \param k The required amount of flow from node \c s to node \c t
32.434 + /// (i.e. the supply of \c s and the demand of \c t).
32.435 + ///
32.436 + /// \return <tt>(*this)</tt>
32.437 + CapacityScaling& stSupply(const Node& s, const Node& t, Value k) {
32.438 + for (int i = 0; i != _node_num; ++i) {
32.439 + _supply[i] = 0;
32.440 + }
32.441 + _supply[_node_id[s]] = k;
32.442 + _supply[_node_id[t]] = -k;
32.443 + return *this;
32.444 + }
32.445 +
32.446 + /// @}
32.447 +
32.448 + /// \name Execution control
32.449 + /// The algorithm can be executed using \ref run().
32.450 +
32.451 + /// @{
32.452 +
32.453 + /// \brief Run the algorithm.
32.454 + ///
32.455 + /// This function runs the algorithm.
32.456 + /// The paramters can be specified using functions \ref lowerMap(),
32.457 + /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply().
32.458 + /// For example,
32.459 + /// \code
32.460 + /// CapacityScaling<ListDigraph> cs(graph);
32.461 + /// cs.lowerMap(lower).upperMap(upper).costMap(cost)
32.462 + /// .supplyMap(sup).run();
32.463 + /// \endcode
32.464 + ///
32.465 + /// This function can be called more than once. All the given parameters
32.466 + /// are kept for the next call, unless \ref resetParams() or \ref reset()
32.467 + /// is used, thus only the modified parameters have to be set again.
32.468 + /// If the underlying digraph was also modified after the construction
32.469 + /// of the class (or the last \ref reset() call), then the \ref reset()
32.470 + /// function must be called.
32.471 + ///
32.472 + /// \param factor The capacity scaling factor. It must be larger than
32.473 + /// one to use scaling. If it is less or equal to one, then scaling
32.474 + /// will be disabled.
32.475 + ///
32.476 + /// \return \c INFEASIBLE if no feasible flow exists,
32.477 + /// \n \c OPTIMAL if the problem has optimal solution
32.478 + /// (i.e. it is feasible and bounded), and the algorithm has found
32.479 + /// optimal flow and node potentials (primal and dual solutions),
32.480 + /// \n \c UNBOUNDED if the digraph contains an arc of negative cost
32.481 + /// and infinite upper bound. It means that the objective function
32.482 + /// is unbounded on that arc, however, note that it could actually be
32.483 + /// bounded over the feasible flows, but this algroithm cannot handle
32.484 + /// these cases.
32.485 + ///
32.486 + /// \see ProblemType
32.487 + /// \see resetParams(), reset()
32.488 + ProblemType run(int factor = 4) {
32.489 + _factor = factor;
32.490 + ProblemType pt = init();
32.491 + if (pt != OPTIMAL) return pt;
32.492 + return start();
32.493 + }
32.494 +
32.495 + /// \brief Reset all the parameters that have been given before.
32.496 + ///
32.497 + /// This function resets all the paramaters that have been given
32.498 + /// before using functions \ref lowerMap(), \ref upperMap(),
32.499 + /// \ref costMap(), \ref supplyMap(), \ref stSupply().
32.500 + ///
32.501 + /// It is useful for multiple \ref run() calls. Basically, all the given
32.502 + /// parameters are kept for the next \ref run() call, unless
32.503 + /// \ref resetParams() or \ref reset() is used.
32.504 + /// If the underlying digraph was also modified after the construction
32.505 + /// of the class or the last \ref reset() call, then the \ref reset()
32.506 + /// function must be used, otherwise \ref resetParams() is sufficient.
32.507 + ///
32.508 + /// For example,
32.509 + /// \code
32.510 + /// CapacityScaling<ListDigraph> cs(graph);
32.511 + ///
32.512 + /// // First run
32.513 + /// cs.lowerMap(lower).upperMap(upper).costMap(cost)
32.514 + /// .supplyMap(sup).run();
32.515 + ///
32.516 + /// // Run again with modified cost map (resetParams() is not called,
32.517 + /// // so only the cost map have to be set again)
32.518 + /// cost[e] += 100;
32.519 + /// cs.costMap(cost).run();
32.520 + ///
32.521 + /// // Run again from scratch using resetParams()
32.522 + /// // (the lower bounds will be set to zero on all arcs)
32.523 + /// cs.resetParams();
32.524 + /// cs.upperMap(capacity).costMap(cost)
32.525 + /// .supplyMap(sup).run();
32.526 + /// \endcode
32.527 + ///
32.528 + /// \return <tt>(*this)</tt>
32.529 + ///
32.530 + /// \see reset(), run()
32.531 + CapacityScaling& resetParams() {
32.532 + for (int i = 0; i != _node_num; ++i) {
32.533 + _supply[i] = 0;
32.534 + }
32.535 + for (int j = 0; j != _res_arc_num; ++j) {
32.536 + _lower[j] = 0;
32.537 + _upper[j] = INF;
32.538 + _cost[j] = _forward[j] ? 1 : -1;
32.539 + }
32.540 + _have_lower = false;
32.541 + return *this;
32.542 + }
32.543 +
32.544 + /// \brief Reset the internal data structures and all the parameters
32.545 + /// that have been given before.
32.546 + ///
32.547 + /// This function resets the internal data structures and all the
32.548 + /// paramaters that have been given before using functions \ref lowerMap(),
32.549 + /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply().
32.550 + ///
32.551 + /// It is useful for multiple \ref run() calls. Basically, all the given
32.552 + /// parameters are kept for the next \ref run() call, unless
32.553 + /// \ref resetParams() or \ref reset() is used.
32.554 + /// If the underlying digraph was also modified after the construction
32.555 + /// of the class or the last \ref reset() call, then the \ref reset()
32.556 + /// function must be used, otherwise \ref resetParams() is sufficient.
32.557 + ///
32.558 + /// See \ref resetParams() for examples.
32.559 + ///
32.560 + /// \return <tt>(*this)</tt>
32.561 + ///
32.562 + /// \see resetParams(), run()
32.563 + CapacityScaling& reset() {
32.564 + // Resize vectors
32.565 + _node_num = countNodes(_graph);
32.566 + _arc_num = countArcs(_graph);
32.567 + _res_arc_num = 2 * (_arc_num + _node_num);
32.568 + _root = _node_num;
32.569 + ++_node_num;
32.570 +
32.571 + _first_out.resize(_node_num + 1);
32.572 + _forward.resize(_res_arc_num);
32.573 + _source.resize(_res_arc_num);
32.574 + _target.resize(_res_arc_num);
32.575 + _reverse.resize(_res_arc_num);
32.576 +
32.577 + _lower.resize(_res_arc_num);
32.578 + _upper.resize(_res_arc_num);
32.579 + _cost.resize(_res_arc_num);
32.580 + _supply.resize(_node_num);
32.581 +
32.582 + _res_cap.resize(_res_arc_num);
32.583 + _pi.resize(_node_num);
32.584 + _excess.resize(_node_num);
32.585 + _pred.resize(_node_num);
32.586 +
32.587 + // Copy the graph
32.588 + int i = 0, j = 0, k = 2 * _arc_num + _node_num - 1;
32.589 + for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
32.590 + _node_id[n] = i;
32.591 + }
32.592 + i = 0;
32.593 + for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
32.594 + _first_out[i] = j;
32.595 + for (OutArcIt a(_graph, n); a != INVALID; ++a, ++j) {
32.596 + _arc_idf[a] = j;
32.597 + _forward[j] = true;
32.598 + _source[j] = i;
32.599 + _target[j] = _node_id[_graph.runningNode(a)];
32.600 + }
32.601 + for (InArcIt a(_graph, n); a != INVALID; ++a, ++j) {
32.602 + _arc_idb[a] = j;
32.603 + _forward[j] = false;
32.604 + _source[j] = i;
32.605 + _target[j] = _node_id[_graph.runningNode(a)];
32.606 + }
32.607 + _forward[j] = false;
32.608 + _source[j] = i;
32.609 + _target[j] = _root;
32.610 + _reverse[j] = k;
32.611 + _forward[k] = true;
32.612 + _source[k] = _root;
32.613 + _target[k] = i;
32.614 + _reverse[k] = j;
32.615 + ++j; ++k;
32.616 + }
32.617 + _first_out[i] = j;
32.618 + _first_out[_node_num] = k;
32.619 + for (ArcIt a(_graph); a != INVALID; ++a) {
32.620 + int fi = _arc_idf[a];
32.621 + int bi = _arc_idb[a];
32.622 + _reverse[fi] = bi;
32.623 + _reverse[bi] = fi;
32.624 + }
32.625 +
32.626 + // Reset parameters
32.627 + resetParams();
32.628 + return *this;
32.629 + }
32.630 +
32.631 + /// @}
32.632 +
32.633 + /// \name Query Functions
32.634 + /// The results of the algorithm can be obtained using these
32.635 + /// functions.\n
32.636 + /// The \ref run() function must be called before using them.
32.637 +
32.638 + /// @{
32.639 +
32.640 + /// \brief Return the total cost of the found flow.
32.641 + ///
32.642 + /// This function returns the total cost of the found flow.
32.643 + /// Its complexity is O(e).
32.644 + ///
32.645 + /// \note The return type of the function can be specified as a
32.646 + /// template parameter. For example,
32.647 + /// \code
32.648 + /// cs.totalCost<double>();
32.649 + /// \endcode
32.650 + /// It is useful if the total cost cannot be stored in the \c Cost
32.651 + /// type of the algorithm, which is the default return type of the
32.652 + /// function.
32.653 + ///
32.654 + /// \pre \ref run() must be called before using this function.
32.655 + template <typename Number>
32.656 + Number totalCost() const {
32.657 + Number c = 0;
32.658 + for (ArcIt a(_graph); a != INVALID; ++a) {
32.659 + int i = _arc_idb[a];
32.660 + c += static_cast<Number>(_res_cap[i]) *
32.661 + (-static_cast<Number>(_cost[i]));
32.662 + }
32.663 + return c;
32.664 + }
32.665 +
32.666 +#ifndef DOXYGEN
32.667 + Cost totalCost() const {
32.668 + return totalCost<Cost>();
32.669 + }
32.670 +#endif
32.671 +
32.672 + /// \brief Return the flow on the given arc.
32.673 + ///
32.674 + /// This function returns the flow on the given arc.
32.675 + ///
32.676 + /// \pre \ref run() must be called before using this function.
32.677 + Value flow(const Arc& a) const {
32.678 + return _res_cap[_arc_idb[a]];
32.679 + }
32.680 +
32.681 + /// \brief Return the flow map (the primal solution).
32.682 + ///
32.683 + /// This function copies the flow value on each arc into the given
32.684 + /// map. The \c Value type of the algorithm must be convertible to
32.685 + /// the \c Value type of the map.
32.686 + ///
32.687 + /// \pre \ref run() must be called before using this function.
32.688 + template <typename FlowMap>
32.689 + void flowMap(FlowMap &map) const {
32.690 + for (ArcIt a(_graph); a != INVALID; ++a) {
32.691 + map.set(a, _res_cap[_arc_idb[a]]);
32.692 + }
32.693 + }
32.694 +
32.695 + /// \brief Return the potential (dual value) of the given node.
32.696 + ///
32.697 + /// This function returns the potential (dual value) of the
32.698 + /// given node.
32.699 + ///
32.700 + /// \pre \ref run() must be called before using this function.
32.701 + Cost potential(const Node& n) const {
32.702 + return _pi[_node_id[n]];
32.703 + }
32.704 +
32.705 + /// \brief Return the potential map (the dual solution).
32.706 + ///
32.707 + /// This function copies the potential (dual value) of each node
32.708 + /// into the given map.
32.709 + /// The \c Cost type of the algorithm must be convertible to the
32.710 + /// \c Value type of the map.
32.711 + ///
32.712 + /// \pre \ref run() must be called before using this function.
32.713 + template <typename PotentialMap>
32.714 + void potentialMap(PotentialMap &map) const {
32.715 + for (NodeIt n(_graph); n != INVALID; ++n) {
32.716 + map.set(n, _pi[_node_id[n]]);
32.717 + }
32.718 + }
32.719 +
32.720 + /// @}
32.721 +
32.722 + private:
32.723 +
32.724 + // Initialize the algorithm
32.725 + ProblemType init() {
32.726 + if (_node_num <= 1) return INFEASIBLE;
32.727 +
32.728 + // Check the sum of supply values
32.729 + _sum_supply = 0;
32.730 + for (int i = 0; i != _root; ++i) {
32.731 + _sum_supply += _supply[i];
32.732 + }
32.733 + if (_sum_supply > 0) return INFEASIBLE;
32.734 +
32.735 + // Initialize vectors
32.736 + for (int i = 0; i != _root; ++i) {
32.737 + _pi[i] = 0;
32.738 + _excess[i] = _supply[i];
32.739 + }
32.740 +
32.741 + // Remove non-zero lower bounds
32.742 + const Value MAX = std::numeric_limits<Value>::max();
32.743 + int last_out;
32.744 + if (_have_lower) {
32.745 + for (int i = 0; i != _root; ++i) {
32.746 + last_out = _first_out[i+1];
32.747 + for (int j = _first_out[i]; j != last_out; ++j) {
32.748 + if (_forward[j]) {
32.749 + Value c = _lower[j];
32.750 + if (c >= 0) {
32.751 + _res_cap[j] = _upper[j] < MAX ? _upper[j] - c : INF;
32.752 + } else {
32.753 + _res_cap[j] = _upper[j] < MAX + c ? _upper[j] - c : INF;
32.754 + }
32.755 + _excess[i] -= c;
32.756 + _excess[_target[j]] += c;
32.757 + } else {
32.758 + _res_cap[j] = 0;
32.759 + }
32.760 + }
32.761 + }
32.762 + } else {
32.763 + for (int j = 0; j != _res_arc_num; ++j) {
32.764 + _res_cap[j] = _forward[j] ? _upper[j] : 0;
32.765 + }
32.766 + }
32.767 +
32.768 + // Handle negative costs
32.769 + for (int i = 0; i != _root; ++i) {
32.770 + last_out = _first_out[i+1] - 1;
32.771 + for (int j = _first_out[i]; j != last_out; ++j) {
32.772 + Value rc = _res_cap[j];
32.773 + if (_cost[j] < 0 && rc > 0) {
32.774 + if (rc >= MAX) return UNBOUNDED;
32.775 + _excess[i] -= rc;
32.776 + _excess[_target[j]] += rc;
32.777 + _res_cap[j] = 0;
32.778 + _res_cap[_reverse[j]] += rc;
32.779 + }
32.780 + }
32.781 + }
32.782 +
32.783 + // Handle GEQ supply type
32.784 + if (_sum_supply < 0) {
32.785 + _pi[_root] = 0;
32.786 + _excess[_root] = -_sum_supply;
32.787 + for (int a = _first_out[_root]; a != _res_arc_num; ++a) {
32.788 + int ra = _reverse[a];
32.789 + _res_cap[a] = -_sum_supply + 1;
32.790 + _res_cap[ra] = 0;
32.791 + _cost[a] = 0;
32.792 + _cost[ra] = 0;
32.793 + }
32.794 + } else {
32.795 + _pi[_root] = 0;
32.796 + _excess[_root] = 0;
32.797 + for (int a = _first_out[_root]; a != _res_arc_num; ++a) {
32.798 + int ra = _reverse[a];
32.799 + _res_cap[a] = 1;
32.800 + _res_cap[ra] = 0;
32.801 + _cost[a] = 0;
32.802 + _cost[ra] = 0;
32.803 + }
32.804 + }
32.805 +
32.806 + // Initialize delta value
32.807 + if (_factor > 1) {
32.808 + // With scaling
32.809 + Value max_sup = 0, max_dem = 0, max_cap = 0;
32.810 + for (int i = 0; i != _root; ++i) {
32.811 + Value ex = _excess[i];
32.812 + if ( ex > max_sup) max_sup = ex;
32.813 + if (-ex > max_dem) max_dem = -ex;
32.814 + int last_out = _first_out[i+1] - 1;
32.815 + for (int j = _first_out[i]; j != last_out; ++j) {
32.816 + if (_res_cap[j] > max_cap) max_cap = _res_cap[j];
32.817 + }
32.818 + }
32.819 + max_sup = std::min(std::min(max_sup, max_dem), max_cap);
32.820 + for (_delta = 1; 2 * _delta <= max_sup; _delta *= 2) ;
32.821 + } else {
32.822 + // Without scaling
32.823 + _delta = 1;
32.824 + }
32.825 +
32.826 + return OPTIMAL;
32.827 + }
32.828 +
32.829 + ProblemType start() {
32.830 + // Execute the algorithm
32.831 + ProblemType pt;
32.832 + if (_delta > 1)
32.833 + pt = startWithScaling();
32.834 + else
32.835 + pt = startWithoutScaling();
32.836 +
32.837 + // Handle non-zero lower bounds
32.838 + if (_have_lower) {
32.839 + int limit = _first_out[_root];
32.840 + for (int j = 0; j != limit; ++j) {
32.841 + if (!_forward[j]) _res_cap[j] += _lower[j];
32.842 + }
32.843 + }
32.844 +
32.845 + // Shift potentials if necessary
32.846 + Cost pr = _pi[_root];
32.847 + if (_sum_supply < 0 || pr > 0) {
32.848 + for (int i = 0; i != _node_num; ++i) {
32.849 + _pi[i] -= pr;
32.850 + }
32.851 + }
32.852 +
32.853 + return pt;
32.854 + }
32.855 +
32.856 + // Execute the capacity scaling algorithm
32.857 + ProblemType startWithScaling() {
32.858 + // Perform capacity scaling phases
32.859 + int s, t;
32.860 + ResidualDijkstra _dijkstra(*this);
32.861 + while (true) {
32.862 + // Saturate all arcs not satisfying the optimality condition
32.863 + int last_out;
32.864 + for (int u = 0; u != _node_num; ++u) {
32.865 + last_out = _sum_supply < 0 ?
32.866 + _first_out[u+1] : _first_out[u+1] - 1;
32.867 + for (int a = _first_out[u]; a != last_out; ++a) {
32.868 + int v = _target[a];
32.869 + Cost c = _cost[a] + _pi[u] - _pi[v];
32.870 + Value rc = _res_cap[a];
32.871 + if (c < 0 && rc >= _delta) {
32.872 + _excess[u] -= rc;
32.873 + _excess[v] += rc;
32.874 + _res_cap[a] = 0;
32.875 + _res_cap[_reverse[a]] += rc;
32.876 + }
32.877 + }
32.878 + }
32.879 +
32.880 + // Find excess nodes and deficit nodes
32.881 + _excess_nodes.clear();
32.882 + _deficit_nodes.clear();
32.883 + for (int u = 0; u != _node_num; ++u) {
32.884 + Value ex = _excess[u];
32.885 + if (ex >= _delta) _excess_nodes.push_back(u);
32.886 + if (ex <= -_delta) _deficit_nodes.push_back(u);
32.887 + }
32.888 + int next_node = 0, next_def_node = 0;
32.889 +
32.890 + // Find augmenting shortest paths
32.891 + while (next_node < int(_excess_nodes.size())) {
32.892 + // Check deficit nodes
32.893 + if (_delta > 1) {
32.894 + bool delta_deficit = false;
32.895 + for ( ; next_def_node < int(_deficit_nodes.size());
32.896 + ++next_def_node ) {
32.897 + if (_excess[_deficit_nodes[next_def_node]] <= -_delta) {
32.898 + delta_deficit = true;
32.899 + break;
32.900 + }
32.901 + }
32.902 + if (!delta_deficit) break;
32.903 + }
32.904 +
32.905 + // Run Dijkstra in the residual network
32.906 + s = _excess_nodes[next_node];
32.907 + if ((t = _dijkstra.run(s, _delta)) == -1) {
32.908 + if (_delta > 1) {
32.909 + ++next_node;
32.910 + continue;
32.911 + }
32.912 + return INFEASIBLE;
32.913 + }
32.914 +
32.915 + // Augment along a shortest path from s to t
32.916 + Value d = std::min(_excess[s], -_excess[t]);
32.917 + int u = t;
32.918 + int a;
32.919 + if (d > _delta) {
32.920 + while ((a = _pred[u]) != -1) {
32.921 + if (_res_cap[a] < d) d = _res_cap[a];
32.922 + u = _source[a];
32.923 + }
32.924 + }
32.925 + u = t;
32.926 + while ((a = _pred[u]) != -1) {
32.927 + _res_cap[a] -= d;
32.928 + _res_cap[_reverse[a]] += d;
32.929 + u = _source[a];
32.930 + }
32.931 + _excess[s] -= d;
32.932 + _excess[t] += d;
32.933 +
32.934 + if (_excess[s] < _delta) ++next_node;
32.935 + }
32.936 +
32.937 + if (_delta == 1) break;
32.938 + _delta = _delta <= _factor ? 1 : _delta / _factor;
32.939 + }
32.940 +
32.941 + return OPTIMAL;
32.942 + }
32.943 +
32.944 + // Execute the successive shortest path algorithm
32.945 + ProblemType startWithoutScaling() {
32.946 + // Find excess nodes
32.947 + _excess_nodes.clear();
32.948 + for (int i = 0; i != _node_num; ++i) {
32.949 + if (_excess[i] > 0) _excess_nodes.push_back(i);
32.950 + }
32.951 + if (_excess_nodes.size() == 0) return OPTIMAL;
32.952 + int next_node = 0;
32.953 +
32.954 + // Find shortest paths
32.955 + int s, t;
32.956 + ResidualDijkstra _dijkstra(*this);
32.957 + while ( _excess[_excess_nodes[next_node]] > 0 ||
32.958 + ++next_node < int(_excess_nodes.size()) )
32.959 + {
32.960 + // Run Dijkstra in the residual network
32.961 + s = _excess_nodes[next_node];
32.962 + if ((t = _dijkstra.run(s)) == -1) return INFEASIBLE;
32.963 +
32.964 + // Augment along a shortest path from s to t
32.965 + Value d = std::min(_excess[s], -_excess[t]);
32.966 + int u = t;
32.967 + int a;
32.968 + if (d > 1) {
32.969 + while ((a = _pred[u]) != -1) {
32.970 + if (_res_cap[a] < d) d = _res_cap[a];
32.971 + u = _source[a];
32.972 + }
32.973 + }
32.974 + u = t;
32.975 + while ((a = _pred[u]) != -1) {
32.976 + _res_cap[a] -= d;
32.977 + _res_cap[_reverse[a]] += d;
32.978 + u = _source[a];
32.979 + }
32.980 + _excess[s] -= d;
32.981 + _excess[t] += d;
32.982 + }
32.983 +
32.984 + return OPTIMAL;
32.985 + }
32.986 +
32.987 + }; //class CapacityScaling
32.988 +
32.989 + ///@}
32.990 +
32.991 +} //namespace lemon
32.992 +
32.993 +#endif //LEMON_CAPACITY_SCALING_H
33.1 --- a/lemon/cbc.cc Tue Dec 20 17:44:38 2011 +0100
33.2 +++ b/lemon/cbc.cc Tue Dec 20 18:15:14 2011 +0100
33.3 @@ -94,6 +94,18 @@
33.4 return _prob->numberRows() - 1;
33.5 }
33.6
33.7 + int CbcMip::_addRow(Value l, ExprIterator b, ExprIterator e, Value u) {
33.8 + std::vector<int> indexes;
33.9 + std::vector<Value> values;
33.10 +
33.11 + for(ExprIterator it = b; it != e; ++it) {
33.12 + indexes.push_back(it->first);
33.13 + values.push_back(it->second);
33.14 + }
33.15 +
33.16 + _prob->addRow(values.size(), &indexes.front(), &values.front(), l, u);
33.17 + return _prob->numberRows() - 1;
33.18 + }
33.19
33.20 void CbcMip::_eraseCol(int i) {
33.21 _prob->deleteColumn(i);
34.1 --- a/lemon/cbc.h Tue Dec 20 17:44:38 2011 +0100
34.2 +++ b/lemon/cbc.h Tue Dec 20 18:15:14 2011 +0100
34.3 @@ -2,7 +2,7 @@
34.4 *
34.5 * This file is a part of LEMON, a generic C++ optimization library.
34.6 *
34.7 - * Copyright (C) 2003-2009
34.8 + * Copyright (C) 2003-2010
34.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
34.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
34.11 *
34.12 @@ -62,6 +62,7 @@
34.13
34.14 virtual int _addCol();
34.15 virtual int _addRow();
34.16 + virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
34.17
34.18 virtual void _eraseCol(int i);
34.19 virtual void _eraseRow(int i);
34.20 @@ -120,7 +121,7 @@
34.21
34.22 int _message_level;
34.23
34.24 -
34.25 +
34.26
34.27 };
34.28
35.1 --- a/lemon/circulation.h Tue Dec 20 17:44:38 2011 +0100
35.2 +++ b/lemon/circulation.h Tue Dec 20 18:15:14 2011 +0100
35.3 @@ -2,7 +2,7 @@
35.4 *
35.5 * This file is a part of LEMON, a generic C++ optimization library.
35.6 *
35.7 - * Copyright (C) 2003-2009
35.8 + * Copyright (C) 2003-2010
35.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
35.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
35.11 *
35.12 @@ -59,8 +59,8 @@
35.13
35.14 /// \brief The type of supply map.
35.15 ///
35.16 - /// The type of the map that stores the signed supply values of the
35.17 - /// nodes.
35.18 + /// The type of the map that stores the signed supply values of the
35.19 + /// nodes.
35.20 /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
35.21 typedef SM SupplyMap;
35.22
35.23 @@ -72,7 +72,11 @@
35.24 /// The type of the map that stores the flow values.
35.25 /// It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap"
35.26 /// concept.
35.27 +#ifdef DOXYGEN
35.28 + typedef GR::ArcMap<Value> FlowMap;
35.29 +#else
35.30 typedef typename Digraph::template ArcMap<Value> FlowMap;
35.31 +#endif
35.32
35.33 /// \brief Instantiates a FlowMap.
35.34 ///
35.35 @@ -87,9 +91,12 @@
35.36 ///
35.37 /// The elevator type used by the algorithm.
35.38 ///
35.39 - /// \sa Elevator
35.40 - /// \sa LinkedElevator
35.41 + /// \sa Elevator, LinkedElevator
35.42 +#ifdef DOXYGEN
35.43 + typedef lemon::Elevator<GR, GR::Node> Elevator;
35.44 +#else
35.45 typedef lemon::Elevator<Digraph, typename Digraph::Node> Elevator;
35.46 +#endif
35.47
35.48 /// \brief Instantiates an Elevator.
35.49 ///
35.50 @@ -134,7 +141,7 @@
35.51 \f[ \sum_{uv\in A} f(uv) - \sum_{vu\in A} f(vu)
35.52 \geq sup(u) \quad \forall u\in V, \f]
35.53 \f[ lower(uv) \leq f(uv) \leq upper(uv) \quad \forall uv\in A. \f]
35.54 -
35.55 +
35.56 The sum of the supply values, i.e. \f$\sum_{u\in V} sup(u)\f$ must be
35.57 zero or negative in order to have a feasible solution (since the sum
35.58 of the expressions on the left-hand side of the inequalities is zero).
35.59 @@ -144,7 +151,7 @@
35.60 If \f$\sum_{u\in V} sup(u)\f$ is zero, then all the supply/demand
35.61 constraints have to be satisfied with equality, i.e. all demands
35.62 have to be satisfied and all supplies have to be used.
35.63 -
35.64 +
35.65 If you need the opposite inequalities in the supply/demand constraints
35.66 (i.e. the total demand is less than the total supply and all the demands
35.67 have to be satisfied while there could be supplies that are not used),
35.68 @@ -166,6 +173,11 @@
35.69 The default map type is \c LM.
35.70 \tparam SM The type of the supply map. The default map type is
35.71 \ref concepts::Digraph::NodeMap "GR::NodeMap<UM::Value>".
35.72 + \tparam TR The traits class that defines various types used by the
35.73 + algorithm. By default, it is \ref CirculationDefaultTraits
35.74 + "CirculationDefaultTraits<GR, LM, UM, SM>".
35.75 + In most cases, this parameter should not be set directly,
35.76 + consider to use the named template parameters instead.
35.77 */
35.78 #ifdef DOXYGEN
35.79 template< typename GR,
35.80 @@ -299,7 +311,7 @@
35.81 /// The Elevator should have standard constructor interface to be
35.82 /// able to automatically created by the algorithm (i.e. the
35.83 /// digraph and the maximum level should be passed to it).
35.84 - /// However an external elevator object could also be passed to the
35.85 + /// However, an external elevator object could also be passed to the
35.86 /// algorithm with the \ref elevator(Elevator&) "elevator()" function
35.87 /// before calling \ref run() or \ref init().
35.88 /// \sa SetElevator
35.89 @@ -325,7 +337,7 @@
35.90 ///
35.91 /// \param graph The digraph the algorithm runs on.
35.92 /// \param lower The lower bounds for the flow values on the arcs.
35.93 - /// \param upper The upper bounds (capacities) for the flow values
35.94 + /// \param upper The upper bounds (capacities) for the flow values
35.95 /// on the arcs.
35.96 /// \param supply The signed supply values of the nodes.
35.97 Circulation(const Digraph &graph, const LowerMap &lower,
35.98 @@ -450,9 +462,10 @@
35.99 return *_level;
35.100 }
35.101
35.102 - /// \brief Sets the tolerance used by algorithm.
35.103 + /// \brief Sets the tolerance used by the algorithm.
35.104 ///
35.105 - /// Sets the tolerance used by algorithm.
35.106 + /// Sets the tolerance object used by the algorithm.
35.107 + /// \return <tt>(*this)</tt>
35.108 Circulation& tolerance(const Tolerance& tolerance) {
35.109 _tol = tolerance;
35.110 return *this;
35.111 @@ -460,15 +473,16 @@
35.112
35.113 /// \brief Returns a const reference to the tolerance.
35.114 ///
35.115 - /// Returns a const reference to the tolerance.
35.116 + /// Returns a const reference to the tolerance object used by
35.117 + /// the algorithm.
35.118 const Tolerance& tolerance() const {
35.119 return _tol;
35.120 }
35.121
35.122 /// \name Execution Control
35.123 /// The simplest way to execute the algorithm is to call \ref run().\n
35.124 - /// If you need more control on the initial solution or the execution,
35.125 - /// first you have to call one of the \ref init() functions, then
35.126 + /// If you need better control on the initial solution or the execution,
35.127 + /// you have to call one of the \ref init() functions first, then
35.128 /// the \ref start() function.
35.129
35.130 ///@{
36.1 --- a/lemon/clp.cc Tue Dec 20 17:44:38 2011 +0100
36.2 +++ b/lemon/clp.cc Tue Dec 20 18:15:14 2011 +0100
36.3 @@ -2,7 +2,7 @@
36.4 *
36.5 * This file is a part of LEMON, a generic C++ optimization library.
36.6 *
36.7 - * Copyright (C) 2003-2008
36.8 + * Copyright (C) 2003-2010
36.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
36.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
36.11 *
36.12 @@ -78,6 +78,19 @@
36.13 return _prob->numberRows() - 1;
36.14 }
36.15
36.16 + int ClpLp::_addRow(Value l, ExprIterator b, ExprIterator e, Value u) {
36.17 + std::vector<int> indexes;
36.18 + std::vector<Value> values;
36.19 +
36.20 + for(ExprIterator it = b; it != e; ++it) {
36.21 + indexes.push_back(it->first);
36.22 + values.push_back(it->second);
36.23 + }
36.24 +
36.25 + _prob->addRow(values.size(), &indexes.front(), &values.front(), l, u);
36.26 + return _prob->numberRows() - 1;
36.27 + }
36.28 +
36.29
36.30 void ClpLp::_eraseCol(int c) {
36.31 _col_names_ref.erase(_prob->getColumnName(c));
37.1 --- a/lemon/clp.h Tue Dec 20 17:44:38 2011 +0100
37.2 +++ b/lemon/clp.h Tue Dec 20 18:15:14 2011 +0100
37.3 @@ -2,7 +2,7 @@
37.4 *
37.5 * This file is a part of LEMON, a generic C++ optimization library.
37.6 *
37.7 - * Copyright (C) 2003-2008
37.8 + * Copyright (C) 2003-2010
37.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
37.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
37.11 *
37.12 @@ -75,6 +75,7 @@
37.13
37.14 virtual int _addCol();
37.15 virtual int _addRow();
37.16 + virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
37.17
37.18 virtual void _eraseCol(int i);
37.19 virtual void _eraseRow(int i);
37.20 @@ -137,7 +138,7 @@
37.21 virtual void _clear();
37.22
37.23 virtual void _messageLevel(MessageLevel);
37.24 -
37.25 +
37.26 public:
37.27
37.28 ///Solves LP with primal simplex method.
38.1 --- a/lemon/concepts/digraph.h Tue Dec 20 17:44:38 2011 +0100
38.2 +++ b/lemon/concepts/digraph.h Tue Dec 20 18:15:14 2011 +0100
38.3 @@ -2,7 +2,7 @@
38.4 *
38.5 * This file is a part of LEMON, a generic C++ optimization library.
38.6 *
38.7 - * Copyright (C) 2003-2009
38.8 + * Copyright (C) 2003-2010
38.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
38.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
38.11 *
38.12 @@ -35,46 +35,40 @@
38.13 ///
38.14 /// \brief Class describing the concept of directed graphs.
38.15 ///
38.16 - /// This class describes the \ref concept "concept" of the
38.17 - /// immutable directed digraphs.
38.18 + /// This class describes the common interface of all directed
38.19 + /// graphs (digraphs).
38.20 ///
38.21 - /// Note that actual digraph implementation like @ref ListDigraph or
38.22 - /// @ref SmartDigraph may have several additional functionality.
38.23 + /// Like all concept classes, it only provides an interface
38.24 + /// without any sensible implementation. So any general algorithm for
38.25 + /// directed graphs should compile with this class, but it will not
38.26 + /// run properly, of course.
38.27 + /// An actual digraph implementation like \ref ListDigraph or
38.28 + /// \ref SmartDigraph may have additional functionality.
38.29 ///
38.30 - /// \sa concept
38.31 + /// \sa Graph
38.32 class Digraph {
38.33 private:
38.34 - ///Digraphs are \e not copy constructible. Use DigraphCopy() instead.
38.35 + /// Diraphs are \e not copy constructible. Use DigraphCopy instead.
38.36 + Digraph(const Digraph &) {}
38.37 + /// \brief Assignment of a digraph to another one is \e not allowed.
38.38 + /// Use DigraphCopy instead.
38.39 + void operator=(const Digraph &) {}
38.40
38.41 - ///Digraphs are \e not copy constructible. Use DigraphCopy() instead.
38.42 - ///
38.43 - Digraph(const Digraph &) {};
38.44 - ///\brief Assignment of \ref Digraph "Digraph"s to another ones are
38.45 - ///\e not allowed. Use DigraphCopy() instead.
38.46 + public:
38.47 + /// Default constructor.
38.48 + Digraph() { }
38.49
38.50 - ///Assignment of \ref Digraph "Digraph"s to another ones are
38.51 - ///\e not allowed. Use DigraphCopy() instead.
38.52 -
38.53 - void operator=(const Digraph &) {}
38.54 - public:
38.55 - ///\e
38.56 -
38.57 - /// Defalult constructor.
38.58 -
38.59 - /// Defalult constructor.
38.60 - ///
38.61 - Digraph() { }
38.62 - /// Class for identifying a node of the digraph
38.63 + /// The node type of the digraph
38.64
38.65 /// This class identifies a node of the digraph. It also serves
38.66 /// as a base class of the node iterators,
38.67 - /// thus they will convert to this type.
38.68 + /// thus they convert to this type.
38.69 class Node {
38.70 public:
38.71 /// Default constructor
38.72
38.73 - /// @warning The default constructor sets the iterator
38.74 - /// to an undefined value.
38.75 + /// Default constructor.
38.76 + /// \warning It sets the object to an undefined value.
38.77 Node() { }
38.78 /// Copy constructor.
38.79
38.80 @@ -82,40 +76,39 @@
38.81 ///
38.82 Node(const Node&) { }
38.83
38.84 - /// Invalid constructor \& conversion.
38.85 + /// %Invalid constructor \& conversion.
38.86
38.87 - /// This constructor initializes the iterator to be invalid.
38.88 + /// Initializes the object to be invalid.
38.89 /// \sa Invalid for more details.
38.90 Node(Invalid) { }
38.91 /// Equality operator
38.92
38.93 + /// Equality operator.
38.94 + ///
38.95 /// Two iterators are equal if and only if they point to the
38.96 - /// same object or both are invalid.
38.97 + /// same object or both are \c INVALID.
38.98 bool operator==(Node) const { return true; }
38.99
38.100 /// Inequality operator
38.101
38.102 - /// \sa operator==(Node n)
38.103 - ///
38.104 + /// Inequality operator.
38.105 bool operator!=(Node) const { return true; }
38.106
38.107 /// Artificial ordering operator.
38.108
38.109 - /// To allow the use of digraph descriptors as key type in std::map or
38.110 - /// similar associative container we require this.
38.111 + /// Artificial ordering operator.
38.112 ///
38.113 - /// \note This operator only have to define some strict ordering of
38.114 - /// the items; this order has nothing to do with the iteration
38.115 - /// ordering of the items.
38.116 + /// \note This operator only has to define some strict ordering of
38.117 + /// the nodes; this order has nothing to do with the iteration
38.118 + /// ordering of the nodes.
38.119 bool operator<(Node) const { return false; }
38.120 -
38.121 };
38.122
38.123 - /// This iterator goes through each node.
38.124 + /// Iterator class for the nodes.
38.125
38.126 - /// This iterator goes through each node.
38.127 - /// Its usage is quite simple, for example you can count the number
38.128 - /// of nodes in digraph \c g of type \c Digraph like this:
38.129 + /// This iterator goes through each node of the digraph.
38.130 + /// Its usage is quite simple, for example, you can count the number
38.131 + /// of nodes in a digraph \c g of type \c %Digraph like this:
38.132 ///\code
38.133 /// int count=0;
38.134 /// for (Digraph::NodeIt n(g); n!=INVALID; ++n) ++count;
38.135 @@ -124,30 +117,28 @@
38.136 public:
38.137 /// Default constructor
38.138
38.139 - /// @warning The default constructor sets the iterator
38.140 - /// to an undefined value.
38.141 + /// Default constructor.
38.142 + /// \warning It sets the iterator to an undefined value.
38.143 NodeIt() { }
38.144 /// Copy constructor.
38.145
38.146 /// Copy constructor.
38.147 ///
38.148 NodeIt(const NodeIt& n) : Node(n) { }
38.149 - /// Invalid constructor \& conversion.
38.150 + /// %Invalid constructor \& conversion.
38.151
38.152 - /// Initialize the iterator to be invalid.
38.153 + /// Initializes the iterator to be invalid.
38.154 /// \sa Invalid for more details.
38.155 NodeIt(Invalid) { }
38.156 /// Sets the iterator to the first node.
38.157
38.158 - /// Sets the iterator to the first node of \c g.
38.159 + /// Sets the iterator to the first node of the given digraph.
38.160 ///
38.161 - NodeIt(const Digraph&) { }
38.162 - /// Node -> NodeIt conversion.
38.163 + explicit NodeIt(const Digraph&) { }
38.164 + /// Sets the iterator to the given node.
38.165
38.166 - /// Sets the iterator to the node of \c the digraph pointed by
38.167 - /// the trivial iterator.
38.168 - /// This feature necessitates that each time we
38.169 - /// iterate the arc-set, the iteration order is the same.
38.170 + /// Sets the iterator to the given node of the given digraph.
38.171 + ///
38.172 NodeIt(const Digraph&, const Node&) { }
38.173 /// Next node.
38.174
38.175 @@ -157,7 +148,7 @@
38.176 };
38.177
38.178
38.179 - /// Class for identifying an arc of the digraph
38.180 + /// The arc type of the digraph
38.181
38.182 /// This class identifies an arc of the digraph. It also serves
38.183 /// as a base class of the arc iterators,
38.184 @@ -166,207 +157,214 @@
38.185 public:
38.186 /// Default constructor
38.187
38.188 - /// @warning The default constructor sets the iterator
38.189 - /// to an undefined value.
38.190 + /// Default constructor.
38.191 + /// \warning It sets the object to an undefined value.
38.192 Arc() { }
38.193 /// Copy constructor.
38.194
38.195 /// Copy constructor.
38.196 ///
38.197 Arc(const Arc&) { }
38.198 - /// Initialize the iterator to be invalid.
38.199 + /// %Invalid constructor \& conversion.
38.200
38.201 - /// Initialize the iterator to be invalid.
38.202 - ///
38.203 + /// Initializes the object to be invalid.
38.204 + /// \sa Invalid for more details.
38.205 Arc(Invalid) { }
38.206 /// Equality operator
38.207
38.208 + /// Equality operator.
38.209 + ///
38.210 /// Two iterators are equal if and only if they point to the
38.211 - /// same object or both are invalid.
38.212 + /// same object or both are \c INVALID.
38.213 bool operator==(Arc) const { return true; }
38.214 /// Inequality operator
38.215
38.216 - /// \sa operator==(Arc n)
38.217 - ///
38.218 + /// Inequality operator.
38.219 bool operator!=(Arc) const { return true; }
38.220
38.221 /// Artificial ordering operator.
38.222
38.223 - /// To allow the use of digraph descriptors as key type in std::map or
38.224 - /// similar associative container we require this.
38.225 + /// Artificial ordering operator.
38.226 ///
38.227 - /// \note This operator only have to define some strict ordering of
38.228 - /// the items; this order has nothing to do with the iteration
38.229 - /// ordering of the items.
38.230 + /// \note This operator only has to define some strict ordering of
38.231 + /// the arcs; this order has nothing to do with the iteration
38.232 + /// ordering of the arcs.
38.233 bool operator<(Arc) const { return false; }
38.234 };
38.235
38.236 - /// This iterator goes trough the outgoing arcs of a node.
38.237 + /// Iterator class for the outgoing arcs of a node.
38.238
38.239 /// This iterator goes trough the \e outgoing arcs of a certain node
38.240 /// of a digraph.
38.241 - /// Its usage is quite simple, for example you can count the number
38.242 + /// Its usage is quite simple, for example, you can count the number
38.243 /// of outgoing arcs of a node \c n
38.244 - /// in digraph \c g of type \c Digraph as follows.
38.245 + /// in a digraph \c g of type \c %Digraph as follows.
38.246 ///\code
38.247 /// int count=0;
38.248 - /// for (Digraph::OutArcIt e(g, n); e!=INVALID; ++e) ++count;
38.249 + /// for (Digraph::OutArcIt a(g, n); a!=INVALID; ++a) ++count;
38.250 ///\endcode
38.251 -
38.252 class OutArcIt : public Arc {
38.253 public:
38.254 /// Default constructor
38.255
38.256 - /// @warning The default constructor sets the iterator
38.257 - /// to an undefined value.
38.258 + /// Default constructor.
38.259 + /// \warning It sets the iterator to an undefined value.
38.260 OutArcIt() { }
38.261 /// Copy constructor.
38.262
38.263 /// Copy constructor.
38.264 ///
38.265 OutArcIt(const OutArcIt& e) : Arc(e) { }
38.266 - /// Initialize the iterator to be invalid.
38.267 + /// %Invalid constructor \& conversion.
38.268
38.269 - /// Initialize the iterator to be invalid.
38.270 + /// Initializes the iterator to be invalid.
38.271 + /// \sa Invalid for more details.
38.272 + OutArcIt(Invalid) { }
38.273 + /// Sets the iterator to the first outgoing arc.
38.274 +
38.275 + /// Sets the iterator to the first outgoing arc of the given node.
38.276 ///
38.277 - OutArcIt(Invalid) { }
38.278 - /// This constructor sets the iterator to the first outgoing arc.
38.279 + OutArcIt(const Digraph&, const Node&) { }
38.280 + /// Sets the iterator to the given arc.
38.281
38.282 - /// This constructor sets the iterator to the first outgoing arc of
38.283 - /// the node.
38.284 - OutArcIt(const Digraph&, const Node&) { }
38.285 - /// Arc -> OutArcIt conversion
38.286 -
38.287 - /// Sets the iterator to the value of the trivial iterator.
38.288 - /// This feature necessitates that each time we
38.289 - /// iterate the arc-set, the iteration order is the same.
38.290 + /// Sets the iterator to the given arc of the given digraph.
38.291 + ///
38.292 OutArcIt(const Digraph&, const Arc&) { }
38.293 - ///Next outgoing arc
38.294 + /// Next outgoing arc
38.295
38.296 /// Assign the iterator to the next
38.297 /// outgoing arc of the corresponding node.
38.298 OutArcIt& operator++() { return *this; }
38.299 };
38.300
38.301 - /// This iterator goes trough the incoming arcs of a node.
38.302 + /// Iterator class for the incoming arcs of a node.
38.303
38.304 /// This iterator goes trough the \e incoming arcs of a certain node
38.305 /// of a digraph.
38.306 - /// Its usage is quite simple, for example you can count the number
38.307 - /// of outgoing arcs of a node \c n
38.308 - /// in digraph \c g of type \c Digraph as follows.
38.309 + /// Its usage is quite simple, for example, you can count the number
38.310 + /// of incoming arcs of a node \c n
38.311 + /// in a digraph \c g of type \c %Digraph as follows.
38.312 ///\code
38.313 /// int count=0;
38.314 - /// for(Digraph::InArcIt e(g, n); e!=INVALID; ++e) ++count;
38.315 + /// for(Digraph::InArcIt a(g, n); a!=INVALID; ++a) ++count;
38.316 ///\endcode
38.317 -
38.318 class InArcIt : public Arc {
38.319 public:
38.320 /// Default constructor
38.321
38.322 - /// @warning The default constructor sets the iterator
38.323 - /// to an undefined value.
38.324 + /// Default constructor.
38.325 + /// \warning It sets the iterator to an undefined value.
38.326 InArcIt() { }
38.327 /// Copy constructor.
38.328
38.329 /// Copy constructor.
38.330 ///
38.331 InArcIt(const InArcIt& e) : Arc(e) { }
38.332 - /// Initialize the iterator to be invalid.
38.333 + /// %Invalid constructor \& conversion.
38.334
38.335 - /// Initialize the iterator to be invalid.
38.336 + /// Initializes the iterator to be invalid.
38.337 + /// \sa Invalid for more details.
38.338 + InArcIt(Invalid) { }
38.339 + /// Sets the iterator to the first incoming arc.
38.340 +
38.341 + /// Sets the iterator to the first incoming arc of the given node.
38.342 ///
38.343 - InArcIt(Invalid) { }
38.344 - /// This constructor sets the iterator to first incoming arc.
38.345 + InArcIt(const Digraph&, const Node&) { }
38.346 + /// Sets the iterator to the given arc.
38.347
38.348 - /// This constructor set the iterator to the first incoming arc of
38.349 - /// the node.
38.350 - InArcIt(const Digraph&, const Node&) { }
38.351 - /// Arc -> InArcIt conversion
38.352 -
38.353 - /// Sets the iterator to the value of the trivial iterator \c e.
38.354 - /// This feature necessitates that each time we
38.355 - /// iterate the arc-set, the iteration order is the same.
38.356 + /// Sets the iterator to the given arc of the given digraph.
38.357 + ///
38.358 InArcIt(const Digraph&, const Arc&) { }
38.359 /// Next incoming arc
38.360
38.361 - /// Assign the iterator to the next inarc of the corresponding node.
38.362 - ///
38.363 + /// Assign the iterator to the next
38.364 + /// incoming arc of the corresponding node.
38.365 InArcIt& operator++() { return *this; }
38.366 };
38.367 - /// This iterator goes through each arc.
38.368
38.369 - /// This iterator goes through each arc of a digraph.
38.370 - /// Its usage is quite simple, for example you can count the number
38.371 - /// of arcs in a digraph \c g of type \c Digraph as follows:
38.372 + /// Iterator class for the arcs.
38.373 +
38.374 + /// This iterator goes through each arc of the digraph.
38.375 + /// Its usage is quite simple, for example, you can count the number
38.376 + /// of arcs in a digraph \c g of type \c %Digraph as follows:
38.377 ///\code
38.378 /// int count=0;
38.379 - /// for(Digraph::ArcIt e(g); e!=INVALID; ++e) ++count;
38.380 + /// for(Digraph::ArcIt a(g); a!=INVALID; ++a) ++count;
38.381 ///\endcode
38.382 class ArcIt : public Arc {
38.383 public:
38.384 /// Default constructor
38.385
38.386 - /// @warning The default constructor sets the iterator
38.387 - /// to an undefined value.
38.388 + /// Default constructor.
38.389 + /// \warning It sets the iterator to an undefined value.
38.390 ArcIt() { }
38.391 /// Copy constructor.
38.392
38.393 /// Copy constructor.
38.394 ///
38.395 ArcIt(const ArcIt& e) : Arc(e) { }
38.396 - /// Initialize the iterator to be invalid.
38.397 + /// %Invalid constructor \& conversion.
38.398
38.399 - /// Initialize the iterator to be invalid.
38.400 + /// Initializes the iterator to be invalid.
38.401 + /// \sa Invalid for more details.
38.402 + ArcIt(Invalid) { }
38.403 + /// Sets the iterator to the first arc.
38.404 +
38.405 + /// Sets the iterator to the first arc of the given digraph.
38.406 ///
38.407 - ArcIt(Invalid) { }
38.408 - /// This constructor sets the iterator to the first arc.
38.409 + explicit ArcIt(const Digraph& g) { ignore_unused_variable_warning(g); }
38.410 + /// Sets the iterator to the given arc.
38.411
38.412 - /// This constructor sets the iterator to the first arc of \c g.
38.413 - ///@param g the digraph
38.414 - ArcIt(const Digraph& g) { ignore_unused_variable_warning(g); }
38.415 - /// Arc -> ArcIt conversion
38.416 -
38.417 - /// Sets the iterator to the value of the trivial iterator \c e.
38.418 - /// This feature necessitates that each time we
38.419 - /// iterate the arc-set, the iteration order is the same.
38.420 + /// Sets the iterator to the given arc of the given digraph.
38.421 + ///
38.422 ArcIt(const Digraph&, const Arc&) { }
38.423 - ///Next arc
38.424 + /// Next arc
38.425
38.426 /// Assign the iterator to the next arc.
38.427 + ///
38.428 ArcIt& operator++() { return *this; }
38.429 };
38.430 - ///Gives back the target node of an arc.
38.431
38.432 - ///Gives back the target node of an arc.
38.433 + /// \brief The source node of the arc.
38.434 ///
38.435 - Node target(Arc) const { return INVALID; }
38.436 - ///Gives back the source node of an arc.
38.437 -
38.438 - ///Gives back the source node of an arc.
38.439 - ///
38.440 + /// Returns the source node of the given arc.
38.441 Node source(Arc) const { return INVALID; }
38.442
38.443 - /// \brief Returns the ID of the node.
38.444 + /// \brief The target node of the arc.
38.445 + ///
38.446 + /// Returns the target node of the given arc.
38.447 + Node target(Arc) const { return INVALID; }
38.448 +
38.449 + /// \brief The ID of the node.
38.450 + ///
38.451 + /// Returns the ID of the given node.
38.452 int id(Node) const { return -1; }
38.453
38.454 - /// \brief Returns the ID of the arc.
38.455 + /// \brief The ID of the arc.
38.456 + ///
38.457 + /// Returns the ID of the given arc.
38.458 int id(Arc) const { return -1; }
38.459
38.460 - /// \brief Returns the node with the given ID.
38.461 + /// \brief The node with the given ID.
38.462 ///
38.463 - /// \pre The argument should be a valid node ID in the graph.
38.464 + /// Returns the node with the given ID.
38.465 + /// \pre The argument should be a valid node ID in the digraph.
38.466 Node nodeFromId(int) const { return INVALID; }
38.467
38.468 - /// \brief Returns the arc with the given ID.
38.469 + /// \brief The arc with the given ID.
38.470 ///
38.471 - /// \pre The argument should be a valid arc ID in the graph.
38.472 + /// Returns the arc with the given ID.
38.473 + /// \pre The argument should be a valid arc ID in the digraph.
38.474 Arc arcFromId(int) const { return INVALID; }
38.475
38.476 - /// \brief Returns an upper bound on the node IDs.
38.477 + /// \brief An upper bound on the node IDs.
38.478 + ///
38.479 + /// Returns an upper bound on the node IDs.
38.480 int maxNodeId() const { return -1; }
38.481
38.482 - /// \brief Returns an upper bound on the arc IDs.
38.483 + /// \brief An upper bound on the arc IDs.
38.484 + ///
38.485 + /// Returns an upper bound on the arc IDs.
38.486 int maxArcId() const { return -1; }
38.487
38.488 void first(Node&) const {}
38.489 @@ -392,50 +390,51 @@
38.490 // Dummy parameter.
38.491 int maxId(Arc) const { return -1; }
38.492
38.493 + /// \brief The opposite node on the arc.
38.494 + ///
38.495 + /// Returns the opposite node on the given arc.
38.496 + Node oppositeNode(Node, Arc) const { return INVALID; }
38.497 +
38.498 /// \brief The base node of the iterator.
38.499 ///
38.500 - /// Gives back the base node of the iterator.
38.501 - /// It is always the target of the pointed arc.
38.502 - Node baseNode(const InArcIt&) const { return INVALID; }
38.503 + /// Returns the base node of the given outgoing arc iterator
38.504 + /// (i.e. the source node of the corresponding arc).
38.505 + Node baseNode(OutArcIt) const { return INVALID; }
38.506
38.507 /// \brief The running node of the iterator.
38.508 ///
38.509 - /// Gives back the running node of the iterator.
38.510 - /// It is always the source of the pointed arc.
38.511 - Node runningNode(const InArcIt&) const { return INVALID; }
38.512 + /// Returns the running node of the given outgoing arc iterator
38.513 + /// (i.e. the target node of the corresponding arc).
38.514 + Node runningNode(OutArcIt) const { return INVALID; }
38.515
38.516 /// \brief The base node of the iterator.
38.517 ///
38.518 - /// Gives back the base node of the iterator.
38.519 - /// It is always the source of the pointed arc.
38.520 - Node baseNode(const OutArcIt&) const { return INVALID; }
38.521 + /// Returns the base node of the given incomming arc iterator
38.522 + /// (i.e. the target node of the corresponding arc).
38.523 + Node baseNode(InArcIt) const { return INVALID; }
38.524
38.525 /// \brief The running node of the iterator.
38.526 ///
38.527 - /// Gives back the running node of the iterator.
38.528 - /// It is always the target of the pointed arc.
38.529 - Node runningNode(const OutArcIt&) const { return INVALID; }
38.530 + /// Returns the running node of the given incomming arc iterator
38.531 + /// (i.e. the source node of the corresponding arc).
38.532 + Node runningNode(InArcIt) const { return INVALID; }
38.533
38.534 - /// \brief The opposite node on the given arc.
38.535 + /// \brief Standard graph map type for the nodes.
38.536 ///
38.537 - /// Gives back the opposite node on the given arc.
38.538 - Node oppositeNode(const Node&, const Arc&) const { return INVALID; }
38.539 -
38.540 - /// \brief Reference map of the nodes to type \c T.
38.541 - ///
38.542 - /// Reference map of the nodes to type \c T.
38.543 + /// Standard graph map type for the nodes.
38.544 + /// It conforms to the ReferenceMap concept.
38.545 template<class T>
38.546 class NodeMap : public ReferenceMap<Node, T, T&, const T&> {
38.547 public:
38.548
38.549 - ///\e
38.550 - NodeMap(const Digraph&) { }
38.551 - ///\e
38.552 + /// Constructor
38.553 + explicit NodeMap(const Digraph&) { }
38.554 + /// Constructor with given initial value
38.555 NodeMap(const Digraph&, T) { }
38.556
38.557 private:
38.558 ///Copy constructor
38.559 - NodeMap(const NodeMap& nm) :
38.560 + NodeMap(const NodeMap& nm) :
38.561 ReferenceMap<Node, T, T&, const T&>(nm) { }
38.562 ///Assignment operator
38.563 template <typename CMap>
38.564 @@ -445,17 +444,19 @@
38.565 }
38.566 };
38.567
38.568 - /// \brief Reference map of the arcs to type \c T.
38.569 + /// \brief Standard graph map type for the arcs.
38.570 ///
38.571 - /// Reference map of the arcs to type \c T.
38.572 + /// Standard graph map type for the arcs.
38.573 + /// It conforms to the ReferenceMap concept.
38.574 template<class T>
38.575 class ArcMap : public ReferenceMap<Arc, T, T&, const T&> {
38.576 public:
38.577
38.578 - ///\e
38.579 - ArcMap(const Digraph&) { }
38.580 - ///\e
38.581 + /// Constructor
38.582 + explicit ArcMap(const Digraph&) { }
38.583 + /// Constructor with given initial value
38.584 ArcMap(const Digraph&, T) { }
38.585 +
38.586 private:
38.587 ///Copy constructor
38.588 ArcMap(const ArcMap& em) :
39.1 --- a/lemon/concepts/graph.h Tue Dec 20 17:44:38 2011 +0100
39.2 +++ b/lemon/concepts/graph.h Tue Dec 20 18:15:14 2011 +0100
39.3 @@ -2,7 +2,7 @@
39.4 *
39.5 * This file is a part of LEMON, a generic C++ optimization library.
39.6 *
39.7 - * Copyright (C) 2003-2009
39.8 + * Copyright (C) 2003-2010
39.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
39.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
39.11 *
39.12 @@ -18,12 +18,14 @@
39.13
39.14 ///\ingroup graph_concepts
39.15 ///\file
39.16 -///\brief The concept of Undirected Graphs.
39.17 +///\brief The concept of undirected graphs.
39.18
39.19 #ifndef LEMON_CONCEPTS_GRAPH_H
39.20 #define LEMON_CONCEPTS_GRAPH_H
39.21
39.22 #include <lemon/concepts/graph_components.h>
39.23 +#include <lemon/concepts/maps.h>
39.24 +#include <lemon/concept_check.h>
39.25 #include <lemon/core.h>
39.26
39.27 namespace lemon {
39.28 @@ -31,63 +33,74 @@
39.29
39.30 /// \ingroup graph_concepts
39.31 ///
39.32 - /// \brief Class describing the concept of Undirected Graphs.
39.33 + /// \brief Class describing the concept of undirected graphs.
39.34 ///
39.35 - /// This class describes the common interface of all Undirected
39.36 - /// Graphs.
39.37 + /// This class describes the common interface of all undirected
39.38 + /// graphs.
39.39 ///
39.40 - /// As all concept describing classes it provides only interface
39.41 - /// without any sensible implementation. So any algorithm for
39.42 - /// undirected graph should compile with this class, but it will not
39.43 + /// Like all concept classes, it only provides an interface
39.44 + /// without any sensible implementation. So any general algorithm for
39.45 + /// undirected graphs should compile with this class, but it will not
39.46 /// run properly, of course.
39.47 + /// An actual graph implementation like \ref ListGraph or
39.48 + /// \ref SmartGraph may have additional functionality.
39.49 ///
39.50 - /// The LEMON undirected graphs also fulfill the concept of
39.51 - /// directed graphs (\ref lemon::concepts::Digraph "Digraph
39.52 - /// Concept"). Each edges can be seen as two opposite
39.53 - /// directed arc and consequently the undirected graph can be
39.54 - /// seen as the direceted graph of these directed arcs. The
39.55 - /// Graph has the Edge inner class for the edges and
39.56 - /// the Arc type for the directed arcs. The Arc type is
39.57 - /// convertible to Edge or inherited from it so from a directed
39.58 - /// arc we can get the represented edge.
39.59 + /// The undirected graphs also fulfill the concept of \ref Digraph
39.60 + /// "directed graphs", since each edge can also be regarded as two
39.61 + /// oppositely directed arcs.
39.62 + /// Undirected graphs provide an Edge type for the undirected edges and
39.63 + /// an Arc type for the directed arcs. The Arc type is convertible to
39.64 + /// Edge or inherited from it, i.e. the corresponding edge can be
39.65 + /// obtained from an arc.
39.66 + /// EdgeIt and EdgeMap classes can be used for the edges, while ArcIt
39.67 + /// and ArcMap classes can be used for the arcs (just like in digraphs).
39.68 + /// Both InArcIt and OutArcIt iterates on the same edges but with
39.69 + /// opposite direction. IncEdgeIt also iterates on the same edges
39.70 + /// as OutArcIt and InArcIt, but it is not convertible to Arc,
39.71 + /// only to Edge.
39.72 ///
39.73 - /// In the sense of the LEMON each edge has a default
39.74 - /// direction (it should be in every computer implementation,
39.75 - /// because the order of edge's nodes defines an
39.76 - /// orientation). With the default orientation we can define that
39.77 - /// the directed arc is forward or backward directed. With the \c
39.78 - /// direction() and \c direct() function we can get the direction
39.79 - /// of the directed arc and we can direct an edge.
39.80 + /// In LEMON, each undirected edge has an inherent orientation.
39.81 + /// Thus it can defined if an arc is forward or backward oriented in
39.82 + /// an undirected graph with respect to this default oriantation of
39.83 + /// the represented edge.
39.84 + /// With the direction() and direct() functions the direction
39.85 + /// of an arc can be obtained and set, respectively.
39.86 ///
39.87 - /// The EdgeIt is an iterator for the edges. We can use
39.88 - /// the EdgeMap to map values for the edges. The InArcIt and
39.89 - /// OutArcIt iterates on the same edges but with opposite
39.90 - /// direction. The IncEdgeIt iterates also on the same edges
39.91 - /// as the OutArcIt and InArcIt but it is not convertible to Arc just
39.92 - /// to Edge.
39.93 + /// Only nodes and edges can be added to or removed from an undirected
39.94 + /// graph and the corresponding arcs are added or removed automatically.
39.95 + ///
39.96 + /// \sa Digraph
39.97 class Graph {
39.98 + private:
39.99 + /// Graphs are \e not copy constructible. Use DigraphCopy instead.
39.100 + Graph(const Graph&) {}
39.101 + /// \brief Assignment of a graph to another one is \e not allowed.
39.102 + /// Use DigraphCopy instead.
39.103 + void operator=(const Graph&) {}
39.104 +
39.105 public:
39.106 - /// \brief The undirected graph should be tagged by the
39.107 - /// UndirectedTag.
39.108 + /// Default constructor.
39.109 + Graph() {}
39.110 +
39.111 + /// \brief Undirected graphs should be tagged with \c UndirectedTag.
39.112 ///
39.113 - /// The undirected graph should be tagged by the UndirectedTag. This
39.114 - /// tag helps the enable_if technics to make compile time
39.115 + /// Undirected graphs should be tagged with \c UndirectedTag.
39.116 + ///
39.117 + /// This tag helps the \c enable_if technics to make compile time
39.118 /// specializations for undirected graphs.
39.119 typedef True UndirectedTag;
39.120
39.121 - /// \brief The base type of node iterators,
39.122 - /// or in other words, the trivial node iterator.
39.123 - ///
39.124 - /// This is the base type of each node iterator,
39.125 - /// thus each kind of node iterator converts to this.
39.126 - /// More precisely each kind of node iterator should be inherited
39.127 - /// from the trivial node iterator.
39.128 + /// The node type of the graph
39.129 +
39.130 + /// This class identifies a node of the graph. It also serves
39.131 + /// as a base class of the node iterators,
39.132 + /// thus they convert to this type.
39.133 class Node {
39.134 public:
39.135 /// Default constructor
39.136
39.137 - /// @warning The default constructor sets the iterator
39.138 - /// to an undefined value.
39.139 + /// Default constructor.
39.140 + /// \warning It sets the object to an undefined value.
39.141 Node() { }
39.142 /// Copy constructor.
39.143
39.144 @@ -95,40 +108,40 @@
39.145 ///
39.146 Node(const Node&) { }
39.147
39.148 - /// Invalid constructor \& conversion.
39.149 + /// %Invalid constructor \& conversion.
39.150
39.151 - /// This constructor initializes the iterator to be invalid.
39.152 + /// Initializes the object to be invalid.
39.153 /// \sa Invalid for more details.
39.154 Node(Invalid) { }
39.155 /// Equality operator
39.156
39.157 + /// Equality operator.
39.158 + ///
39.159 /// Two iterators are equal if and only if they point to the
39.160 - /// same object or both are invalid.
39.161 + /// same object or both are \c INVALID.
39.162 bool operator==(Node) const { return true; }
39.163
39.164 /// Inequality operator
39.165
39.166 - /// \sa operator==(Node n)
39.167 - ///
39.168 + /// Inequality operator.
39.169 bool operator!=(Node) const { return true; }
39.170
39.171 /// Artificial ordering operator.
39.172
39.173 - /// To allow the use of graph descriptors as key type in std::map or
39.174 - /// similar associative container we require this.
39.175 + /// Artificial ordering operator.
39.176 ///
39.177 - /// \note This operator only have to define some strict ordering of
39.178 + /// \note This operator only has to define some strict ordering of
39.179 /// the items; this order has nothing to do with the iteration
39.180 /// ordering of the items.
39.181 bool operator<(Node) const { return false; }
39.182
39.183 };
39.184
39.185 - /// This iterator goes through each node.
39.186 + /// Iterator class for the nodes.
39.187
39.188 - /// This iterator goes through each node.
39.189 - /// Its usage is quite simple, for example you can count the number
39.190 - /// of nodes in graph \c g of type \c Graph like this:
39.191 + /// This iterator goes through each node of the graph.
39.192 + /// Its usage is quite simple, for example, you can count the number
39.193 + /// of nodes in a graph \c g of type \c %Graph like this:
39.194 ///\code
39.195 /// int count=0;
39.196 /// for (Graph::NodeIt n(g); n!=INVALID; ++n) ++count;
39.197 @@ -137,30 +150,28 @@
39.198 public:
39.199 /// Default constructor
39.200
39.201 - /// @warning The default constructor sets the iterator
39.202 - /// to an undefined value.
39.203 + /// Default constructor.
39.204 + /// \warning It sets the iterator to an undefined value.
39.205 NodeIt() { }
39.206 /// Copy constructor.
39.207
39.208 /// Copy constructor.
39.209 ///
39.210 NodeIt(const NodeIt& n) : Node(n) { }
39.211 - /// Invalid constructor \& conversion.
39.212 + /// %Invalid constructor \& conversion.
39.213
39.214 - /// Initialize the iterator to be invalid.
39.215 + /// Initializes the iterator to be invalid.
39.216 /// \sa Invalid for more details.
39.217 NodeIt(Invalid) { }
39.218 /// Sets the iterator to the first node.
39.219
39.220 - /// Sets the iterator to the first node of \c g.
39.221 + /// Sets the iterator to the first node of the given digraph.
39.222 ///
39.223 - NodeIt(const Graph&) { }
39.224 - /// Node -> NodeIt conversion.
39.225 + explicit NodeIt(const Graph&) { }
39.226 + /// Sets the iterator to the given node.
39.227
39.228 - /// Sets the iterator to the node of \c the graph pointed by
39.229 - /// the trivial iterator.
39.230 - /// This feature necessitates that each time we
39.231 - /// iterate the arc-set, the iteration order is the same.
39.232 + /// Sets the iterator to the given node of the given digraph.
39.233 + ///
39.234 NodeIt(const Graph&, const Node&) { }
39.235 /// Next node.
39.236
39.237 @@ -170,54 +181,55 @@
39.238 };
39.239
39.240
39.241 - /// The base type of the edge iterators.
39.242 + /// The edge type of the graph
39.243
39.244 - /// The base type of the edge iterators.
39.245 - ///
39.246 + /// This class identifies an edge of the graph. It also serves
39.247 + /// as a base class of the edge iterators,
39.248 + /// thus they will convert to this type.
39.249 class Edge {
39.250 public:
39.251 /// Default constructor
39.252
39.253 - /// @warning The default constructor sets the iterator
39.254 - /// to an undefined value.
39.255 + /// Default constructor.
39.256 + /// \warning It sets the object to an undefined value.
39.257 Edge() { }
39.258 /// Copy constructor.
39.259
39.260 /// Copy constructor.
39.261 ///
39.262 Edge(const Edge&) { }
39.263 - /// Initialize the iterator to be invalid.
39.264 + /// %Invalid constructor \& conversion.
39.265
39.266 - /// Initialize the iterator to be invalid.
39.267 - ///
39.268 + /// Initializes the object to be invalid.
39.269 + /// \sa Invalid for more details.
39.270 Edge(Invalid) { }
39.271 /// Equality operator
39.272
39.273 + /// Equality operator.
39.274 + ///
39.275 /// Two iterators are equal if and only if they point to the
39.276 - /// same object or both are invalid.
39.277 + /// same object or both are \c INVALID.
39.278 bool operator==(Edge) const { return true; }
39.279 /// Inequality operator
39.280
39.281 - /// \sa operator==(Edge n)
39.282 - ///
39.283 + /// Inequality operator.
39.284 bool operator!=(Edge) const { return true; }
39.285
39.286 /// Artificial ordering operator.
39.287
39.288 - /// To allow the use of graph descriptors as key type in std::map or
39.289 - /// similar associative container we require this.
39.290 + /// Artificial ordering operator.
39.291 ///
39.292 - /// \note This operator only have to define some strict ordering of
39.293 - /// the items; this order has nothing to do with the iteration
39.294 - /// ordering of the items.
39.295 + /// \note This operator only has to define some strict ordering of
39.296 + /// the edges; this order has nothing to do with the iteration
39.297 + /// ordering of the edges.
39.298 bool operator<(Edge) const { return false; }
39.299 };
39.300
39.301 - /// This iterator goes through each edge.
39.302 + /// Iterator class for the edges.
39.303
39.304 - /// This iterator goes through each edge of a graph.
39.305 - /// Its usage is quite simple, for example you can count the number
39.306 - /// of edges in a graph \c g of type \c Graph as follows:
39.307 + /// This iterator goes through each edge of the graph.
39.308 + /// Its usage is quite simple, for example, you can count the number
39.309 + /// of edges in a graph \c g of type \c %Graph as follows:
39.310 ///\code
39.311 /// int count=0;
39.312 /// for(Graph::EdgeIt e(g); e!=INVALID; ++e) ++count;
39.313 @@ -226,290 +238,285 @@
39.314 public:
39.315 /// Default constructor
39.316
39.317 - /// @warning The default constructor sets the iterator
39.318 - /// to an undefined value.
39.319 + /// Default constructor.
39.320 + /// \warning It sets the iterator to an undefined value.
39.321 EdgeIt() { }
39.322 /// Copy constructor.
39.323
39.324 /// Copy constructor.
39.325 ///
39.326 EdgeIt(const EdgeIt& e) : Edge(e) { }
39.327 - /// Initialize the iterator to be invalid.
39.328 + /// %Invalid constructor \& conversion.
39.329
39.330 - /// Initialize the iterator to be invalid.
39.331 + /// Initializes the iterator to be invalid.
39.332 + /// \sa Invalid for more details.
39.333 + EdgeIt(Invalid) { }
39.334 + /// Sets the iterator to the first edge.
39.335 +
39.336 + /// Sets the iterator to the first edge of the given graph.
39.337 ///
39.338 - EdgeIt(Invalid) { }
39.339 - /// This constructor sets the iterator to the first edge.
39.340 + explicit EdgeIt(const Graph&) { }
39.341 + /// Sets the iterator to the given edge.
39.342
39.343 - /// This constructor sets the iterator to the first edge.
39.344 - EdgeIt(const Graph&) { }
39.345 - /// Edge -> EdgeIt conversion
39.346 -
39.347 - /// Sets the iterator to the value of the trivial iterator.
39.348 - /// This feature necessitates that each time we
39.349 - /// iterate the edge-set, the iteration order is the
39.350 - /// same.
39.351 + /// Sets the iterator to the given edge of the given graph.
39.352 + ///
39.353 EdgeIt(const Graph&, const Edge&) { }
39.354 /// Next edge
39.355
39.356 /// Assign the iterator to the next edge.
39.357 + ///
39.358 EdgeIt& operator++() { return *this; }
39.359 };
39.360
39.361 - /// \brief This iterator goes trough the incident undirected
39.362 - /// arcs of a node.
39.363 - ///
39.364 - /// This iterator goes trough the incident edges
39.365 - /// of a certain node of a graph. You should assume that the
39.366 - /// loop arcs will be iterated twice.
39.367 - ///
39.368 - /// Its usage is quite simple, for example you can compute the
39.369 - /// degree (i.e. count the number of incident arcs of a node \c n
39.370 - /// in graph \c g of type \c Graph as follows.
39.371 + /// Iterator class for the incident edges of a node.
39.372 +
39.373 + /// This iterator goes trough the incident undirected edges
39.374 + /// of a certain node of a graph.
39.375 + /// Its usage is quite simple, for example, you can compute the
39.376 + /// degree (i.e. the number of incident edges) of a node \c n
39.377 + /// in a graph \c g of type \c %Graph as follows.
39.378 ///
39.379 ///\code
39.380 /// int count=0;
39.381 /// for(Graph::IncEdgeIt e(g, n); e!=INVALID; ++e) ++count;
39.382 ///\endcode
39.383 + ///
39.384 + /// \warning Loop edges will be iterated twice.
39.385 class IncEdgeIt : public Edge {
39.386 public:
39.387 /// Default constructor
39.388
39.389 - /// @warning The default constructor sets the iterator
39.390 - /// to an undefined value.
39.391 + /// Default constructor.
39.392 + /// \warning It sets the iterator to an undefined value.
39.393 IncEdgeIt() { }
39.394 /// Copy constructor.
39.395
39.396 /// Copy constructor.
39.397 ///
39.398 IncEdgeIt(const IncEdgeIt& e) : Edge(e) { }
39.399 - /// Initialize the iterator to be invalid.
39.400 + /// %Invalid constructor \& conversion.
39.401
39.402 - /// Initialize the iterator to be invalid.
39.403 + /// Initializes the iterator to be invalid.
39.404 + /// \sa Invalid for more details.
39.405 + IncEdgeIt(Invalid) { }
39.406 + /// Sets the iterator to the first incident edge.
39.407 +
39.408 + /// Sets the iterator to the first incident edge of the given node.
39.409 ///
39.410 - IncEdgeIt(Invalid) { }
39.411 - /// This constructor sets the iterator to first incident arc.
39.412 + IncEdgeIt(const Graph&, const Node&) { }
39.413 + /// Sets the iterator to the given edge.
39.414
39.415 - /// This constructor set the iterator to the first incident arc of
39.416 - /// the node.
39.417 - IncEdgeIt(const Graph&, const Node&) { }
39.418 - /// Edge -> IncEdgeIt conversion
39.419 + /// Sets the iterator to the given edge of the given graph.
39.420 + ///
39.421 + IncEdgeIt(const Graph&, const Edge&) { }
39.422 + /// Next incident edge
39.423
39.424 - /// Sets the iterator to the value of the trivial iterator \c e.
39.425 - /// This feature necessitates that each time we
39.426 - /// iterate the arc-set, the iteration order is the same.
39.427 - IncEdgeIt(const Graph&, const Edge&) { }
39.428 - /// Next incident arc
39.429 -
39.430 - /// Assign the iterator to the next incident arc
39.431 + /// Assign the iterator to the next incident edge
39.432 /// of the corresponding node.
39.433 IncEdgeIt& operator++() { return *this; }
39.434 };
39.435
39.436 - /// The directed arc type.
39.437 + /// The arc type of the graph
39.438
39.439 - /// The directed arc type. It can be converted to the
39.440 - /// edge or it should be inherited from the undirected
39.441 - /// edge.
39.442 + /// This class identifies a directed arc of the graph. It also serves
39.443 + /// as a base class of the arc iterators,
39.444 + /// thus they will convert to this type.
39.445 class Arc {
39.446 public:
39.447 /// Default constructor
39.448
39.449 - /// @warning The default constructor sets the iterator
39.450 - /// to an undefined value.
39.451 + /// Default constructor.
39.452 + /// \warning It sets the object to an undefined value.
39.453 Arc() { }
39.454 /// Copy constructor.
39.455
39.456 /// Copy constructor.
39.457 ///
39.458 Arc(const Arc&) { }
39.459 - /// Initialize the iterator to be invalid.
39.460 + /// %Invalid constructor \& conversion.
39.461
39.462 - /// Initialize the iterator to be invalid.
39.463 - ///
39.464 + /// Initializes the object to be invalid.
39.465 + /// \sa Invalid for more details.
39.466 Arc(Invalid) { }
39.467 /// Equality operator
39.468
39.469 + /// Equality operator.
39.470 + ///
39.471 /// Two iterators are equal if and only if they point to the
39.472 - /// same object or both are invalid.
39.473 + /// same object or both are \c INVALID.
39.474 bool operator==(Arc) const { return true; }
39.475 /// Inequality operator
39.476
39.477 - /// \sa operator==(Arc n)
39.478 - ///
39.479 + /// Inequality operator.
39.480 bool operator!=(Arc) const { return true; }
39.481
39.482 /// Artificial ordering operator.
39.483
39.484 - /// To allow the use of graph descriptors as key type in std::map or
39.485 - /// similar associative container we require this.
39.486 + /// Artificial ordering operator.
39.487 ///
39.488 - /// \note This operator only have to define some strict ordering of
39.489 - /// the items; this order has nothing to do with the iteration
39.490 - /// ordering of the items.
39.491 + /// \note This operator only has to define some strict ordering of
39.492 + /// the arcs; this order has nothing to do with the iteration
39.493 + /// ordering of the arcs.
39.494 bool operator<(Arc) const { return false; }
39.495
39.496 - /// Converison to Edge
39.497 + /// Converison to \c Edge
39.498 +
39.499 + /// Converison to \c Edge.
39.500 + ///
39.501 operator Edge() const { return Edge(); }
39.502 };
39.503 - /// This iterator goes through each directed arc.
39.504
39.505 - /// This iterator goes through each arc of a graph.
39.506 - /// Its usage is quite simple, for example you can count the number
39.507 - /// of arcs in a graph \c g of type \c Graph as follows:
39.508 + /// Iterator class for the arcs.
39.509 +
39.510 + /// This iterator goes through each directed arc of the graph.
39.511 + /// Its usage is quite simple, for example, you can count the number
39.512 + /// of arcs in a graph \c g of type \c %Graph as follows:
39.513 ///\code
39.514 /// int count=0;
39.515 - /// for(Graph::ArcIt e(g); e!=INVALID; ++e) ++count;
39.516 + /// for(Graph::ArcIt a(g); a!=INVALID; ++a) ++count;
39.517 ///\endcode
39.518 class ArcIt : public Arc {
39.519 public:
39.520 /// Default constructor
39.521
39.522 - /// @warning The default constructor sets the iterator
39.523 - /// to an undefined value.
39.524 + /// Default constructor.
39.525 + /// \warning It sets the iterator to an undefined value.
39.526 ArcIt() { }
39.527 /// Copy constructor.
39.528
39.529 /// Copy constructor.
39.530 ///
39.531 ArcIt(const ArcIt& e) : Arc(e) { }
39.532 - /// Initialize the iterator to be invalid.
39.533 + /// %Invalid constructor \& conversion.
39.534
39.535 - /// Initialize the iterator to be invalid.
39.536 + /// Initializes the iterator to be invalid.
39.537 + /// \sa Invalid for more details.
39.538 + ArcIt(Invalid) { }
39.539 + /// Sets the iterator to the first arc.
39.540 +
39.541 + /// Sets the iterator to the first arc of the given graph.
39.542 ///
39.543 - ArcIt(Invalid) { }
39.544 - /// This constructor sets the iterator to the first arc.
39.545 + explicit ArcIt(const Graph &g) { ignore_unused_variable_warning(g); }
39.546 + /// Sets the iterator to the given arc.
39.547
39.548 - /// This constructor sets the iterator to the first arc of \c g.
39.549 - ///@param g the graph
39.550 - ArcIt(const Graph &g) { ignore_unused_variable_warning(g); }
39.551 - /// Arc -> ArcIt conversion
39.552 -
39.553 - /// Sets the iterator to the value of the trivial iterator \c e.
39.554 - /// This feature necessitates that each time we
39.555 - /// iterate the arc-set, the iteration order is the same.
39.556 + /// Sets the iterator to the given arc of the given graph.
39.557 + ///
39.558 ArcIt(const Graph&, const Arc&) { }
39.559 - ///Next arc
39.560 + /// Next arc
39.561
39.562 /// Assign the iterator to the next arc.
39.563 + ///
39.564 ArcIt& operator++() { return *this; }
39.565 };
39.566
39.567 - /// This iterator goes trough the outgoing directed arcs of a node.
39.568 + /// Iterator class for the outgoing arcs of a node.
39.569
39.570 - /// This iterator goes trough the \e outgoing arcs of a certain node
39.571 - /// of a graph.
39.572 - /// Its usage is quite simple, for example you can count the number
39.573 + /// This iterator goes trough the \e outgoing directed arcs of a
39.574 + /// certain node of a graph.
39.575 + /// Its usage is quite simple, for example, you can count the number
39.576 /// of outgoing arcs of a node \c n
39.577 - /// in graph \c g of type \c Graph as follows.
39.578 + /// in a graph \c g of type \c %Graph as follows.
39.579 ///\code
39.580 /// int count=0;
39.581 - /// for (Graph::OutArcIt e(g, n); e!=INVALID; ++e) ++count;
39.582 + /// for (Digraph::OutArcIt a(g, n); a!=INVALID; ++a) ++count;
39.583 ///\endcode
39.584 -
39.585 class OutArcIt : public Arc {
39.586 public:
39.587 /// Default constructor
39.588
39.589 - /// @warning The default constructor sets the iterator
39.590 - /// to an undefined value.
39.591 + /// Default constructor.
39.592 + /// \warning It sets the iterator to an undefined value.
39.593 OutArcIt() { }
39.594 /// Copy constructor.
39.595
39.596 /// Copy constructor.
39.597 ///
39.598 OutArcIt(const OutArcIt& e) : Arc(e) { }
39.599 - /// Initialize the iterator to be invalid.
39.600 + /// %Invalid constructor \& conversion.
39.601
39.602 - /// Initialize the iterator to be invalid.
39.603 + /// Initializes the iterator to be invalid.
39.604 + /// \sa Invalid for more details.
39.605 + OutArcIt(Invalid) { }
39.606 + /// Sets the iterator to the first outgoing arc.
39.607 +
39.608 + /// Sets the iterator to the first outgoing arc of the given node.
39.609 ///
39.610 - OutArcIt(Invalid) { }
39.611 - /// This constructor sets the iterator to the first outgoing arc.
39.612 -
39.613 - /// This constructor sets the iterator to the first outgoing arc of
39.614 - /// the node.
39.615 - ///@param n the node
39.616 - ///@param g the graph
39.617 OutArcIt(const Graph& n, const Node& g) {
39.618 ignore_unused_variable_warning(n);
39.619 ignore_unused_variable_warning(g);
39.620 }
39.621 - /// Arc -> OutArcIt conversion
39.622 + /// Sets the iterator to the given arc.
39.623
39.624 - /// Sets the iterator to the value of the trivial iterator.
39.625 - /// This feature necessitates that each time we
39.626 - /// iterate the arc-set, the iteration order is the same.
39.627 + /// Sets the iterator to the given arc of the given graph.
39.628 + ///
39.629 OutArcIt(const Graph&, const Arc&) { }
39.630 - ///Next outgoing arc
39.631 + /// Next outgoing arc
39.632
39.633 /// Assign the iterator to the next
39.634 /// outgoing arc of the corresponding node.
39.635 OutArcIt& operator++() { return *this; }
39.636 };
39.637
39.638 - /// This iterator goes trough the incoming directed arcs of a node.
39.639 + /// Iterator class for the incoming arcs of a node.
39.640
39.641 - /// This iterator goes trough the \e incoming arcs of a certain node
39.642 - /// of a graph.
39.643 - /// Its usage is quite simple, for example you can count the number
39.644 - /// of outgoing arcs of a node \c n
39.645 - /// in graph \c g of type \c Graph as follows.
39.646 + /// This iterator goes trough the \e incoming directed arcs of a
39.647 + /// certain node of a graph.
39.648 + /// Its usage is quite simple, for example, you can count the number
39.649 + /// of incoming arcs of a node \c n
39.650 + /// in a graph \c g of type \c %Graph as follows.
39.651 ///\code
39.652 /// int count=0;
39.653 - /// for(Graph::InArcIt e(g, n); e!=INVALID; ++e) ++count;
39.654 + /// for (Digraph::InArcIt a(g, n); a!=INVALID; ++a) ++count;
39.655 ///\endcode
39.656 -
39.657 class InArcIt : public Arc {
39.658 public:
39.659 /// Default constructor
39.660
39.661 - /// @warning The default constructor sets the iterator
39.662 - /// to an undefined value.
39.663 + /// Default constructor.
39.664 + /// \warning It sets the iterator to an undefined value.
39.665 InArcIt() { }
39.666 /// Copy constructor.
39.667
39.668 /// Copy constructor.
39.669 ///
39.670 InArcIt(const InArcIt& e) : Arc(e) { }
39.671 - /// Initialize the iterator to be invalid.
39.672 + /// %Invalid constructor \& conversion.
39.673
39.674 - /// Initialize the iterator to be invalid.
39.675 + /// Initializes the iterator to be invalid.
39.676 + /// \sa Invalid for more details.
39.677 + InArcIt(Invalid) { }
39.678 + /// Sets the iterator to the first incoming arc.
39.679 +
39.680 + /// Sets the iterator to the first incoming arc of the given node.
39.681 ///
39.682 - InArcIt(Invalid) { }
39.683 - /// This constructor sets the iterator to first incoming arc.
39.684 -
39.685 - /// This constructor set the iterator to the first incoming arc of
39.686 - /// the node.
39.687 - ///@param n the node
39.688 - ///@param g the graph
39.689 InArcIt(const Graph& g, const Node& n) {
39.690 ignore_unused_variable_warning(n);
39.691 ignore_unused_variable_warning(g);
39.692 }
39.693 - /// Arc -> InArcIt conversion
39.694 + /// Sets the iterator to the given arc.
39.695
39.696 - /// Sets the iterator to the value of the trivial iterator \c e.
39.697 - /// This feature necessitates that each time we
39.698 - /// iterate the arc-set, the iteration order is the same.
39.699 + /// Sets the iterator to the given arc of the given graph.
39.700 + ///
39.701 InArcIt(const Graph&, const Arc&) { }
39.702 /// Next incoming arc
39.703
39.704 - /// Assign the iterator to the next inarc of the corresponding node.
39.705 - ///
39.706 + /// Assign the iterator to the next
39.707 + /// incoming arc of the corresponding node.
39.708 InArcIt& operator++() { return *this; }
39.709 };
39.710
39.711 - /// \brief Reference map of the nodes to type \c T.
39.712 + /// \brief Standard graph map type for the nodes.
39.713 ///
39.714 - /// Reference map of the nodes to type \c T.
39.715 + /// Standard graph map type for the nodes.
39.716 + /// It conforms to the ReferenceMap concept.
39.717 template<class T>
39.718 class NodeMap : public ReferenceMap<Node, T, T&, const T&>
39.719 {
39.720 public:
39.721
39.722 - ///\e
39.723 - NodeMap(const Graph&) { }
39.724 - ///\e
39.725 + /// Constructor
39.726 + explicit NodeMap(const Graph&) { }
39.727 + /// Constructor with given initial value
39.728 NodeMap(const Graph&, T) { }
39.729
39.730 private:
39.731 @@ -524,18 +531,20 @@
39.732 }
39.733 };
39.734
39.735 - /// \brief Reference map of the arcs to type \c T.
39.736 + /// \brief Standard graph map type for the arcs.
39.737 ///
39.738 - /// Reference map of the arcs to type \c T.
39.739 + /// Standard graph map type for the arcs.
39.740 + /// It conforms to the ReferenceMap concept.
39.741 template<class T>
39.742 class ArcMap : public ReferenceMap<Arc, T, T&, const T&>
39.743 {
39.744 public:
39.745
39.746 - ///\e
39.747 - ArcMap(const Graph&) { }
39.748 - ///\e
39.749 + /// Constructor
39.750 + explicit ArcMap(const Graph&) { }
39.751 + /// Constructor with given initial value
39.752 ArcMap(const Graph&, T) { }
39.753 +
39.754 private:
39.755 ///Copy constructor
39.756 ArcMap(const ArcMap& em) :
39.757 @@ -548,18 +557,20 @@
39.758 }
39.759 };
39.760
39.761 - /// Reference map of the edges to type \c T.
39.762 -
39.763 - /// Reference map of the edges to type \c T.
39.764 + /// \brief Standard graph map type for the edges.
39.765 + ///
39.766 + /// Standard graph map type for the edges.
39.767 + /// It conforms to the ReferenceMap concept.
39.768 template<class T>
39.769 class EdgeMap : public ReferenceMap<Edge, T, T&, const T&>
39.770 {
39.771 public:
39.772
39.773 - ///\e
39.774 - EdgeMap(const Graph&) { }
39.775 - ///\e
39.776 + /// Constructor
39.777 + explicit EdgeMap(const Graph&) { }
39.778 + /// Constructor with given initial value
39.779 EdgeMap(const Graph&, T) { }
39.780 +
39.781 private:
39.782 ///Copy constructor
39.783 EdgeMap(const EdgeMap& em) :
39.784 @@ -572,107 +583,124 @@
39.785 }
39.786 };
39.787
39.788 - /// \brief Direct the given edge.
39.789 + /// \brief The first node of the edge.
39.790 ///
39.791 - /// Direct the given edge. The returned arc source
39.792 - /// will be the given node.
39.793 - Arc direct(const Edge&, const Node&) const {
39.794 - return INVALID;
39.795 - }
39.796 -
39.797 - /// \brief Direct the given edge.
39.798 + /// Returns the first node of the given edge.
39.799 ///
39.800 - /// Direct the given edge. The returned arc
39.801 - /// represents the given edge and the direction comes
39.802 - /// from the bool parameter. The source of the edge and
39.803 - /// the directed arc is the same when the given bool is true.
39.804 - Arc direct(const Edge&, bool) const {
39.805 - return INVALID;
39.806 - }
39.807 -
39.808 - /// \brief Returns true if the arc has default orientation.
39.809 - ///
39.810 - /// Returns whether the given directed arc is same orientation as
39.811 - /// the corresponding edge's default orientation.
39.812 - bool direction(Arc) const { return true; }
39.813 -
39.814 - /// \brief Returns the opposite directed arc.
39.815 - ///
39.816 - /// Returns the opposite directed arc.
39.817 - Arc oppositeArc(Arc) const { return INVALID; }
39.818 -
39.819 - /// \brief Opposite node on an arc
39.820 - ///
39.821 - /// \return The opposite of the given node on the given edge.
39.822 - Node oppositeNode(Node, Edge) const { return INVALID; }
39.823 -
39.824 - /// \brief First node of the edge.
39.825 - ///
39.826 - /// \return The first node of the given edge.
39.827 - ///
39.828 - /// Naturally edges don't have direction and thus
39.829 - /// don't have source and target node. However we use \c u() and \c v()
39.830 - /// methods to query the two nodes of the arc. The direction of the
39.831 - /// arc which arises this way is called the inherent direction of the
39.832 - /// edge, and is used to define the "default" direction
39.833 - /// of the directed versions of the arcs.
39.834 + /// Edges don't have source and target nodes, however, methods
39.835 + /// u() and v() are used to query the two end-nodes of an edge.
39.836 + /// The orientation of an edge that arises this way is called
39.837 + /// the inherent direction, it is used to define the default
39.838 + /// direction for the corresponding arcs.
39.839 /// \sa v()
39.840 /// \sa direction()
39.841 Node u(Edge) const { return INVALID; }
39.842
39.843 - /// \brief Second node of the edge.
39.844 + /// \brief The second node of the edge.
39.845 ///
39.846 - /// \return The second node of the given edge.
39.847 + /// Returns the second node of the given edge.
39.848 ///
39.849 - /// Naturally edges don't have direction and thus
39.850 - /// don't have source and target node. However we use \c u() and \c v()
39.851 - /// methods to query the two nodes of the arc. The direction of the
39.852 - /// arc which arises this way is called the inherent direction of the
39.853 - /// edge, and is used to define the "default" direction
39.854 - /// of the directed versions of the arcs.
39.855 + /// Edges don't have source and target nodes, however, methods
39.856 + /// u() and v() are used to query the two end-nodes of an edge.
39.857 + /// The orientation of an edge that arises this way is called
39.858 + /// the inherent direction, it is used to define the default
39.859 + /// direction for the corresponding arcs.
39.860 /// \sa u()
39.861 /// \sa direction()
39.862 Node v(Edge) const { return INVALID; }
39.863
39.864 - /// \brief Source node of the directed arc.
39.865 + /// \brief The source node of the arc.
39.866 + ///
39.867 + /// Returns the source node of the given arc.
39.868 Node source(Arc) const { return INVALID; }
39.869
39.870 - /// \brief Target node of the directed arc.
39.871 + /// \brief The target node of the arc.
39.872 + ///
39.873 + /// Returns the target node of the given arc.
39.874 Node target(Arc) const { return INVALID; }
39.875
39.876 - /// \brief Returns the id of the node.
39.877 + /// \brief The ID of the node.
39.878 + ///
39.879 + /// Returns the ID of the given node.
39.880 int id(Node) const { return -1; }
39.881
39.882 - /// \brief Returns the id of the edge.
39.883 + /// \brief The ID of the edge.
39.884 + ///
39.885 + /// Returns the ID of the given edge.
39.886 int id(Edge) const { return -1; }
39.887
39.888 - /// \brief Returns the id of the arc.
39.889 + /// \brief The ID of the arc.
39.890 + ///
39.891 + /// Returns the ID of the given arc.
39.892 int id(Arc) const { return -1; }
39.893
39.894 - /// \brief Returns the node with the given id.
39.895 + /// \brief The node with the given ID.
39.896 ///
39.897 - /// \pre The argument should be a valid node id in the graph.
39.898 + /// Returns the node with the given ID.
39.899 + /// \pre The argument should be a valid node ID in the graph.
39.900 Node nodeFromId(int) const { return INVALID; }
39.901
39.902 - /// \brief Returns the edge with the given id.
39.903 + /// \brief The edge with the given ID.
39.904 ///
39.905 - /// \pre The argument should be a valid edge id in the graph.
39.906 + /// Returns the edge with the given ID.
39.907 + /// \pre The argument should be a valid edge ID in the graph.
39.908 Edge edgeFromId(int) const { return INVALID; }
39.909
39.910 - /// \brief Returns the arc with the given id.
39.911 + /// \brief The arc with the given ID.
39.912 ///
39.913 - /// \pre The argument should be a valid arc id in the graph.
39.914 + /// Returns the arc with the given ID.
39.915 + /// \pre The argument should be a valid arc ID in the graph.
39.916 Arc arcFromId(int) const { return INVALID; }
39.917
39.918 - /// \brief Returns an upper bound on the node IDs.
39.919 + /// \brief An upper bound on the node IDs.
39.920 + ///
39.921 + /// Returns an upper bound on the node IDs.
39.922 int maxNodeId() const { return -1; }
39.923
39.924 - /// \brief Returns an upper bound on the edge IDs.
39.925 + /// \brief An upper bound on the edge IDs.
39.926 + ///
39.927 + /// Returns an upper bound on the edge IDs.
39.928 int maxEdgeId() const { return -1; }
39.929
39.930 - /// \brief Returns an upper bound on the arc IDs.
39.931 + /// \brief An upper bound on the arc IDs.
39.932 + ///
39.933 + /// Returns an upper bound on the arc IDs.
39.934 int maxArcId() const { return -1; }
39.935
39.936 + /// \brief The direction of the arc.
39.937 + ///
39.938 + /// Returns \c true if the direction of the given arc is the same as
39.939 + /// the inherent orientation of the represented edge.
39.940 + bool direction(Arc) const { return true; }
39.941 +
39.942 + /// \brief Direct the edge.
39.943 + ///
39.944 + /// Direct the given edge. The returned arc
39.945 + /// represents the given edge and its direction comes
39.946 + /// from the bool parameter. If it is \c true, then the direction
39.947 + /// of the arc is the same as the inherent orientation of the edge.
39.948 + Arc direct(Edge, bool) const {
39.949 + return INVALID;
39.950 + }
39.951 +
39.952 + /// \brief Direct the edge.
39.953 + ///
39.954 + /// Direct the given edge. The returned arc represents the given
39.955 + /// edge and its source node is the given node.
39.956 + Arc direct(Edge, Node) const {
39.957 + return INVALID;
39.958 + }
39.959 +
39.960 + /// \brief The oppositely directed arc.
39.961 + ///
39.962 + /// Returns the oppositely directed arc representing the same edge.
39.963 + Arc oppositeArc(Arc) const { return INVALID; }
39.964 +
39.965 + /// \brief The opposite node on the edge.
39.966 + ///
39.967 + /// Returns the opposite node on the given edge.
39.968 + Node oppositeNode(Node, Edge) const { return INVALID; }
39.969 +
39.970 void first(Node&) const {}
39.971 void next(Node&) const {}
39.972
39.973 @@ -705,47 +733,39 @@
39.974 // Dummy parameter.
39.975 int maxId(Arc) const { return -1; }
39.976
39.977 - /// \brief Base node of the iterator
39.978 + /// \brief The base node of the iterator.
39.979 ///
39.980 - /// Returns the base node (the source in this case) of the iterator
39.981 - Node baseNode(OutArcIt e) const {
39.982 - return source(e);
39.983 - }
39.984 - /// \brief Running node of the iterator
39.985 + /// Returns the base node of the given incident edge iterator.
39.986 + Node baseNode(IncEdgeIt) const { return INVALID; }
39.987 +
39.988 + /// \brief The running node of the iterator.
39.989 ///
39.990 - /// Returns the running node (the target in this case) of the
39.991 - /// iterator
39.992 - Node runningNode(OutArcIt e) const {
39.993 - return target(e);
39.994 - }
39.995 + /// Returns the running node of the given incident edge iterator.
39.996 + Node runningNode(IncEdgeIt) const { return INVALID; }
39.997
39.998 - /// \brief Base node of the iterator
39.999 + /// \brief The base node of the iterator.
39.1000 ///
39.1001 - /// Returns the base node (the target in this case) of the iterator
39.1002 - Node baseNode(InArcIt e) const {
39.1003 - return target(e);
39.1004 - }
39.1005 - /// \brief Running node of the iterator
39.1006 + /// Returns the base node of the given outgoing arc iterator
39.1007 + /// (i.e. the source node of the corresponding arc).
39.1008 + Node baseNode(OutArcIt) const { return INVALID; }
39.1009 +
39.1010 + /// \brief The running node of the iterator.
39.1011 ///
39.1012 - /// Returns the running node (the source in this case) of the
39.1013 - /// iterator
39.1014 - Node runningNode(InArcIt e) const {
39.1015 - return source(e);
39.1016 - }
39.1017 + /// Returns the running node of the given outgoing arc iterator
39.1018 + /// (i.e. the target node of the corresponding arc).
39.1019 + Node runningNode(OutArcIt) const { return INVALID; }
39.1020
39.1021 - /// \brief Base node of the iterator
39.1022 + /// \brief The base node of the iterator.
39.1023 ///
39.1024 - /// Returns the base node of the iterator
39.1025 - Node baseNode(IncEdgeIt) const {
39.1026 - return INVALID;
39.1027 - }
39.1028 + /// Returns the base node of the given incomming arc iterator
39.1029 + /// (i.e. the target node of the corresponding arc).
39.1030 + Node baseNode(InArcIt) const { return INVALID; }
39.1031
39.1032 - /// \brief Running node of the iterator
39.1033 + /// \brief The running node of the iterator.
39.1034 ///
39.1035 - /// Returns the running node of the iterator
39.1036 - Node runningNode(IncEdgeIt) const {
39.1037 - return INVALID;
39.1038 - }
39.1039 + /// Returns the running node of the given incomming arc iterator
39.1040 + /// (i.e. the source node of the corresponding arc).
39.1041 + Node runningNode(InArcIt) const { return INVALID; }
39.1042
39.1043 template <typename _Graph>
39.1044 struct Constraints {
40.1 --- a/lemon/concepts/graph_components.h Tue Dec 20 17:44:38 2011 +0100
40.2 +++ b/lemon/concepts/graph_components.h Tue Dec 20 18:15:14 2011 +0100
40.3 @@ -2,7 +2,7 @@
40.4 *
40.5 * This file is a part of LEMON, a generic C++ optimization library.
40.6 *
40.7 - * Copyright (C) 2003-2009
40.8 + * Copyright (C) 2003-2010
40.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
40.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
40.11 *
40.12 @@ -18,7 +18,7 @@
40.13
40.14 ///\ingroup graph_concepts
40.15 ///\file
40.16 -///\brief The concept of graph components.
40.17 +///\brief The concepts of graph components.
40.18
40.19 #ifndef LEMON_CONCEPTS_GRAPH_COMPONENTS_H
40.20 #define LEMON_CONCEPTS_GRAPH_COMPONENTS_H
40.21 @@ -38,7 +38,7 @@
40.22 ///
40.23 /// \note This class is a template class so that we can use it to
40.24 /// create graph skeleton classes. The reason for this is that \c Node
40.25 - /// and \c Arc (or \c Edge) types should \e not derive from the same
40.26 + /// and \c Arc (or \c Edge) types should \e not derive from the same
40.27 /// base class. For \c Node you should instantiate it with character
40.28 /// \c 'n', for \c Arc with \c 'a' and for \c Edge with \c 'e'.
40.29 #ifndef DOXYGEN
40.30 @@ -89,10 +89,10 @@
40.31 /// \brief Ordering operator.
40.32 ///
40.33 /// This operator defines an ordering of the items.
40.34 - /// It makes possible to use graph item types as key types in
40.35 + /// It makes possible to use graph item types as key types in
40.36 /// associative containers (e.g. \c std::map).
40.37 ///
40.38 - /// \note This operator only have to define some strict ordering of
40.39 + /// \note This operator only has to define some strict ordering of
40.40 /// the items; this order has nothing to do with the iteration
40.41 /// ordering of the items.
40.42 bool operator<(const GraphItem&) const { return false; }
40.43 @@ -122,7 +122,7 @@
40.44 ///
40.45 /// This class describes the base interface of directed graph types.
40.46 /// All digraph %concepts have to conform to this class.
40.47 - /// It just provides types for nodes and arcs and functions
40.48 + /// It just provides types for nodes and arcs and functions
40.49 /// to get the source and the target nodes of arcs.
40.50 class BaseDigraphComponent {
40.51 public:
40.52 @@ -426,7 +426,7 @@
40.53
40.54 /// \brief Concept class for \c NodeIt, \c ArcIt and \c EdgeIt types.
40.55 ///
40.56 - /// This class describes the concept of \c NodeIt, \c ArcIt and
40.57 + /// This class describes the concept of \c NodeIt, \c ArcIt and
40.58 /// \c EdgeIt subtypes of digraph and graph types.
40.59 template <typename GR, typename Item>
40.60 class GraphItemIt : public Item {
40.61 @@ -466,7 +466,7 @@
40.62 /// This operator increments the iterator, i.e. assigns it to the
40.63 /// next item.
40.64 GraphItemIt& operator++() { return *this; }
40.65 -
40.66 +
40.67 /// \brief Equality operator
40.68 ///
40.69 /// Equality operator.
40.70 @@ -501,15 +501,15 @@
40.71 };
40.72 };
40.73
40.74 - /// \brief Concept class for \c InArcIt, \c OutArcIt and
40.75 + /// \brief Concept class for \c InArcIt, \c OutArcIt and
40.76 /// \c IncEdgeIt types.
40.77 ///
40.78 - /// This class describes the concept of \c InArcIt, \c OutArcIt
40.79 + /// This class describes the concept of \c InArcIt, \c OutArcIt
40.80 /// and \c IncEdgeIt subtypes of digraph and graph types.
40.81 ///
40.82 /// \note Since these iterator classes do not inherit from the same
40.83 /// base class, there is an additional template parameter (selector)
40.84 - /// \c sel. For \c InArcIt you should instantiate it with character
40.85 + /// \c sel. For \c InArcIt you should instantiate it with character
40.86 /// \c 'i', for \c OutArcIt with \c 'o' and for \c IncEdgeIt with \c 'e'.
40.87 template <typename GR,
40.88 typename Item = typename GR::Arc,
40.89 @@ -530,10 +530,10 @@
40.90 /// Copy constructor.
40.91 GraphIncIt(const GraphIncIt& it) : Item(it) {}
40.92
40.93 - /// \brief Constructor that sets the iterator to the first
40.94 + /// \brief Constructor that sets the iterator to the first
40.95 /// incoming or outgoing arc.
40.96 ///
40.97 - /// Constructor that sets the iterator to the first arc
40.98 + /// Constructor that sets the iterator to the first arc
40.99 /// incoming to or outgoing from the given node.
40.100 explicit GraphIncIt(const GR&, const Base&) {}
40.101
40.102 @@ -804,16 +804,16 @@
40.103
40.104 /// \brief Return the first edge incident to the given node.
40.105 ///
40.106 - /// This function gives back the first edge incident to the given
40.107 + /// This function gives back the first edge incident to the given
40.108 /// node. The bool parameter gives back the direction for which the
40.109 - /// source node of the directed arc representing the edge is the
40.110 + /// source node of the directed arc representing the edge is the
40.111 /// given node.
40.112 void firstInc(Edge&, bool&, const Node&) const {}
40.113
40.114 /// \brief Gives back the next of the edges from the
40.115 /// given node.
40.116 ///
40.117 - /// This function gives back the next edge incident to the given
40.118 + /// This function gives back the next edge incident to the given
40.119 /// node. The bool parameter should be used as \c firstInc() use it.
40.120 void nextInc(Edge&, bool&) const {}
40.121
40.122 @@ -990,7 +990,7 @@
40.123 /// \brief Concept class for standard graph maps.
40.124 ///
40.125 /// This class describes the concept of standard graph maps, i.e.
40.126 - /// the \c NodeMap, \c ArcMap and \c EdgeMap subtypes of digraph and
40.127 + /// the \c NodeMap, \c ArcMap and \c EdgeMap subtypes of digraph and
40.128 /// graph types, which can be used for associating data to graph items.
40.129 /// The standard graph maps must conform to the ReferenceMap concept.
40.130 template <typename GR, typename K, typename V>
40.131 @@ -1045,7 +1045,7 @@
40.132 <ReferenceMap<Key, Value, Value&, const Value&>, _Map>();
40.133 _Map m1(g);
40.134 _Map m2(g,t);
40.135 -
40.136 +
40.137 // Copy constructor
40.138 // _Map m3(m);
40.139
40.140 @@ -1068,7 +1068,7 @@
40.141 /// \brief Skeleton class for mappable directed graphs.
40.142 ///
40.143 /// This class describes the interface of mappable directed graphs.
40.144 - /// It extends \ref BaseDigraphComponent with the standard digraph
40.145 + /// It extends \ref BaseDigraphComponent with the standard digraph
40.146 /// map classes, namely \c NodeMap and \c ArcMap.
40.147 /// This concept is part of the Digraph concept.
40.148 template <typename BAS = BaseDigraphComponent>
40.149 @@ -1205,7 +1205,7 @@
40.150 /// \brief Skeleton class for mappable undirected graphs.
40.151 ///
40.152 /// This class describes the interface of mappable undirected graphs.
40.153 - /// It extends \ref MappableDigraphComponent with the standard graph
40.154 + /// It extends \ref MappableDigraphComponent with the standard graph
40.155 /// map class for edges (\c EdgeMap).
40.156 /// This concept is part of the Graph concept.
40.157 template <typename BAS = BaseGraphComponent>
40.158 @@ -1290,7 +1290,7 @@
40.159 /// \brief Skeleton class for extendable directed graphs.
40.160 ///
40.161 /// This class describes the interface of extendable directed graphs.
40.162 - /// It extends \ref BaseDigraphComponent with functions for adding
40.163 + /// It extends \ref BaseDigraphComponent with functions for adding
40.164 /// nodes and arcs to the digraph.
40.165 /// This concept requires \ref AlterableDigraphComponent.
40.166 template <typename BAS = BaseDigraphComponent>
40.167 @@ -1334,7 +1334,7 @@
40.168 /// \brief Skeleton class for extendable undirected graphs.
40.169 ///
40.170 /// This class describes the interface of extendable undirected graphs.
40.171 - /// It extends \ref BaseGraphComponent with functions for adding
40.172 + /// It extends \ref BaseGraphComponent with functions for adding
40.173 /// nodes and edges to the graph.
40.174 /// This concept requires \ref AlterableGraphComponent.
40.175 template <typename BAS = BaseGraphComponent>
40.176 @@ -1378,7 +1378,7 @@
40.177 /// \brief Skeleton class for erasable directed graphs.
40.178 ///
40.179 /// This class describes the interface of erasable directed graphs.
40.180 - /// It extends \ref BaseDigraphComponent with functions for removing
40.181 + /// It extends \ref BaseDigraphComponent with functions for removing
40.182 /// nodes and arcs from the digraph.
40.183 /// This concept requires \ref AlterableDigraphComponent.
40.184 template <typename BAS = BaseDigraphComponent>
40.185 @@ -1391,7 +1391,7 @@
40.186
40.187 /// \brief Erase a node from the digraph.
40.188 ///
40.189 - /// This function erases the given node from the digraph and all arcs
40.190 + /// This function erases the given node from the digraph and all arcs
40.191 /// connected to the node.
40.192 void erase(const Node&) {}
40.193
40.194 @@ -1417,7 +1417,7 @@
40.195 /// \brief Skeleton class for erasable undirected graphs.
40.196 ///
40.197 /// This class describes the interface of erasable undirected graphs.
40.198 - /// It extends \ref BaseGraphComponent with functions for removing
40.199 + /// It extends \ref BaseGraphComponent with functions for removing
40.200 /// nodes and edges from the graph.
40.201 /// This concept requires \ref AlterableGraphComponent.
40.202 template <typename BAS = BaseGraphComponent>
41.1 --- a/lemon/concepts/heap.h Tue Dec 20 17:44:38 2011 +0100
41.2 +++ b/lemon/concepts/heap.h Tue Dec 20 18:15:14 2011 +0100
41.3 @@ -2,7 +2,7 @@
41.4 *
41.5 * This file is a part of LEMON, a generic C++ optimization library.
41.6 *
41.7 - * Copyright (C) 2003-2009
41.8 + * Copyright (C) 2003-2010
41.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
41.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
41.11 *
41.12 @@ -16,13 +16,13 @@
41.13 *
41.14 */
41.15
41.16 +#ifndef LEMON_CONCEPTS_HEAP_H
41.17 +#define LEMON_CONCEPTS_HEAP_H
41.18 +
41.19 ///\ingroup concept
41.20 ///\file
41.21 ///\brief The concept of heaps.
41.22
41.23 -#ifndef LEMON_CONCEPTS_HEAP_H
41.24 -#define LEMON_CONCEPTS_HEAP_H
41.25 -
41.26 #include <lemon/core.h>
41.27 #include <lemon/concept_check.h>
41.28
41.29 @@ -35,21 +35,27 @@
41.30
41.31 /// \brief The heap concept.
41.32 ///
41.33 - /// Concept class describing the main interface of heaps. A \e heap
41.34 - /// is a data structure for storing items with specified values called
41.35 - /// \e priorities in such a way that finding the item with minimum
41.36 - /// priority is efficient. In a heap one can change the priority of an
41.37 - /// item, add or erase an item, etc.
41.38 + /// This concept class describes the main interface of heaps.
41.39 + /// The various \ref heaps "heap structures" are efficient
41.40 + /// implementations of the abstract data type \e priority \e queue.
41.41 + /// They store items with specified values called \e priorities
41.42 + /// in such a way that finding and removing the item with minimum
41.43 + /// priority are efficient. The basic operations are adding and
41.44 + /// erasing items, changing the priority of an item, etc.
41.45 ///
41.46 - /// \tparam PR Type of the priority of the items.
41.47 - /// \tparam IM A read and writable item map with int values, used
41.48 + /// Heaps are crucial in several algorithms, such as Dijkstra and Prim.
41.49 + /// Any class that conforms to this concept can be used easily in such
41.50 + /// algorithms.
41.51 + ///
41.52 + /// \tparam PR Type of the priorities of the items.
41.53 + /// \tparam IM A read-writable item map with \c int values, used
41.54 /// internally to handle the cross references.
41.55 - /// \tparam Comp A functor class for the ordering of the priorities.
41.56 + /// \tparam CMP A functor class for comparing the priorities.
41.57 /// The default is \c std::less<PR>.
41.58 #ifdef DOXYGEN
41.59 - template <typename PR, typename IM, typename Comp = std::less<PR> >
41.60 + template <typename PR, typename IM, typename CMP>
41.61 #else
41.62 - template <typename PR, typename IM>
41.63 + template <typename PR, typename IM, typename CMP = std::less<PR> >
41.64 #endif
41.65 class Heap {
41.66 public:
41.67 @@ -64,109 +70,157 @@
41.68 /// \brief Type to represent the states of the items.
41.69 ///
41.70 /// Each item has a state associated to it. It can be "in heap",
41.71 - /// "pre heap" or "post heap". The later two are indifferent
41.72 - /// from the point of view of the heap, but may be useful for
41.73 - /// the user.
41.74 + /// "pre-heap" or "post-heap". The latter two are indifferent from the
41.75 + /// heap's point of view, but may be useful to the user.
41.76 ///
41.77 /// The item-int map must be initialized in such way that it assigns
41.78 /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
41.79 enum State {
41.80 IN_HEAP = 0, ///< = 0. The "in heap" state constant.
41.81 - PRE_HEAP = -1, ///< = -1. The "pre heap" state constant.
41.82 - POST_HEAP = -2 ///< = -2. The "post heap" state constant.
41.83 + PRE_HEAP = -1, ///< = -1. The "pre-heap" state constant.
41.84 + POST_HEAP = -2 ///< = -2. The "post-heap" state constant.
41.85 };
41.86
41.87 - /// \brief The constructor.
41.88 + /// \brief Constructor.
41.89 ///
41.90 - /// The constructor.
41.91 + /// Constructor.
41.92 /// \param map A map that assigns \c int values to keys of type
41.93 /// \c Item. It is used internally by the heap implementations to
41.94 /// handle the cross references. The assigned value must be
41.95 - /// \c PRE_HEAP (<tt>-1</tt>) for every item.
41.96 + /// \c PRE_HEAP (<tt>-1</tt>) for each item.
41.97 +#ifdef DOXYGEN
41.98 explicit Heap(ItemIntMap &map) {}
41.99 +#else
41.100 + explicit Heap(ItemIntMap&) {}
41.101 +#endif
41.102 +
41.103 + /// \brief Constructor.
41.104 + ///
41.105 + /// Constructor.
41.106 + /// \param map A map that assigns \c int values to keys of type
41.107 + /// \c Item. It is used internally by the heap implementations to
41.108 + /// handle the cross references. The assigned value must be
41.109 + /// \c PRE_HEAP (<tt>-1</tt>) for each item.
41.110 + /// \param comp The function object used for comparing the priorities.
41.111 +#ifdef DOXYGEN
41.112 + explicit Heap(ItemIntMap &map, const CMP &comp) {}
41.113 +#else
41.114 + explicit Heap(ItemIntMap&, const CMP&) {}
41.115 +#endif
41.116
41.117 /// \brief The number of items stored in the heap.
41.118 ///
41.119 - /// Returns the number of items stored in the heap.
41.120 + /// This function returns the number of items stored in the heap.
41.121 int size() const { return 0; }
41.122
41.123 - /// \brief Checks if the heap is empty.
41.124 + /// \brief Check if the heap is empty.
41.125 ///
41.126 - /// Returns \c true if the heap is empty.
41.127 + /// This function returns \c true if the heap is empty.
41.128 bool empty() const { return false; }
41.129
41.130 - /// \brief Makes the heap empty.
41.131 + /// \brief Make the heap empty.
41.132 ///
41.133 - /// Makes the heap empty.
41.134 - void clear();
41.135 + /// This functon makes the heap empty.
41.136 + /// It does not change the cross reference map. If you want to reuse
41.137 + /// a heap that is not surely empty, you should first clear it and
41.138 + /// then you should set the cross reference map to \c PRE_HEAP
41.139 + /// for each item.
41.140 + void clear() {}
41.141
41.142 - /// \brief Inserts an item into the heap with the given priority.
41.143 + /// \brief Insert an item into the heap with the given priority.
41.144 ///
41.145 - /// Inserts the given item into the heap with the given priority.
41.146 + /// This function inserts the given item into the heap with the
41.147 + /// given priority.
41.148 /// \param i The item to insert.
41.149 /// \param p The priority of the item.
41.150 + /// \pre \e i must not be stored in the heap.
41.151 +#ifdef DOXYGEN
41.152 void push(const Item &i, const Prio &p) {}
41.153 +#else
41.154 + void push(const Item&, const Prio&) {}
41.155 +#endif
41.156
41.157 - /// \brief Returns the item having minimum priority.
41.158 + /// \brief Return the item having minimum priority.
41.159 ///
41.160 - /// Returns the item having minimum priority.
41.161 + /// This function returns the item having minimum priority.
41.162 /// \pre The heap must be non-empty.
41.163 - Item top() const {}
41.164 + Item top() const { return Item(); }
41.165
41.166 /// \brief The minimum priority.
41.167 ///
41.168 - /// Returns the minimum priority.
41.169 + /// This function returns the minimum priority.
41.170 /// \pre The heap must be non-empty.
41.171 - Prio prio() const {}
41.172 + Prio prio() const { return Prio(); }
41.173
41.174 - /// \brief Removes the item having minimum priority.
41.175 + /// \brief Remove the item having minimum priority.
41.176 ///
41.177 - /// Removes the item having minimum priority.
41.178 + /// This function removes the item having minimum priority.
41.179 /// \pre The heap must be non-empty.
41.180 void pop() {}
41.181
41.182 - /// \brief Removes an item from the heap.
41.183 + /// \brief Remove the given item from the heap.
41.184 ///
41.185 - /// Removes the given item from the heap if it is already stored.
41.186 + /// This function removes the given item from the heap if it is
41.187 + /// already stored.
41.188 /// \param i The item to delete.
41.189 + /// \pre \e i must be in the heap.
41.190 +#ifdef DOXYGEN
41.191 void erase(const Item &i) {}
41.192 +#else
41.193 + void erase(const Item&) {}
41.194 +#endif
41.195
41.196 - /// \brief The priority of an item.
41.197 + /// \brief The priority of the given item.
41.198 ///
41.199 - /// Returns the priority of the given item.
41.200 + /// This function returns the priority of the given item.
41.201 /// \param i The item.
41.202 - /// \pre \c i must be in the heap.
41.203 + /// \pre \e i must be in the heap.
41.204 +#ifdef DOXYGEN
41.205 Prio operator[](const Item &i) const {}
41.206 +#else
41.207 + Prio operator[](const Item&) const { return Prio(); }
41.208 +#endif
41.209
41.210 - /// \brief Sets the priority of an item or inserts it, if it is
41.211 + /// \brief Set the priority of an item or insert it, if it is
41.212 /// not stored in the heap.
41.213 ///
41.214 /// This method sets the priority of the given item if it is
41.215 - /// already stored in the heap.
41.216 - /// Otherwise it inserts the given item with the given priority.
41.217 + /// already stored in the heap. Otherwise it inserts the given
41.218 + /// item into the heap with the given priority.
41.219 ///
41.220 /// \param i The item.
41.221 /// \param p The priority.
41.222 +#ifdef DOXYGEN
41.223 void set(const Item &i, const Prio &p) {}
41.224 +#else
41.225 + void set(const Item&, const Prio&) {}
41.226 +#endif
41.227
41.228 - /// \brief Decreases the priority of an item to the given value.
41.229 + /// \brief Decrease the priority of an item to the given value.
41.230 ///
41.231 - /// Decreases the priority of an item to the given value.
41.232 + /// This function decreases the priority of an item to the given value.
41.233 /// \param i The item.
41.234 /// \param p The priority.
41.235 - /// \pre \c i must be stored in the heap with priority at least \c p.
41.236 + /// \pre \e i must be stored in the heap with priority at least \e p.
41.237 +#ifdef DOXYGEN
41.238 void decrease(const Item &i, const Prio &p) {}
41.239 +#else
41.240 + void decrease(const Item&, const Prio&) {}
41.241 +#endif
41.242
41.243 - /// \brief Increases the priority of an item to the given value.
41.244 + /// \brief Increase the priority of an item to the given value.
41.245 ///
41.246 - /// Increases the priority of an item to the given value.
41.247 + /// This function increases the priority of an item to the given value.
41.248 /// \param i The item.
41.249 /// \param p The priority.
41.250 - /// \pre \c i must be stored in the heap with priority at most \c p.
41.251 + /// \pre \e i must be stored in the heap with priority at most \e p.
41.252 +#ifdef DOXYGEN
41.253 void increase(const Item &i, const Prio &p) {}
41.254 +#else
41.255 + void increase(const Item&, const Prio&) {}
41.256 +#endif
41.257
41.258 - /// \brief Returns if an item is in, has already been in, or has
41.259 - /// never been in the heap.
41.260 + /// \brief Return the state of an item.
41.261 ///
41.262 /// This method returns \c PRE_HEAP if the given item has never
41.263 /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
41.264 @@ -174,16 +228,24 @@
41.265 /// In the latter case it is possible that the item will get back
41.266 /// to the heap again.
41.267 /// \param i The item.
41.268 +#ifdef DOXYGEN
41.269 State state(const Item &i) const {}
41.270 +#else
41.271 + State state(const Item&) const { return PRE_HEAP; }
41.272 +#endif
41.273
41.274 - /// \brief Sets the state of an item in the heap.
41.275 + /// \brief Set the state of an item in the heap.
41.276 ///
41.277 - /// Sets the state of the given item in the heap. It can be used
41.278 - /// to manually clear the heap when it is important to achive the
41.279 - /// better time complexity.
41.280 + /// This function sets the state of the given item in the heap.
41.281 + /// It can be used to manually clear the heap when it is important
41.282 + /// to achive better time complexity.
41.283 /// \param i The item.
41.284 /// \param st The state. It should not be \c IN_HEAP.
41.285 +#ifdef DOXYGEN
41.286 void state(const Item& i, State st) {}
41.287 +#else
41.288 + void state(const Item&, State) {}
41.289 +#endif
41.290
41.291
41.292 template <typename _Heap>
42.1 --- a/lemon/concepts/path.h Tue Dec 20 17:44:38 2011 +0100
42.2 +++ b/lemon/concepts/path.h Tue Dec 20 18:15:14 2011 +0100
42.3 @@ -18,7 +18,7 @@
42.4
42.5 ///\ingroup concept
42.6 ///\file
42.7 -///\brief Classes for representing paths in digraphs.
42.8 +///\brief The concept of paths
42.9 ///
42.10
42.11 #ifndef LEMON_CONCEPTS_PATH_H
42.12 @@ -38,13 +38,22 @@
42.13 ///
42.14 /// A skeleton structure for representing directed paths in a
42.15 /// digraph.
42.16 + /// In a sense, a path can be treated as a list of arcs.
42.17 + /// LEMON path types just store this list. As a consequence, they cannot
42.18 + /// enumerate the nodes on the path directly and a zero length path
42.19 + /// cannot store its source node.
42.20 + ///
42.21 + /// The arcs of a path should be stored in the order of their directions,
42.22 + /// i.e. the target node of each arc should be the same as the source
42.23 + /// node of the next arc. This consistency could be checked using
42.24 + /// \ref checkPath().
42.25 + /// The source and target nodes of a (consistent) path can be obtained
42.26 + /// using \ref pathSource() and \ref pathTarget().
42.27 + ///
42.28 + /// A path can be constructed from another path of any type using the
42.29 + /// copy constructor or the assignment operator.
42.30 + ///
42.31 /// \tparam GR The digraph type in which the path is.
42.32 - ///
42.33 - /// In a sense, the path can be treated as a list of arcs. The
42.34 - /// lemon path type stores just this list. As a consequence it
42.35 - /// cannot enumerate the nodes in the path and the zero length
42.36 - /// paths cannot store the source.
42.37 - ///
42.38 template <typename GR>
42.39 class Path {
42.40 public:
42.41 @@ -59,18 +68,18 @@
42.42 /// \brief Default constructor
42.43 Path() {}
42.44
42.45 - /// \brief Template constructor
42.46 + /// \brief Template copy constructor
42.47 template <typename CPath>
42.48 Path(const CPath& cpath) {}
42.49
42.50 - /// \brief Template assigment
42.51 + /// \brief Template assigment operator
42.52 template <typename CPath>
42.53 Path& operator=(const CPath& cpath) {
42.54 ignore_unused_variable_warning(cpath);
42.55 return *this;
42.56 }
42.57
42.58 - /// Length of the path ie. the number of arcs in the path.
42.59 + /// Length of the path, i.e. the number of arcs on the path.
42.60 int length() const { return 0;}
42.61
42.62 /// Returns whether the path is empty.
42.63 @@ -79,19 +88,19 @@
42.64 /// Resets the path to an empty path.
42.65 void clear() {}
42.66
42.67 - /// \brief LEMON style iterator for path arcs
42.68 + /// \brief LEMON style iterator for enumerating the arcs of a path.
42.69 ///
42.70 - /// This class is used to iterate on the arcs of the paths.
42.71 + /// LEMON style iterator class for enumerating the arcs of a path.
42.72 class ArcIt {
42.73 public:
42.74 /// Default constructor
42.75 ArcIt() {}
42.76 /// Invalid constructor
42.77 ArcIt(Invalid) {}
42.78 - /// Constructor for first arc
42.79 + /// Sets the iterator to the first arc of the given path
42.80 ArcIt(const Path &) {}
42.81
42.82 - /// Conversion to Arc
42.83 + /// Conversion to \c Arc
42.84 operator Arc() const { return INVALID; }
42.85
42.86 /// Next arc
42.87 @@ -192,24 +201,18 @@
42.88 /// \brief A skeleton structure for path dumpers.
42.89 ///
42.90 /// A skeleton structure for path dumpers. The path dumpers are
42.91 - /// the generalization of the paths. The path dumpers can
42.92 - /// enumerate the arcs of the path wheter in forward or in
42.93 - /// backward order. In most time these classes are not used
42.94 - /// directly rather it used to assign a dumped class to a real
42.95 - /// path type.
42.96 + /// the generalization of the paths, they can enumerate the arcs
42.97 + /// of the path either in forward or in backward order.
42.98 + /// These classes are typically not used directly, they are rather
42.99 + /// used to be assigned to a real path type.
42.100 ///
42.101 /// The main purpose of this concept is that the shortest path
42.102 - /// algorithms can enumerate easily the arcs in reverse order.
42.103 - /// If we would like to give back a real path from these
42.104 - /// algorithms then we should create a temporarly path object. In
42.105 - /// LEMON such algorithms gives back a path dumper what can
42.106 - /// assigned to a real path and the dumpers can be implemented as
42.107 + /// algorithms can enumerate the arcs easily in reverse order.
42.108 + /// In LEMON, such algorithms give back a (reverse) path dumper that
42.109 + /// can be assigned to a real path. The dumpers can be implemented as
42.110 /// an adaptor class to the predecessor map.
42.111 ///
42.112 /// \tparam GR The digraph type in which the path is.
42.113 - ///
42.114 - /// The paths can be constructed from any path type by a
42.115 - /// template constructor or a template assignment operator.
42.116 template <typename GR>
42.117 class PathDumper {
42.118 public:
42.119 @@ -219,7 +222,7 @@
42.120 /// Arc type of the underlying digraph.
42.121 typedef typename Digraph::Arc Arc;
42.122
42.123 - /// Length of the path ie. the number of arcs in the path.
42.124 + /// Length of the path, i.e. the number of arcs on the path.
42.125 int length() const { return 0;}
42.126
42.127 /// Returns whether the path is empty.
42.128 @@ -227,25 +230,24 @@
42.129
42.130 /// \brief Forward or reverse dumping
42.131 ///
42.132 - /// If the RevPathTag is defined and true then reverse dumping
42.133 - /// is provided in the path dumper. In this case instead of the
42.134 - /// ArcIt the RevArcIt iterator should be implemented in the
42.135 - /// dumper.
42.136 + /// If this tag is defined to be \c True, then reverse dumping
42.137 + /// is provided in the path dumper. In this case, \c RevArcIt
42.138 + /// iterator should be implemented instead of \c ArcIt iterator.
42.139 typedef False RevPathTag;
42.140
42.141 - /// \brief LEMON style iterator for path arcs
42.142 + /// \brief LEMON style iterator for enumerating the arcs of a path.
42.143 ///
42.144 - /// This class is used to iterate on the arcs of the paths.
42.145 + /// LEMON style iterator class for enumerating the arcs of a path.
42.146 class ArcIt {
42.147 public:
42.148 /// Default constructor
42.149 ArcIt() {}
42.150 /// Invalid constructor
42.151 ArcIt(Invalid) {}
42.152 - /// Constructor for first arc
42.153 + /// Sets the iterator to the first arc of the given path
42.154 ArcIt(const PathDumper&) {}
42.155
42.156 - /// Conversion to Arc
42.157 + /// Conversion to \c Arc
42.158 operator Arc() const { return INVALID; }
42.159
42.160 /// Next arc
42.161 @@ -260,20 +262,21 @@
42.162
42.163 };
42.164
42.165 - /// \brief LEMON style iterator for path arcs
42.166 + /// \brief LEMON style iterator for enumerating the arcs of a path
42.167 + /// in reverse direction.
42.168 ///
42.169 - /// This class is used to iterate on the arcs of the paths in
42.170 - /// reverse direction.
42.171 + /// LEMON style iterator class for enumerating the arcs of a path
42.172 + /// in reverse direction.
42.173 class RevArcIt {
42.174 public:
42.175 /// Default constructor
42.176 RevArcIt() {}
42.177 /// Invalid constructor
42.178 RevArcIt(Invalid) {}
42.179 - /// Constructor for first arc
42.180 + /// Sets the iterator to the last arc of the given path
42.181 RevArcIt(const PathDumper &) {}
42.182
42.183 - /// Conversion to Arc
42.184 + /// Conversion to \c Arc
42.185 operator Arc() const { return INVALID; }
42.186
42.187 /// Next arc
43.1 --- a/lemon/connectivity.h Tue Dec 20 17:44:38 2011 +0100
43.2 +++ b/lemon/connectivity.h Tue Dec 20 18:15:14 2011 +0100
43.3 @@ -2,7 +2,7 @@
43.4 *
43.5 * This file is a part of LEMON, a generic C++ optimization library.
43.6 *
43.7 - * Copyright (C) 2003-2009
43.8 + * Copyright (C) 2003-2010
43.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
43.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
43.11 *
43.12 @@ -258,7 +258,7 @@
43.13 ///
43.14 /// \return \c true if the digraph is strongly connected.
43.15 /// \note By definition, the empty digraph is strongly connected.
43.16 - ///
43.17 + ///
43.18 /// \see countStronglyConnectedComponents(), stronglyConnectedComponents()
43.19 /// \see connected()
43.20 template <typename Digraph>
43.21 @@ -310,7 +310,7 @@
43.22
43.23 /// \ingroup graph_properties
43.24 ///
43.25 - /// \brief Count the number of strongly connected components of a
43.26 + /// \brief Count the number of strongly connected components of a
43.27 /// directed graph
43.28 ///
43.29 /// This function counts the number of strongly connected components of
43.30 @@ -744,7 +744,7 @@
43.31 ///
43.32 /// \brief Check whether an undirected graph is bi-node-connected.
43.33 ///
43.34 - /// This function checks whether the given undirected graph is
43.35 + /// This function checks whether the given undirected graph is
43.36 /// bi-node-connected, i.e. any two edges are on same circle.
43.37 ///
43.38 /// \return \c true if the graph bi-node-connected.
43.39 @@ -758,7 +758,7 @@
43.40
43.41 /// \ingroup graph_properties
43.42 ///
43.43 - /// \brief Count the number of bi-node-connected components of an
43.44 + /// \brief Count the number of bi-node-connected components of an
43.45 /// undirected graph.
43.46 ///
43.47 /// This function counts the number of bi-node-connected components of
43.48 @@ -812,7 +812,7 @@
43.49 /// \param graph The undirected graph.
43.50 /// \retval compMap A writable edge map. The values will be set from 0
43.51 /// to the number of the bi-node-connected components minus one. Each
43.52 - /// value of the map will be set exactly once, and the values of a
43.53 + /// value of the map will be set exactly once, and the values of a
43.54 /// certain component will be set continuously.
43.55 /// \return The number of bi-node-connected components.
43.56 ///
43.57 @@ -858,7 +858,7 @@
43.58 /// the components.
43.59 ///
43.60 /// \param graph The undirected graph.
43.61 - /// \retval cutMap A writable node map. The values will be set to
43.62 + /// \retval cutMap A writable node map. The values will be set to
43.63 /// \c true for the nodes that separate two or more components
43.64 /// (exactly once for each cut node), and will not be changed for
43.65 /// other nodes.
43.66 @@ -1085,7 +1085,7 @@
43.67 ///
43.68 /// \brief Check whether an undirected graph is bi-edge-connected.
43.69 ///
43.70 - /// This function checks whether the given undirected graph is
43.71 + /// This function checks whether the given undirected graph is
43.72 /// bi-edge-connected, i.e. any two nodes are connected with at least
43.73 /// two edge-disjoint paths.
43.74 ///
43.75 @@ -1192,7 +1192,7 @@
43.76 /// \brief Find the bi-edge-connected cut edges in an undirected graph.
43.77 ///
43.78 /// This function finds the bi-edge-connected cut edges in the given
43.79 - /// undirected graph.
43.80 + /// undirected graph.
43.81 ///
43.82 /// The bi-edge-connected components are the classes of an equivalence
43.83 /// relation on the nodes of an undirected graph. Two nodes are in the
43.84 @@ -1349,7 +1349,7 @@
43.85 ///
43.86 /// \param digraph The digraph.
43.87 /// \retval order A readable and writable node map. The values will be
43.88 - /// set from 0 to the number of the nodes in the digraph minus one.
43.89 + /// set from 0 to the number of the nodes in the digraph minus one.
43.90 /// Each value of the map will be set exactly once, and the values will
43.91 /// be set descending order.
43.92 /// \return \c false if the digraph is not DAG.
44.1 --- a/lemon/core.h Tue Dec 20 17:44:38 2011 +0100
44.2 +++ b/lemon/core.h Tue Dec 20 18:15:14 2011 +0100
44.3 @@ -2,7 +2,7 @@
44.4 *
44.5 * This file is a part of LEMON, a generic C++ optimization library.
44.6 *
44.7 - * Copyright (C) 2003-2009
44.8 + * Copyright (C) 2003-2010
44.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
44.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
44.11 *
44.12 @@ -1241,7 +1241,8 @@
44.13
44.14 protected:
44.15
44.16 - class AutoNodeMap : public ItemSetTraits<GR, Node>::template Map<Arc>::Type {
44.17 + class AutoNodeMap : public ItemSetTraits<GR, Node>::template Map<Arc>::Type
44.18 + {
44.19 typedef typename ItemSetTraits<GR, Node>::template Map<Arc>::Type Parent;
44.20
44.21 public:
44.22 @@ -1280,7 +1281,7 @@
44.23 }
44.24 };
44.25
44.26 - protected:
44.27 + protected:
44.28
44.29 const Digraph &_g;
44.30 AutoNodeMap _head;
45.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
45.2 +++ b/lemon/cost_scaling.h Tue Dec 20 18:15:14 2011 +0100
45.3 @@ -0,0 +1,1316 @@
45.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
45.5 + *
45.6 + * This file is a part of LEMON, a generic C++ optimization library.
45.7 + *
45.8 + * Copyright (C) 2003-2010
45.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
45.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
45.11 + *
45.12 + * Permission to use, modify and distribute this software is granted
45.13 + * provided that this copyright notice appears in all copies. For
45.14 + * precise terms see the accompanying LICENSE file.
45.15 + *
45.16 + * This software is provided "AS IS" with no warranty of any kind,
45.17 + * express or implied, and with no claim as to its suitability for any
45.18 + * purpose.
45.19 + *
45.20 + */
45.21 +
45.22 +#ifndef LEMON_COST_SCALING_H
45.23 +#define LEMON_COST_SCALING_H
45.24 +
45.25 +/// \ingroup min_cost_flow_algs
45.26 +/// \file
45.27 +/// \brief Cost scaling algorithm for finding a minimum cost flow.
45.28 +
45.29 +#include <vector>
45.30 +#include <deque>
45.31 +#include <limits>
45.32 +
45.33 +#include <lemon/core.h>
45.34 +#include <lemon/maps.h>
45.35 +#include <lemon/math.h>
45.36 +#include <lemon/static_graph.h>
45.37 +#include <lemon/circulation.h>
45.38 +#include <lemon/bellman_ford.h>
45.39 +
45.40 +namespace lemon {
45.41 +
45.42 + /// \brief Default traits class of CostScaling algorithm.
45.43 + ///
45.44 + /// Default traits class of CostScaling algorithm.
45.45 + /// \tparam GR Digraph type.
45.46 + /// \tparam V The number type used for flow amounts, capacity bounds
45.47 + /// and supply values. By default it is \c int.
45.48 + /// \tparam C The number type used for costs and potentials.
45.49 + /// By default it is the same as \c V.
45.50 +#ifdef DOXYGEN
45.51 + template <typename GR, typename V = int, typename C = V>
45.52 +#else
45.53 + template < typename GR, typename V = int, typename C = V,
45.54 + bool integer = std::numeric_limits<C>::is_integer >
45.55 +#endif
45.56 + struct CostScalingDefaultTraits
45.57 + {
45.58 + /// The type of the digraph
45.59 + typedef GR Digraph;
45.60 + /// The type of the flow amounts, capacity bounds and supply values
45.61 + typedef V Value;
45.62 + /// The type of the arc costs
45.63 + typedef C Cost;
45.64 +
45.65 + /// \brief The large cost type used for internal computations
45.66 + ///
45.67 + /// The large cost type used for internal computations.
45.68 + /// It is \c long \c long if the \c Cost type is integer,
45.69 + /// otherwise it is \c double.
45.70 + /// \c Cost must be convertible to \c LargeCost.
45.71 + typedef double LargeCost;
45.72 + };
45.73 +
45.74 + // Default traits class for integer cost types
45.75 + template <typename GR, typename V, typename C>
45.76 + struct CostScalingDefaultTraits<GR, V, C, true>
45.77 + {
45.78 + typedef GR Digraph;
45.79 + typedef V Value;
45.80 + typedef C Cost;
45.81 +#ifdef LEMON_HAVE_LONG_LONG
45.82 + typedef long long LargeCost;
45.83 +#else
45.84 + typedef long LargeCost;
45.85 +#endif
45.86 + };
45.87 +
45.88 +
45.89 + /// \addtogroup min_cost_flow_algs
45.90 + /// @{
45.91 +
45.92 + /// \brief Implementation of the Cost Scaling algorithm for
45.93 + /// finding a \ref min_cost_flow "minimum cost flow".
45.94 + ///
45.95 + /// \ref CostScaling implements a cost scaling algorithm that performs
45.96 + /// push/augment and relabel operations for finding a \ref min_cost_flow
45.97 + /// "minimum cost flow" \ref amo93networkflows, \ref goldberg90approximation,
45.98 + /// \ref goldberg97efficient, \ref bunnagel98efficient.
45.99 + /// It is a highly efficient primal-dual solution method, which
45.100 + /// can be viewed as the generalization of the \ref Preflow
45.101 + /// "preflow push-relabel" algorithm for the maximum flow problem.
45.102 + ///
45.103 + /// Most of the parameters of the problem (except for the digraph)
45.104 + /// can be given using separate functions, and the algorithm can be
45.105 + /// executed using the \ref run() function. If some parameters are not
45.106 + /// specified, then default values will be used.
45.107 + ///
45.108 + /// \tparam GR The digraph type the algorithm runs on.
45.109 + /// \tparam V The number type used for flow amounts, capacity bounds
45.110 + /// and supply values in the algorithm. By default, it is \c int.
45.111 + /// \tparam C The number type used for costs and potentials in the
45.112 + /// algorithm. By default, it is the same as \c V.
45.113 + /// \tparam TR The traits class that defines various types used by the
45.114 + /// algorithm. By default, it is \ref CostScalingDefaultTraits
45.115 + /// "CostScalingDefaultTraits<GR, V, C>".
45.116 + /// In most cases, this parameter should not be set directly,
45.117 + /// consider to use the named template parameters instead.
45.118 + ///
45.119 + /// \warning Both number types must be signed and all input data must
45.120 + /// be integer.
45.121 + /// \warning This algorithm does not support negative costs for such
45.122 + /// arcs that have infinite upper bound.
45.123 + ///
45.124 + /// \note %CostScaling provides three different internal methods,
45.125 + /// from which the most efficient one is used by default.
45.126 + /// For more information, see \ref Method.
45.127 +#ifdef DOXYGEN
45.128 + template <typename GR, typename V, typename C, typename TR>
45.129 +#else
45.130 + template < typename GR, typename V = int, typename C = V,
45.131 + typename TR = CostScalingDefaultTraits<GR, V, C> >
45.132 +#endif
45.133 + class CostScaling
45.134 + {
45.135 + public:
45.136 +
45.137 + /// The type of the digraph
45.138 + typedef typename TR::Digraph Digraph;
45.139 + /// The type of the flow amounts, capacity bounds and supply values
45.140 + typedef typename TR::Value Value;
45.141 + /// The type of the arc costs
45.142 + typedef typename TR::Cost Cost;
45.143 +
45.144 + /// \brief The large cost type
45.145 + ///
45.146 + /// The large cost type used for internal computations.
45.147 + /// By default, it is \c long \c long if the \c Cost type is integer,
45.148 + /// otherwise it is \c double.
45.149 + typedef typename TR::LargeCost LargeCost;
45.150 +
45.151 + /// The \ref CostScalingDefaultTraits "traits class" of the algorithm
45.152 + typedef TR Traits;
45.153 +
45.154 + public:
45.155 +
45.156 + /// \brief Problem type constants for the \c run() function.
45.157 + ///
45.158 + /// Enum type containing the problem type constants that can be
45.159 + /// returned by the \ref run() function of the algorithm.
45.160 + enum ProblemType {
45.161 + /// The problem has no feasible solution (flow).
45.162 + INFEASIBLE,
45.163 + /// The problem has optimal solution (i.e. it is feasible and
45.164 + /// bounded), and the algorithm has found optimal flow and node
45.165 + /// potentials (primal and dual solutions).
45.166 + OPTIMAL,
45.167 + /// The digraph contains an arc of negative cost and infinite
45.168 + /// upper bound. It means that the objective function is unbounded
45.169 + /// on that arc, however, note that it could actually be bounded
45.170 + /// over the feasible flows, but this algroithm cannot handle
45.171 + /// these cases.
45.172 + UNBOUNDED
45.173 + };
45.174 +
45.175 + /// \brief Constants for selecting the internal method.
45.176 + ///
45.177 + /// Enum type containing constants for selecting the internal method
45.178 + /// for the \ref run() function.
45.179 + ///
45.180 + /// \ref CostScaling provides three internal methods that differ mainly
45.181 + /// in their base operations, which are used in conjunction with the
45.182 + /// relabel operation.
45.183 + /// By default, the so called \ref PARTIAL_AUGMENT
45.184 + /// "Partial Augment-Relabel" method is used, which proved to be
45.185 + /// the most efficient and the most robust on various test inputs.
45.186 + /// However, the other methods can be selected using the \ref run()
45.187 + /// function with the proper parameter.
45.188 + enum Method {
45.189 + /// Local push operations are used, i.e. flow is moved only on one
45.190 + /// admissible arc at once.
45.191 + PUSH,
45.192 + /// Augment operations are used, i.e. flow is moved on admissible
45.193 + /// paths from a node with excess to a node with deficit.
45.194 + AUGMENT,
45.195 + /// Partial augment operations are used, i.e. flow is moved on
45.196 + /// admissible paths started from a node with excess, but the
45.197 + /// lengths of these paths are limited. This method can be viewed
45.198 + /// as a combined version of the previous two operations.
45.199 + PARTIAL_AUGMENT
45.200 + };
45.201 +
45.202 + private:
45.203 +
45.204 + TEMPLATE_DIGRAPH_TYPEDEFS(GR);
45.205 +
45.206 + typedef std::vector<int> IntVector;
45.207 + typedef std::vector<Value> ValueVector;
45.208 + typedef std::vector<Cost> CostVector;
45.209 + typedef std::vector<LargeCost> LargeCostVector;
45.210 + typedef std::vector<char> BoolVector;
45.211 + // Note: vector<char> is used instead of vector<bool> for efficiency reasons
45.212 +
45.213 + private:
45.214 +
45.215 + template <typename KT, typename VT>
45.216 + class StaticVectorMap {
45.217 + public:
45.218 + typedef KT Key;
45.219 + typedef VT Value;
45.220 +
45.221 + StaticVectorMap(std::vector<Value>& v) : _v(v) {}
45.222 +
45.223 + const Value& operator[](const Key& key) const {
45.224 + return _v[StaticDigraph::id(key)];
45.225 + }
45.226 +
45.227 + Value& operator[](const Key& key) {
45.228 + return _v[StaticDigraph::id(key)];
45.229 + }
45.230 +
45.231 + void set(const Key& key, const Value& val) {
45.232 + _v[StaticDigraph::id(key)] = val;
45.233 + }
45.234 +
45.235 + private:
45.236 + std::vector<Value>& _v;
45.237 + };
45.238 +
45.239 + typedef StaticVectorMap<StaticDigraph::Node, LargeCost> LargeCostNodeMap;
45.240 + typedef StaticVectorMap<StaticDigraph::Arc, LargeCost> LargeCostArcMap;
45.241 +
45.242 + private:
45.243 +
45.244 + // Data related to the underlying digraph
45.245 + const GR &_graph;
45.246 + int _node_num;
45.247 + int _arc_num;
45.248 + int _res_node_num;
45.249 + int _res_arc_num;
45.250 + int _root;
45.251 +
45.252 + // Parameters of the problem
45.253 + bool _have_lower;
45.254 + Value _sum_supply;
45.255 + int _sup_node_num;
45.256 +
45.257 + // Data structures for storing the digraph
45.258 + IntNodeMap _node_id;
45.259 + IntArcMap _arc_idf;
45.260 + IntArcMap _arc_idb;
45.261 + IntVector _first_out;
45.262 + BoolVector _forward;
45.263 + IntVector _source;
45.264 + IntVector _target;
45.265 + IntVector _reverse;
45.266 +
45.267 + // Node and arc data
45.268 + ValueVector _lower;
45.269 + ValueVector _upper;
45.270 + CostVector _scost;
45.271 + ValueVector _supply;
45.272 +
45.273 + ValueVector _res_cap;
45.274 + LargeCostVector _cost;
45.275 + LargeCostVector _pi;
45.276 + ValueVector _excess;
45.277 + IntVector _next_out;
45.278 + std::deque<int> _active_nodes;
45.279 +
45.280 + // Data for scaling
45.281 + LargeCost _epsilon;
45.282 + int _alpha;
45.283 +
45.284 + IntVector _buckets;
45.285 + IntVector _bucket_next;
45.286 + IntVector _bucket_prev;
45.287 + IntVector _rank;
45.288 + int _max_rank;
45.289 +
45.290 + // Data for a StaticDigraph structure
45.291 + typedef std::pair<int, int> IntPair;
45.292 + StaticDigraph _sgr;
45.293 + std::vector<IntPair> _arc_vec;
45.294 + std::vector<LargeCost> _cost_vec;
45.295 + LargeCostArcMap _cost_map;
45.296 + LargeCostNodeMap _pi_map;
45.297 +
45.298 + public:
45.299 +
45.300 + /// \brief Constant for infinite upper bounds (capacities).
45.301 + ///
45.302 + /// Constant for infinite upper bounds (capacities).
45.303 + /// It is \c std::numeric_limits<Value>::infinity() if available,
45.304 + /// \c std::numeric_limits<Value>::max() otherwise.
45.305 + const Value INF;
45.306 +
45.307 + public:
45.308 +
45.309 + /// \name Named Template Parameters
45.310 + /// @{
45.311 +
45.312 + template <typename T>
45.313 + struct SetLargeCostTraits : public Traits {
45.314 + typedef T LargeCost;
45.315 + };
45.316 +
45.317 + /// \brief \ref named-templ-param "Named parameter" for setting
45.318 + /// \c LargeCost type.
45.319 + ///
45.320 + /// \ref named-templ-param "Named parameter" for setting \c LargeCost
45.321 + /// type, which is used for internal computations in the algorithm.
45.322 + /// \c Cost must be convertible to \c LargeCost.
45.323 + template <typename T>
45.324 + struct SetLargeCost
45.325 + : public CostScaling<GR, V, C, SetLargeCostTraits<T> > {
45.326 + typedef CostScaling<GR, V, C, SetLargeCostTraits<T> > Create;
45.327 + };
45.328 +
45.329 + /// @}
45.330 +
45.331 + protected:
45.332 +
45.333 + CostScaling() {}
45.334 +
45.335 + public:
45.336 +
45.337 + /// \brief Constructor.
45.338 + ///
45.339 + /// The constructor of the class.
45.340 + ///
45.341 + /// \param graph The digraph the algorithm runs on.
45.342 + CostScaling(const GR& graph) :
45.343 + _graph(graph), _node_id(graph), _arc_idf(graph), _arc_idb(graph),
45.344 + _cost_map(_cost_vec), _pi_map(_pi),
45.345 + INF(std::numeric_limits<Value>::has_infinity ?
45.346 + std::numeric_limits<Value>::infinity() :
45.347 + std::numeric_limits<Value>::max())
45.348 + {
45.349 + // Check the number types
45.350 + LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
45.351 + "The flow type of CostScaling must be signed");
45.352 + LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
45.353 + "The cost type of CostScaling must be signed");
45.354 +
45.355 + // Reset data structures
45.356 + reset();
45.357 + }
45.358 +
45.359 + /// \name Parameters
45.360 + /// The parameters of the algorithm can be specified using these
45.361 + /// functions.
45.362 +
45.363 + /// @{
45.364 +
45.365 + /// \brief Set the lower bounds on the arcs.
45.366 + ///
45.367 + /// This function sets the lower bounds on the arcs.
45.368 + /// If it is not used before calling \ref run(), the lower bounds
45.369 + /// will be set to zero on all arcs.
45.370 + ///
45.371 + /// \param map An arc map storing the lower bounds.
45.372 + /// Its \c Value type must be convertible to the \c Value type
45.373 + /// of the algorithm.
45.374 + ///
45.375 + /// \return <tt>(*this)</tt>
45.376 + template <typename LowerMap>
45.377 + CostScaling& lowerMap(const LowerMap& map) {
45.378 + _have_lower = true;
45.379 + for (ArcIt a(_graph); a != INVALID; ++a) {
45.380 + _lower[_arc_idf[a]] = map[a];
45.381 + _lower[_arc_idb[a]] = map[a];
45.382 + }
45.383 + return *this;
45.384 + }
45.385 +
45.386 + /// \brief Set the upper bounds (capacities) on the arcs.
45.387 + ///
45.388 + /// This function sets the upper bounds (capacities) on the arcs.
45.389 + /// If it is not used before calling \ref run(), the upper bounds
45.390 + /// will be set to \ref INF on all arcs (i.e. the flow value will be
45.391 + /// unbounded from above).
45.392 + ///
45.393 + /// \param map An arc map storing the upper bounds.
45.394 + /// Its \c Value type must be convertible to the \c Value type
45.395 + /// of the algorithm.
45.396 + ///
45.397 + /// \return <tt>(*this)</tt>
45.398 + template<typename UpperMap>
45.399 + CostScaling& upperMap(const UpperMap& map) {
45.400 + for (ArcIt a(_graph); a != INVALID; ++a) {
45.401 + _upper[_arc_idf[a]] = map[a];
45.402 + }
45.403 + return *this;
45.404 + }
45.405 +
45.406 + /// \brief Set the costs of the arcs.
45.407 + ///
45.408 + /// This function sets the costs of the arcs.
45.409 + /// If it is not used before calling \ref run(), the costs
45.410 + /// will be set to \c 1 on all arcs.
45.411 + ///
45.412 + /// \param map An arc map storing the costs.
45.413 + /// Its \c Value type must be convertible to the \c Cost type
45.414 + /// of the algorithm.
45.415 + ///
45.416 + /// \return <tt>(*this)</tt>
45.417 + template<typename CostMap>
45.418 + CostScaling& costMap(const CostMap& map) {
45.419 + for (ArcIt a(_graph); a != INVALID; ++a) {
45.420 + _scost[_arc_idf[a]] = map[a];
45.421 + _scost[_arc_idb[a]] = -map[a];
45.422 + }
45.423 + return *this;
45.424 + }
45.425 +
45.426 + /// \brief Set the supply values of the nodes.
45.427 + ///
45.428 + /// This function sets the supply values of the nodes.
45.429 + /// If neither this function nor \ref stSupply() is used before
45.430 + /// calling \ref run(), the supply of each node will be set to zero.
45.431 + ///
45.432 + /// \param map A node map storing the supply values.
45.433 + /// Its \c Value type must be convertible to the \c Value type
45.434 + /// of the algorithm.
45.435 + ///
45.436 + /// \return <tt>(*this)</tt>
45.437 + template<typename SupplyMap>
45.438 + CostScaling& supplyMap(const SupplyMap& map) {
45.439 + for (NodeIt n(_graph); n != INVALID; ++n) {
45.440 + _supply[_node_id[n]] = map[n];
45.441 + }
45.442 + return *this;
45.443 + }
45.444 +
45.445 + /// \brief Set single source and target nodes and a supply value.
45.446 + ///
45.447 + /// This function sets a single source node and a single target node
45.448 + /// and the required flow value.
45.449 + /// If neither this function nor \ref supplyMap() is used before
45.450 + /// calling \ref run(), the supply of each node will be set to zero.
45.451 + ///
45.452 + /// Using this function has the same effect as using \ref supplyMap()
45.453 + /// with such a map in which \c k is assigned to \c s, \c -k is
45.454 + /// assigned to \c t and all other nodes have zero supply value.
45.455 + ///
45.456 + /// \param s The source node.
45.457 + /// \param t The target node.
45.458 + /// \param k The required amount of flow from node \c s to node \c t
45.459 + /// (i.e. the supply of \c s and the demand of \c t).
45.460 + ///
45.461 + /// \return <tt>(*this)</tt>
45.462 + CostScaling& stSupply(const Node& s, const Node& t, Value k) {
45.463 + for (int i = 0; i != _res_node_num; ++i) {
45.464 + _supply[i] = 0;
45.465 + }
45.466 + _supply[_node_id[s]] = k;
45.467 + _supply[_node_id[t]] = -k;
45.468 + return *this;
45.469 + }
45.470 +
45.471 + /// @}
45.472 +
45.473 + /// \name Execution control
45.474 + /// The algorithm can be executed using \ref run().
45.475 +
45.476 + /// @{
45.477 +
45.478 + /// \brief Run the algorithm.
45.479 + ///
45.480 + /// This function runs the algorithm.
45.481 + /// The paramters can be specified using functions \ref lowerMap(),
45.482 + /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply().
45.483 + /// For example,
45.484 + /// \code
45.485 + /// CostScaling<ListDigraph> cs(graph);
45.486 + /// cs.lowerMap(lower).upperMap(upper).costMap(cost)
45.487 + /// .supplyMap(sup).run();
45.488 + /// \endcode
45.489 + ///
45.490 + /// This function can be called more than once. All the given parameters
45.491 + /// are kept for the next call, unless \ref resetParams() or \ref reset()
45.492 + /// is used, thus only the modified parameters have to be set again.
45.493 + /// If the underlying digraph was also modified after the construction
45.494 + /// of the class (or the last \ref reset() call), then the \ref reset()
45.495 + /// function must be called.
45.496 + ///
45.497 + /// \param method The internal method that will be used in the
45.498 + /// algorithm. For more information, see \ref Method.
45.499 + /// \param factor The cost scaling factor. It must be larger than one.
45.500 + ///
45.501 + /// \return \c INFEASIBLE if no feasible flow exists,
45.502 + /// \n \c OPTIMAL if the problem has optimal solution
45.503 + /// (i.e. it is feasible and bounded), and the algorithm has found
45.504 + /// optimal flow and node potentials (primal and dual solutions),
45.505 + /// \n \c UNBOUNDED if the digraph contains an arc of negative cost
45.506 + /// and infinite upper bound. It means that the objective function
45.507 + /// is unbounded on that arc, however, note that it could actually be
45.508 + /// bounded over the feasible flows, but this algroithm cannot handle
45.509 + /// these cases.
45.510 + ///
45.511 + /// \see ProblemType, Method
45.512 + /// \see resetParams(), reset()
45.513 + ProblemType run(Method method = PARTIAL_AUGMENT, int factor = 8) {
45.514 + _alpha = factor;
45.515 + ProblemType pt = init();
45.516 + if (pt != OPTIMAL) return pt;
45.517 + start(method);
45.518 + return OPTIMAL;
45.519 + }
45.520 +
45.521 + /// \brief Reset all the parameters that have been given before.
45.522 + ///
45.523 + /// This function resets all the paramaters that have been given
45.524 + /// before using functions \ref lowerMap(), \ref upperMap(),
45.525 + /// \ref costMap(), \ref supplyMap(), \ref stSupply().
45.526 + ///
45.527 + /// It is useful for multiple \ref run() calls. Basically, all the given
45.528 + /// parameters are kept for the next \ref run() call, unless
45.529 + /// \ref resetParams() or \ref reset() is used.
45.530 + /// If the underlying digraph was also modified after the construction
45.531 + /// of the class or the last \ref reset() call, then the \ref reset()
45.532 + /// function must be used, otherwise \ref resetParams() is sufficient.
45.533 + ///
45.534 + /// For example,
45.535 + /// \code
45.536 + /// CostScaling<ListDigraph> cs(graph);
45.537 + ///
45.538 + /// // First run
45.539 + /// cs.lowerMap(lower).upperMap(upper).costMap(cost)
45.540 + /// .supplyMap(sup).run();
45.541 + ///
45.542 + /// // Run again with modified cost map (resetParams() is not called,
45.543 + /// // so only the cost map have to be set again)
45.544 + /// cost[e] += 100;
45.545 + /// cs.costMap(cost).run();
45.546 + ///
45.547 + /// // Run again from scratch using resetParams()
45.548 + /// // (the lower bounds will be set to zero on all arcs)
45.549 + /// cs.resetParams();
45.550 + /// cs.upperMap(capacity).costMap(cost)
45.551 + /// .supplyMap(sup).run();
45.552 + /// \endcode
45.553 + ///
45.554 + /// \return <tt>(*this)</tt>
45.555 + ///
45.556 + /// \see reset(), run()
45.557 + CostScaling& resetParams() {
45.558 + for (int i = 0; i != _res_node_num; ++i) {
45.559 + _supply[i] = 0;
45.560 + }
45.561 + int limit = _first_out[_root];
45.562 + for (int j = 0; j != limit; ++j) {
45.563 + _lower[j] = 0;
45.564 + _upper[j] = INF;
45.565 + _scost[j] = _forward[j] ? 1 : -1;
45.566 + }
45.567 + for (int j = limit; j != _res_arc_num; ++j) {
45.568 + _lower[j] = 0;
45.569 + _upper[j] = INF;
45.570 + _scost[j] = 0;
45.571 + _scost[_reverse[j]] = 0;
45.572 + }
45.573 + _have_lower = false;
45.574 + return *this;
45.575 + }
45.576 +
45.577 + /// \brief Reset all the parameters that have been given before.
45.578 + ///
45.579 + /// This function resets all the paramaters that have been given
45.580 + /// before using functions \ref lowerMap(), \ref upperMap(),
45.581 + /// \ref costMap(), \ref supplyMap(), \ref stSupply().
45.582 + ///
45.583 + /// It is useful for multiple run() calls. If this function is not
45.584 + /// used, all the parameters given before are kept for the next
45.585 + /// \ref run() call.
45.586 + /// However, the underlying digraph must not be modified after this
45.587 + /// class have been constructed, since it copies and extends the graph.
45.588 + /// \return <tt>(*this)</tt>
45.589 + CostScaling& reset() {
45.590 + // Resize vectors
45.591 + _node_num = countNodes(_graph);
45.592 + _arc_num = countArcs(_graph);
45.593 + _res_node_num = _node_num + 1;
45.594 + _res_arc_num = 2 * (_arc_num + _node_num);
45.595 + _root = _node_num;
45.596 +
45.597 + _first_out.resize(_res_node_num + 1);
45.598 + _forward.resize(_res_arc_num);
45.599 + _source.resize(_res_arc_num);
45.600 + _target.resize(_res_arc_num);
45.601 + _reverse.resize(_res_arc_num);
45.602 +
45.603 + _lower.resize(_res_arc_num);
45.604 + _upper.resize(_res_arc_num);
45.605 + _scost.resize(_res_arc_num);
45.606 + _supply.resize(_res_node_num);
45.607 +
45.608 + _res_cap.resize(_res_arc_num);
45.609 + _cost.resize(_res_arc_num);
45.610 + _pi.resize(_res_node_num);
45.611 + _excess.resize(_res_node_num);
45.612 + _next_out.resize(_res_node_num);
45.613 +
45.614 + _arc_vec.reserve(_res_arc_num);
45.615 + _cost_vec.reserve(_res_arc_num);
45.616 +
45.617 + // Copy the graph
45.618 + int i = 0, j = 0, k = 2 * _arc_num + _node_num;
45.619 + for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
45.620 + _node_id[n] = i;
45.621 + }
45.622 + i = 0;
45.623 + for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
45.624 + _first_out[i] = j;
45.625 + for (OutArcIt a(_graph, n); a != INVALID; ++a, ++j) {
45.626 + _arc_idf[a] = j;
45.627 + _forward[j] = true;
45.628 + _source[j] = i;
45.629 + _target[j] = _node_id[_graph.runningNode(a)];
45.630 + }
45.631 + for (InArcIt a(_graph, n); a != INVALID; ++a, ++j) {
45.632 + _arc_idb[a] = j;
45.633 + _forward[j] = false;
45.634 + _source[j] = i;
45.635 + _target[j] = _node_id[_graph.runningNode(a)];
45.636 + }
45.637 + _forward[j] = false;
45.638 + _source[j] = i;
45.639 + _target[j] = _root;
45.640 + _reverse[j] = k;
45.641 + _forward[k] = true;
45.642 + _source[k] = _root;
45.643 + _target[k] = i;
45.644 + _reverse[k] = j;
45.645 + ++j; ++k;
45.646 + }
45.647 + _first_out[i] = j;
45.648 + _first_out[_res_node_num] = k;
45.649 + for (ArcIt a(_graph); a != INVALID; ++a) {
45.650 + int fi = _arc_idf[a];
45.651 + int bi = _arc_idb[a];
45.652 + _reverse[fi] = bi;
45.653 + _reverse[bi] = fi;
45.654 + }
45.655 +
45.656 + // Reset parameters
45.657 + resetParams();
45.658 + return *this;
45.659 + }
45.660 +
45.661 + /// @}
45.662 +
45.663 + /// \name Query Functions
45.664 + /// The results of the algorithm can be obtained using these
45.665 + /// functions.\n
45.666 + /// The \ref run() function must be called before using them.
45.667 +
45.668 + /// @{
45.669 +
45.670 + /// \brief Return the total cost of the found flow.
45.671 + ///
45.672 + /// This function returns the total cost of the found flow.
45.673 + /// Its complexity is O(e).
45.674 + ///
45.675 + /// \note The return type of the function can be specified as a
45.676 + /// template parameter. For example,
45.677 + /// \code
45.678 + /// cs.totalCost<double>();
45.679 + /// \endcode
45.680 + /// It is useful if the total cost cannot be stored in the \c Cost
45.681 + /// type of the algorithm, which is the default return type of the
45.682 + /// function.
45.683 + ///
45.684 + /// \pre \ref run() must be called before using this function.
45.685 + template <typename Number>
45.686 + Number totalCost() const {
45.687 + Number c = 0;
45.688 + for (ArcIt a(_graph); a != INVALID; ++a) {
45.689 + int i = _arc_idb[a];
45.690 + c += static_cast<Number>(_res_cap[i]) *
45.691 + (-static_cast<Number>(_scost[i]));
45.692 + }
45.693 + return c;
45.694 + }
45.695 +
45.696 +#ifndef DOXYGEN
45.697 + Cost totalCost() const {
45.698 + return totalCost<Cost>();
45.699 + }
45.700 +#endif
45.701 +
45.702 + /// \brief Return the flow on the given arc.
45.703 + ///
45.704 + /// This function returns the flow on the given arc.
45.705 + ///
45.706 + /// \pre \ref run() must be called before using this function.
45.707 + Value flow(const Arc& a) const {
45.708 + return _res_cap[_arc_idb[a]];
45.709 + }
45.710 +
45.711 + /// \brief Return the flow map (the primal solution).
45.712 + ///
45.713 + /// This function copies the flow value on each arc into the given
45.714 + /// map. The \c Value type of the algorithm must be convertible to
45.715 + /// the \c Value type of the map.
45.716 + ///
45.717 + /// \pre \ref run() must be called before using this function.
45.718 + template <typename FlowMap>
45.719 + void flowMap(FlowMap &map) const {
45.720 + for (ArcIt a(_graph); a != INVALID; ++a) {
45.721 + map.set(a, _res_cap[_arc_idb[a]]);
45.722 + }
45.723 + }
45.724 +
45.725 + /// \brief Return the potential (dual value) of the given node.
45.726 + ///
45.727 + /// This function returns the potential (dual value) of the
45.728 + /// given node.
45.729 + ///
45.730 + /// \pre \ref run() must be called before using this function.
45.731 + Cost potential(const Node& n) const {
45.732 + return static_cast<Cost>(_pi[_node_id[n]]);
45.733 + }
45.734 +
45.735 + /// \brief Return the potential map (the dual solution).
45.736 + ///
45.737 + /// This function copies the potential (dual value) of each node
45.738 + /// into the given map.
45.739 + /// The \c Cost type of the algorithm must be convertible to the
45.740 + /// \c Value type of the map.
45.741 + ///
45.742 + /// \pre \ref run() must be called before using this function.
45.743 + template <typename PotentialMap>
45.744 + void potentialMap(PotentialMap &map) const {
45.745 + for (NodeIt n(_graph); n != INVALID; ++n) {
45.746 + map.set(n, static_cast<Cost>(_pi[_node_id[n]]));
45.747 + }
45.748 + }
45.749 +
45.750 + /// @}
45.751 +
45.752 + private:
45.753 +
45.754 + // Initialize the algorithm
45.755 + ProblemType init() {
45.756 + if (_res_node_num <= 1) return INFEASIBLE;
45.757 +
45.758 + // Check the sum of supply values
45.759 + _sum_supply = 0;
45.760 + for (int i = 0; i != _root; ++i) {
45.761 + _sum_supply += _supply[i];
45.762 + }
45.763 + if (_sum_supply > 0) return INFEASIBLE;
45.764 +
45.765 +
45.766 + // Initialize vectors
45.767 + for (int i = 0; i != _res_node_num; ++i) {
45.768 + _pi[i] = 0;
45.769 + _excess[i] = _supply[i];
45.770 + }
45.771 +
45.772 + // Remove infinite upper bounds and check negative arcs
45.773 + const Value MAX = std::numeric_limits<Value>::max();
45.774 + int last_out;
45.775 + if (_have_lower) {
45.776 + for (int i = 0; i != _root; ++i) {
45.777 + last_out = _first_out[i+1];
45.778 + for (int j = _first_out[i]; j != last_out; ++j) {
45.779 + if (_forward[j]) {
45.780 + Value c = _scost[j] < 0 ? _upper[j] : _lower[j];
45.781 + if (c >= MAX) return UNBOUNDED;
45.782 + _excess[i] -= c;
45.783 + _excess[_target[j]] += c;
45.784 + }
45.785 + }
45.786 + }
45.787 + } else {
45.788 + for (int i = 0; i != _root; ++i) {
45.789 + last_out = _first_out[i+1];
45.790 + for (int j = _first_out[i]; j != last_out; ++j) {
45.791 + if (_forward[j] && _scost[j] < 0) {
45.792 + Value c = _upper[j];
45.793 + if (c >= MAX) return UNBOUNDED;
45.794 + _excess[i] -= c;
45.795 + _excess[_target[j]] += c;
45.796 + }
45.797 + }
45.798 + }
45.799 + }
45.800 + Value ex, max_cap = 0;
45.801 + for (int i = 0; i != _res_node_num; ++i) {
45.802 + ex = _excess[i];
45.803 + _excess[i] = 0;
45.804 + if (ex < 0) max_cap -= ex;
45.805 + }
45.806 + for (int j = 0; j != _res_arc_num; ++j) {
45.807 + if (_upper[j] >= MAX) _upper[j] = max_cap;
45.808 + }
45.809 +
45.810 + // Initialize the large cost vector and the epsilon parameter
45.811 + _epsilon = 0;
45.812 + LargeCost lc;
45.813 + for (int i = 0; i != _root; ++i) {
45.814 + last_out = _first_out[i+1];
45.815 + for (int j = _first_out[i]; j != last_out; ++j) {
45.816 + lc = static_cast<LargeCost>(_scost[j]) * _res_node_num * _alpha;
45.817 + _cost[j] = lc;
45.818 + if (lc > _epsilon) _epsilon = lc;
45.819 + }
45.820 + }
45.821 + _epsilon /= _alpha;
45.822 +
45.823 + // Initialize maps for Circulation and remove non-zero lower bounds
45.824 + ConstMap<Arc, Value> low(0);
45.825 + typedef typename Digraph::template ArcMap<Value> ValueArcMap;
45.826 + typedef typename Digraph::template NodeMap<Value> ValueNodeMap;
45.827 + ValueArcMap cap(_graph), flow(_graph);
45.828 + ValueNodeMap sup(_graph);
45.829 + for (NodeIt n(_graph); n != INVALID; ++n) {
45.830 + sup[n] = _supply[_node_id[n]];
45.831 + }
45.832 + if (_have_lower) {
45.833 + for (ArcIt a(_graph); a != INVALID; ++a) {
45.834 + int j = _arc_idf[a];
45.835 + Value c = _lower[j];
45.836 + cap[a] = _upper[j] - c;
45.837 + sup[_graph.source(a)] -= c;
45.838 + sup[_graph.target(a)] += c;
45.839 + }
45.840 + } else {
45.841 + for (ArcIt a(_graph); a != INVALID; ++a) {
45.842 + cap[a] = _upper[_arc_idf[a]];
45.843 + }
45.844 + }
45.845 +
45.846 + _sup_node_num = 0;
45.847 + for (NodeIt n(_graph); n != INVALID; ++n) {
45.848 + if (sup[n] > 0) ++_sup_node_num;
45.849 + }
45.850 +
45.851 + // Find a feasible flow using Circulation
45.852 + Circulation<Digraph, ConstMap<Arc, Value>, ValueArcMap, ValueNodeMap>
45.853 + circ(_graph, low, cap, sup);
45.854 + if (!circ.flowMap(flow).run()) return INFEASIBLE;
45.855 +
45.856 + // Set residual capacities and handle GEQ supply type
45.857 + if (_sum_supply < 0) {
45.858 + for (ArcIt a(_graph); a != INVALID; ++a) {
45.859 + Value fa = flow[a];
45.860 + _res_cap[_arc_idf[a]] = cap[a] - fa;
45.861 + _res_cap[_arc_idb[a]] = fa;
45.862 + sup[_graph.source(a)] -= fa;
45.863 + sup[_graph.target(a)] += fa;
45.864 + }
45.865 + for (NodeIt n(_graph); n != INVALID; ++n) {
45.866 + _excess[_node_id[n]] = sup[n];
45.867 + }
45.868 + for (int a = _first_out[_root]; a != _res_arc_num; ++a) {
45.869 + int u = _target[a];
45.870 + int ra = _reverse[a];
45.871 + _res_cap[a] = -_sum_supply + 1;
45.872 + _res_cap[ra] = -_excess[u];
45.873 + _cost[a] = 0;
45.874 + _cost[ra] = 0;
45.875 + _excess[u] = 0;
45.876 + }
45.877 + } else {
45.878 + for (ArcIt a(_graph); a != INVALID; ++a) {
45.879 + Value fa = flow[a];
45.880 + _res_cap[_arc_idf[a]] = cap[a] - fa;
45.881 + _res_cap[_arc_idb[a]] = fa;
45.882 + }
45.883 + for (int a = _first_out[_root]; a != _res_arc_num; ++a) {
45.884 + int ra = _reverse[a];
45.885 + _res_cap[a] = 0;
45.886 + _res_cap[ra] = 0;
45.887 + _cost[a] = 0;
45.888 + _cost[ra] = 0;
45.889 + }
45.890 + }
45.891 +
45.892 + return OPTIMAL;
45.893 + }
45.894 +
45.895 + // Execute the algorithm and transform the results
45.896 + void start(Method method) {
45.897 + // Maximum path length for partial augment
45.898 + const int MAX_PATH_LENGTH = 4;
45.899 +
45.900 + // Initialize data structures for buckets
45.901 + _max_rank = _alpha * _res_node_num;
45.902 + _buckets.resize(_max_rank);
45.903 + _bucket_next.resize(_res_node_num + 1);
45.904 + _bucket_prev.resize(_res_node_num + 1);
45.905 + _rank.resize(_res_node_num + 1);
45.906 +
45.907 + // Execute the algorithm
45.908 + switch (method) {
45.909 + case PUSH:
45.910 + startPush();
45.911 + break;
45.912 + case AUGMENT:
45.913 + startAugment(_res_node_num - 1);
45.914 + break;
45.915 + case PARTIAL_AUGMENT:
45.916 + startAugment(MAX_PATH_LENGTH);
45.917 + break;
45.918 + }
45.919 +
45.920 + // Compute node potentials for the original costs
45.921 + _arc_vec.clear();
45.922 + _cost_vec.clear();
45.923 + for (int j = 0; j != _res_arc_num; ++j) {
45.924 + if (_res_cap[j] > 0) {
45.925 + _arc_vec.push_back(IntPair(_source[j], _target[j]));
45.926 + _cost_vec.push_back(_scost[j]);
45.927 + }
45.928 + }
45.929 + _sgr.build(_res_node_num, _arc_vec.begin(), _arc_vec.end());
45.930 +
45.931 + typename BellmanFord<StaticDigraph, LargeCostArcMap>
45.932 + ::template SetDistMap<LargeCostNodeMap>::Create bf(_sgr, _cost_map);
45.933 + bf.distMap(_pi_map);
45.934 + bf.init(0);
45.935 + bf.start();
45.936 +
45.937 + // Handle non-zero lower bounds
45.938 + if (_have_lower) {
45.939 + int limit = _first_out[_root];
45.940 + for (int j = 0; j != limit; ++j) {
45.941 + if (!_forward[j]) _res_cap[j] += _lower[j];
45.942 + }
45.943 + }
45.944 + }
45.945 +
45.946 + // Initialize a cost scaling phase
45.947 + void initPhase() {
45.948 + // Saturate arcs not satisfying the optimality condition
45.949 + for (int u = 0; u != _res_node_num; ++u) {
45.950 + int last_out = _first_out[u+1];
45.951 + LargeCost pi_u = _pi[u];
45.952 + for (int a = _first_out[u]; a != last_out; ++a) {
45.953 + int v = _target[a];
45.954 + if (_res_cap[a] > 0 && _cost[a] + pi_u - _pi[v] < 0) {
45.955 + Value delta = _res_cap[a];
45.956 + _excess[u] -= delta;
45.957 + _excess[v] += delta;
45.958 + _res_cap[a] = 0;
45.959 + _res_cap[_reverse[a]] += delta;
45.960 + }
45.961 + }
45.962 + }
45.963 +
45.964 + // Find active nodes (i.e. nodes with positive excess)
45.965 + for (int u = 0; u != _res_node_num; ++u) {
45.966 + if (_excess[u] > 0) _active_nodes.push_back(u);
45.967 + }
45.968 +
45.969 + // Initialize the next arcs
45.970 + for (int u = 0; u != _res_node_num; ++u) {
45.971 + _next_out[u] = _first_out[u];
45.972 + }
45.973 + }
45.974 +
45.975 + // Early termination heuristic
45.976 + bool earlyTermination() {
45.977 + const double EARLY_TERM_FACTOR = 3.0;
45.978 +
45.979 + // Build a static residual graph
45.980 + _arc_vec.clear();
45.981 + _cost_vec.clear();
45.982 + for (int j = 0; j != _res_arc_num; ++j) {
45.983 + if (_res_cap[j] > 0) {
45.984 + _arc_vec.push_back(IntPair(_source[j], _target[j]));
45.985 + _cost_vec.push_back(_cost[j] + 1);
45.986 + }
45.987 + }
45.988 + _sgr.build(_res_node_num, _arc_vec.begin(), _arc_vec.end());
45.989 +
45.990 + // Run Bellman-Ford algorithm to check if the current flow is optimal
45.991 + BellmanFord<StaticDigraph, LargeCostArcMap> bf(_sgr, _cost_map);
45.992 + bf.init(0);
45.993 + bool done = false;
45.994 + int K = int(EARLY_TERM_FACTOR * std::sqrt(double(_res_node_num)));
45.995 + for (int i = 0; i < K && !done; ++i) {
45.996 + done = bf.processNextWeakRound();
45.997 + }
45.998 + return done;
45.999 + }
45.1000 +
45.1001 + // Global potential update heuristic
45.1002 + void globalUpdate() {
45.1003 + int bucket_end = _root + 1;
45.1004 +
45.1005 + // Initialize buckets
45.1006 + for (int r = 0; r != _max_rank; ++r) {
45.1007 + _buckets[r] = bucket_end;
45.1008 + }
45.1009 + Value total_excess = 0;
45.1010 + for (int i = 0; i != _res_node_num; ++i) {
45.1011 + if (_excess[i] < 0) {
45.1012 + _rank[i] = 0;
45.1013 + _bucket_next[i] = _buckets[0];
45.1014 + _bucket_prev[_buckets[0]] = i;
45.1015 + _buckets[0] = i;
45.1016 + } else {
45.1017 + total_excess += _excess[i];
45.1018 + _rank[i] = _max_rank;
45.1019 + }
45.1020 + }
45.1021 + if (total_excess == 0) return;
45.1022 +
45.1023 + // Search the buckets
45.1024 + int r = 0;
45.1025 + for ( ; r != _max_rank; ++r) {
45.1026 + while (_buckets[r] != bucket_end) {
45.1027 + // Remove the first node from the current bucket
45.1028 + int u = _buckets[r];
45.1029 + _buckets[r] = _bucket_next[u];
45.1030 +
45.1031 + // Search the incomming arcs of u
45.1032 + LargeCost pi_u = _pi[u];
45.1033 + int last_out = _first_out[u+1];
45.1034 + for (int a = _first_out[u]; a != last_out; ++a) {
45.1035 + int ra = _reverse[a];
45.1036 + if (_res_cap[ra] > 0) {
45.1037 + int v = _source[ra];
45.1038 + int old_rank_v = _rank[v];
45.1039 + if (r < old_rank_v) {
45.1040 + // Compute the new rank of v
45.1041 + LargeCost nrc = (_cost[ra] + _pi[v] - pi_u) / _epsilon;
45.1042 + int new_rank_v = old_rank_v;
45.1043 + if (nrc < LargeCost(_max_rank))
45.1044 + new_rank_v = r + 1 + int(nrc);
45.1045 +
45.1046 + // Change the rank of v
45.1047 + if (new_rank_v < old_rank_v) {
45.1048 + _rank[v] = new_rank_v;
45.1049 + _next_out[v] = _first_out[v];
45.1050 +
45.1051 + // Remove v from its old bucket
45.1052 + if (old_rank_v < _max_rank) {
45.1053 + if (_buckets[old_rank_v] == v) {
45.1054 + _buckets[old_rank_v] = _bucket_next[v];
45.1055 + } else {
45.1056 + _bucket_next[_bucket_prev[v]] = _bucket_next[v];
45.1057 + _bucket_prev[_bucket_next[v]] = _bucket_prev[v];
45.1058 + }
45.1059 + }
45.1060 +
45.1061 + // Insert v to its new bucket
45.1062 + _bucket_next[v] = _buckets[new_rank_v];
45.1063 + _bucket_prev[_buckets[new_rank_v]] = v;
45.1064 + _buckets[new_rank_v] = v;
45.1065 + }
45.1066 + }
45.1067 + }
45.1068 + }
45.1069 +
45.1070 + // Finish search if there are no more active nodes
45.1071 + if (_excess[u] > 0) {
45.1072 + total_excess -= _excess[u];
45.1073 + if (total_excess <= 0) break;
45.1074 + }
45.1075 + }
45.1076 + if (total_excess <= 0) break;
45.1077 + }
45.1078 +
45.1079 + // Relabel nodes
45.1080 + for (int u = 0; u != _res_node_num; ++u) {
45.1081 + int k = std::min(_rank[u], r);
45.1082 + if (k > 0) {
45.1083 + _pi[u] -= _epsilon * k;
45.1084 + _next_out[u] = _first_out[u];
45.1085 + }
45.1086 + }
45.1087 + }
45.1088 +
45.1089 + /// Execute the algorithm performing augment and relabel operations
45.1090 + void startAugment(int max_length) {
45.1091 + // Paramters for heuristics
45.1092 + const int EARLY_TERM_EPSILON_LIMIT = 1000;
45.1093 + const double GLOBAL_UPDATE_FACTOR = 3.0;
45.1094 +
45.1095 + const int global_update_freq = int(GLOBAL_UPDATE_FACTOR *
45.1096 + (_res_node_num + _sup_node_num * _sup_node_num));
45.1097 + int next_update_limit = global_update_freq;
45.1098 +
45.1099 + int relabel_cnt = 0;
45.1100 +
45.1101 + // Perform cost scaling phases
45.1102 + std::vector<int> path;
45.1103 + for ( ; _epsilon >= 1; _epsilon = _epsilon < _alpha && _epsilon > 1 ?
45.1104 + 1 : _epsilon / _alpha )
45.1105 + {
45.1106 + // Early termination heuristic
45.1107 + if (_epsilon <= EARLY_TERM_EPSILON_LIMIT) {
45.1108 + if (earlyTermination()) break;
45.1109 + }
45.1110 +
45.1111 + // Initialize current phase
45.1112 + initPhase();
45.1113 +
45.1114 + // Perform partial augment and relabel operations
45.1115 + while (true) {
45.1116 + // Select an active node (FIFO selection)
45.1117 + while (_active_nodes.size() > 0 &&
45.1118 + _excess[_active_nodes.front()] <= 0) {
45.1119 + _active_nodes.pop_front();
45.1120 + }
45.1121 + if (_active_nodes.size() == 0) break;
45.1122 + int start = _active_nodes.front();
45.1123 +
45.1124 + // Find an augmenting path from the start node
45.1125 + path.clear();
45.1126 + int tip = start;
45.1127 + while (_excess[tip] >= 0 && int(path.size()) < max_length) {
45.1128 + int u;
45.1129 + LargeCost min_red_cost, rc, pi_tip = _pi[tip];
45.1130 + int last_out = _first_out[tip+1];
45.1131 + for (int a = _next_out[tip]; a != last_out; ++a) {
45.1132 + u = _target[a];
45.1133 + if (_res_cap[a] > 0 && _cost[a] + pi_tip - _pi[u] < 0) {
45.1134 + path.push_back(a);
45.1135 + _next_out[tip] = a;
45.1136 + tip = u;
45.1137 + goto next_step;
45.1138 + }
45.1139 + }
45.1140 +
45.1141 + // Relabel tip node
45.1142 + min_red_cost = std::numeric_limits<LargeCost>::max();
45.1143 + if (tip != start) {
45.1144 + int ra = _reverse[path.back()];
45.1145 + min_red_cost = _cost[ra] + pi_tip - _pi[_target[ra]];
45.1146 + }
45.1147 + for (int a = _first_out[tip]; a != last_out; ++a) {
45.1148 + rc = _cost[a] + pi_tip - _pi[_target[a]];
45.1149 + if (_res_cap[a] > 0 && rc < min_red_cost) {
45.1150 + min_red_cost = rc;
45.1151 + }
45.1152 + }
45.1153 + _pi[tip] -= min_red_cost + _epsilon;
45.1154 + _next_out[tip] = _first_out[tip];
45.1155 + ++relabel_cnt;
45.1156 +
45.1157 + // Step back
45.1158 + if (tip != start) {
45.1159 + tip = _source[path.back()];
45.1160 + path.pop_back();
45.1161 + }
45.1162 +
45.1163 + next_step: ;
45.1164 + }
45.1165 +
45.1166 + // Augment along the found path (as much flow as possible)
45.1167 + Value delta;
45.1168 + int pa, u, v = start;
45.1169 + for (int i = 0; i != int(path.size()); ++i) {
45.1170 + pa = path[i];
45.1171 + u = v;
45.1172 + v = _target[pa];
45.1173 + delta = std::min(_res_cap[pa], _excess[u]);
45.1174 + _res_cap[pa] -= delta;
45.1175 + _res_cap[_reverse[pa]] += delta;
45.1176 + _excess[u] -= delta;
45.1177 + _excess[v] += delta;
45.1178 + if (_excess[v] > 0 && _excess[v] <= delta)
45.1179 + _active_nodes.push_back(v);
45.1180 + }
45.1181 +
45.1182 + // Global update heuristic
45.1183 + if (relabel_cnt >= next_update_limit) {
45.1184 + globalUpdate();
45.1185 + next_update_limit += global_update_freq;
45.1186 + }
45.1187 + }
45.1188 + }
45.1189 + }
45.1190 +
45.1191 + /// Execute the algorithm performing push and relabel operations
45.1192 + void startPush() {
45.1193 + // Paramters for heuristics
45.1194 + const int EARLY_TERM_EPSILON_LIMIT = 1000;
45.1195 + const double GLOBAL_UPDATE_FACTOR = 2.0;
45.1196 +
45.1197 + const int global_update_freq = int(GLOBAL_UPDATE_FACTOR *
45.1198 + (_res_node_num + _sup_node_num * _sup_node_num));
45.1199 + int next_update_limit = global_update_freq;
45.1200 +
45.1201 + int relabel_cnt = 0;
45.1202 +
45.1203 + // Perform cost scaling phases
45.1204 + BoolVector hyper(_res_node_num, false);
45.1205 + LargeCostVector hyper_cost(_res_node_num);
45.1206 + for ( ; _epsilon >= 1; _epsilon = _epsilon < _alpha && _epsilon > 1 ?
45.1207 + 1 : _epsilon / _alpha )
45.1208 + {
45.1209 + // Early termination heuristic
45.1210 + if (_epsilon <= EARLY_TERM_EPSILON_LIMIT) {
45.1211 + if (earlyTermination()) break;
45.1212 + }
45.1213 +
45.1214 + // Initialize current phase
45.1215 + initPhase();
45.1216 +
45.1217 + // Perform push and relabel operations
45.1218 + while (_active_nodes.size() > 0) {
45.1219 + LargeCost min_red_cost, rc, pi_n;
45.1220 + Value delta;
45.1221 + int n, t, a, last_out = _res_arc_num;
45.1222 +
45.1223 + next_node:
45.1224 + // Select an active node (FIFO selection)
45.1225 + n = _active_nodes.front();
45.1226 + last_out = _first_out[n+1];
45.1227 + pi_n = _pi[n];
45.1228 +
45.1229 + // Perform push operations if there are admissible arcs
45.1230 + if (_excess[n] > 0) {
45.1231 + for (a = _next_out[n]; a != last_out; ++a) {
45.1232 + if (_res_cap[a] > 0 &&
45.1233 + _cost[a] + pi_n - _pi[_target[a]] < 0) {
45.1234 + delta = std::min(_res_cap[a], _excess[n]);
45.1235 + t = _target[a];
45.1236 +
45.1237 + // Push-look-ahead heuristic
45.1238 + Value ahead = -_excess[t];
45.1239 + int last_out_t = _first_out[t+1];
45.1240 + LargeCost pi_t = _pi[t];
45.1241 + for (int ta = _next_out[t]; ta != last_out_t; ++ta) {
45.1242 + if (_res_cap[ta] > 0 &&
45.1243 + _cost[ta] + pi_t - _pi[_target[ta]] < 0)
45.1244 + ahead += _res_cap[ta];
45.1245 + if (ahead >= delta) break;
45.1246 + }
45.1247 + if (ahead < 0) ahead = 0;
45.1248 +
45.1249 + // Push flow along the arc
45.1250 + if (ahead < delta && !hyper[t]) {
45.1251 + _res_cap[a] -= ahead;
45.1252 + _res_cap[_reverse[a]] += ahead;
45.1253 + _excess[n] -= ahead;
45.1254 + _excess[t] += ahead;
45.1255 + _active_nodes.push_front(t);
45.1256 + hyper[t] = true;
45.1257 + hyper_cost[t] = _cost[a] + pi_n - pi_t;
45.1258 + _next_out[n] = a;
45.1259 + goto next_node;
45.1260 + } else {
45.1261 + _res_cap[a] -= delta;
45.1262 + _res_cap[_reverse[a]] += delta;
45.1263 + _excess[n] -= delta;
45.1264 + _excess[t] += delta;
45.1265 + if (_excess[t] > 0 && _excess[t] <= delta)
45.1266 + _active_nodes.push_back(t);
45.1267 + }
45.1268 +
45.1269 + if (_excess[n] == 0) {
45.1270 + _next_out[n] = a;
45.1271 + goto remove_nodes;
45.1272 + }
45.1273 + }
45.1274 + }
45.1275 + _next_out[n] = a;
45.1276 + }
45.1277 +
45.1278 + // Relabel the node if it is still active (or hyper)
45.1279 + if (_excess[n] > 0 || hyper[n]) {
45.1280 + min_red_cost = hyper[n] ? -hyper_cost[n] :
45.1281 + std::numeric_limits<LargeCost>::max();
45.1282 + for (int a = _first_out[n]; a != last_out; ++a) {
45.1283 + rc = _cost[a] + pi_n - _pi[_target[a]];
45.1284 + if (_res_cap[a] > 0 && rc < min_red_cost) {
45.1285 + min_red_cost = rc;
45.1286 + }
45.1287 + }
45.1288 + _pi[n] -= min_red_cost + _epsilon;
45.1289 + _next_out[n] = _first_out[n];
45.1290 + hyper[n] = false;
45.1291 + ++relabel_cnt;
45.1292 + }
45.1293 +
45.1294 + // Remove nodes that are not active nor hyper
45.1295 + remove_nodes:
45.1296 + while ( _active_nodes.size() > 0 &&
45.1297 + _excess[_active_nodes.front()] <= 0 &&
45.1298 + !hyper[_active_nodes.front()] ) {
45.1299 + _active_nodes.pop_front();
45.1300 + }
45.1301 +
45.1302 + // Global update heuristic
45.1303 + if (relabel_cnt >= next_update_limit) {
45.1304 + globalUpdate();
45.1305 + for (int u = 0; u != _res_node_num; ++u)
45.1306 + hyper[u] = false;
45.1307 + next_update_limit += global_update_freq;
45.1308 + }
45.1309 + }
45.1310 + }
45.1311 + }
45.1312 +
45.1313 + }; //class CostScaling
45.1314 +
45.1315 + ///@}
45.1316 +
45.1317 +} //namespace lemon
45.1318 +
45.1319 +#endif //LEMON_COST_SCALING_H
46.1 --- a/lemon/counter.h Tue Dec 20 17:44:38 2011 +0100
46.2 +++ b/lemon/counter.h Tue Dec 20 18:15:14 2011 +0100
46.3 @@ -212,7 +212,7 @@
46.4
46.5 /// 'Do nothing' version of Counter.
46.6
46.7 - /// This class can be used in the same way as \ref Counter however it
46.8 + /// This class can be used in the same way as \ref Counter, but it
46.9 /// does not count at all and does not print report on destruction.
46.10 ///
46.11 /// Replacing a \ref Counter with a \ref NoCounter makes it possible
47.1 --- a/lemon/cplex.cc Tue Dec 20 17:44:38 2011 +0100
47.2 +++ b/lemon/cplex.cc Tue Dec 20 18:15:14 2011 +0100
47.3 @@ -2,7 +2,7 @@
47.4 *
47.5 * This file is a part of LEMON, a generic C++ optimization library.
47.6 *
47.7 - * Copyright (C) 2003-2009
47.8 + * Copyright (C) 2003-2010
47.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
47.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
47.11 *
47.12 @@ -111,6 +111,39 @@
47.13 return i;
47.14 }
47.15
47.16 + int CplexBase::_addRow(Value lb, ExprIterator b,
47.17 + ExprIterator e, Value ub) {
47.18 + int i = CPXgetnumrows(cplexEnv(), _prob);
47.19 + if (lb == -INF) {
47.20 + const char s = 'L';
47.21 + CPXnewrows(cplexEnv(), _prob, 1, &ub, &s, 0, 0);
47.22 + } else if (ub == INF) {
47.23 + const char s = 'G';
47.24 + CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, 0, 0);
47.25 + } else if (lb == ub){
47.26 + const char s = 'E';
47.27 + CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, 0, 0);
47.28 + } else {
47.29 + const char s = 'R';
47.30 + double len = ub - lb;
47.31 + CPXnewrows(cplexEnv(), _prob, 1, &lb, &s, &len, 0);
47.32 + }
47.33 +
47.34 + std::vector<int> indices;
47.35 + std::vector<int> rowlist;
47.36 + std::vector<Value> values;
47.37 +
47.38 + for(ExprIterator it=b; it!=e; ++it) {
47.39 + indices.push_back(it->first);
47.40 + values.push_back(it->second);
47.41 + rowlist.push_back(i);
47.42 + }
47.43 +
47.44 + CPXchgcoeflist(cplexEnv(), _prob, values.size(),
47.45 + &rowlist.front(), &indices.front(), &values.front());
47.46 +
47.47 + return i;
47.48 + }
47.49
47.50 void CplexBase::_eraseCol(int i) {
47.51 CPXdelcols(cplexEnv(), _prob, i, i);
47.52 @@ -456,7 +489,7 @@
47.53 }
47.54
47.55 void CplexBase::_applyMessageLevel() {
47.56 - CPXsetintparam(cplexEnv(), CPX_PARAM_SCRIND,
47.57 + CPXsetintparam(cplexEnv(), CPX_PARAM_SCRIND,
47.58 _message_enabled ? CPX_ON : CPX_OFF);
47.59 }
47.60
48.1 --- a/lemon/cplex.h Tue Dec 20 17:44:38 2011 +0100
48.2 +++ b/lemon/cplex.h Tue Dec 20 18:15:14 2011 +0100
48.3 @@ -93,6 +93,7 @@
48.4
48.5 virtual int _addCol();
48.6 virtual int _addRow();
48.7 + virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
48.8
48.9 virtual void _eraseCol(int i);
48.10 virtual void _eraseRow(int i);
49.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
49.2 +++ b/lemon/cycle_canceling.h Tue Dec 20 18:15:14 2011 +0100
49.3 @@ -0,0 +1,1170 @@
49.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
49.5 + *
49.6 + * This file is a part of LEMON, a generic C++ optimization library.
49.7 + *
49.8 + * Copyright (C) 2003-2010
49.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
49.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
49.11 + *
49.12 + * Permission to use, modify and distribute this software is granted
49.13 + * provided that this copyright notice appears in all copies. For
49.14 + * precise terms see the accompanying LICENSE file.
49.15 + *
49.16 + * This software is provided "AS IS" with no warranty of any kind,
49.17 + * express or implied, and with no claim as to its suitability for any
49.18 + * purpose.
49.19 + *
49.20 + */
49.21 +
49.22 +#ifndef LEMON_CYCLE_CANCELING_H
49.23 +#define LEMON_CYCLE_CANCELING_H
49.24 +
49.25 +/// \ingroup min_cost_flow_algs
49.26 +/// \file
49.27 +/// \brief Cycle-canceling algorithms for finding a minimum cost flow.
49.28 +
49.29 +#include <vector>
49.30 +#include <limits>
49.31 +
49.32 +#include <lemon/core.h>
49.33 +#include <lemon/maps.h>
49.34 +#include <lemon/path.h>
49.35 +#include <lemon/math.h>
49.36 +#include <lemon/static_graph.h>
49.37 +#include <lemon/adaptors.h>
49.38 +#include <lemon/circulation.h>
49.39 +#include <lemon/bellman_ford.h>
49.40 +#include <lemon/howard_mmc.h>
49.41 +
49.42 +namespace lemon {
49.43 +
49.44 + /// \addtogroup min_cost_flow_algs
49.45 + /// @{
49.46 +
49.47 + /// \brief Implementation of cycle-canceling algorithms for
49.48 + /// finding a \ref min_cost_flow "minimum cost flow".
49.49 + ///
49.50 + /// \ref CycleCanceling implements three different cycle-canceling
49.51 + /// algorithms for finding a \ref min_cost_flow "minimum cost flow"
49.52 + /// \ref amo93networkflows, \ref klein67primal,
49.53 + /// \ref goldberg89cyclecanceling.
49.54 + /// The most efficent one (both theoretically and practically)
49.55 + /// is the \ref CANCEL_AND_TIGHTEN "Cancel and Tighten" algorithm,
49.56 + /// thus it is the default method.
49.57 + /// It is strongly polynomial, but in practice, it is typically much
49.58 + /// slower than the scaling algorithms and NetworkSimplex.
49.59 + ///
49.60 + /// Most of the parameters of the problem (except for the digraph)
49.61 + /// can be given using separate functions, and the algorithm can be
49.62 + /// executed using the \ref run() function. If some parameters are not
49.63 + /// specified, then default values will be used.
49.64 + ///
49.65 + /// \tparam GR The digraph type the algorithm runs on.
49.66 + /// \tparam V The number type used for flow amounts, capacity bounds
49.67 + /// and supply values in the algorithm. By default, it is \c int.
49.68 + /// \tparam C The number type used for costs and potentials in the
49.69 + /// algorithm. By default, it is the same as \c V.
49.70 + ///
49.71 + /// \warning Both number types must be signed and all input data must
49.72 + /// be integer.
49.73 + /// \warning This algorithm does not support negative costs for such
49.74 + /// arcs that have infinite upper bound.
49.75 + ///
49.76 + /// \note For more information about the three available methods,
49.77 + /// see \ref Method.
49.78 +#ifdef DOXYGEN
49.79 + template <typename GR, typename V, typename C>
49.80 +#else
49.81 + template <typename GR, typename V = int, typename C = V>
49.82 +#endif
49.83 + class CycleCanceling
49.84 + {
49.85 + public:
49.86 +
49.87 + /// The type of the digraph
49.88 + typedef GR Digraph;
49.89 + /// The type of the flow amounts, capacity bounds and supply values
49.90 + typedef V Value;
49.91 + /// The type of the arc costs
49.92 + typedef C Cost;
49.93 +
49.94 + public:
49.95 +
49.96 + /// \brief Problem type constants for the \c run() function.
49.97 + ///
49.98 + /// Enum type containing the problem type constants that can be
49.99 + /// returned by the \ref run() function of the algorithm.
49.100 + enum ProblemType {
49.101 + /// The problem has no feasible solution (flow).
49.102 + INFEASIBLE,
49.103 + /// The problem has optimal solution (i.e. it is feasible and
49.104 + /// bounded), and the algorithm has found optimal flow and node
49.105 + /// potentials (primal and dual solutions).
49.106 + OPTIMAL,
49.107 + /// The digraph contains an arc of negative cost and infinite
49.108 + /// upper bound. It means that the objective function is unbounded
49.109 + /// on that arc, however, note that it could actually be bounded
49.110 + /// over the feasible flows, but this algroithm cannot handle
49.111 + /// these cases.
49.112 + UNBOUNDED
49.113 + };
49.114 +
49.115 + /// \brief Constants for selecting the used method.
49.116 + ///
49.117 + /// Enum type containing constants for selecting the used method
49.118 + /// for the \ref run() function.
49.119 + ///
49.120 + /// \ref CycleCanceling provides three different cycle-canceling
49.121 + /// methods. By default, \ref CANCEL_AND_TIGHTEN "Cancel and Tighten"
49.122 + /// is used, which proved to be the most efficient and the most robust
49.123 + /// on various test inputs.
49.124 + /// However, the other methods can be selected using the \ref run()
49.125 + /// function with the proper parameter.
49.126 + enum Method {
49.127 + /// A simple cycle-canceling method, which uses the
49.128 + /// \ref BellmanFord "Bellman-Ford" algorithm with limited iteration
49.129 + /// number for detecting negative cycles in the residual network.
49.130 + SIMPLE_CYCLE_CANCELING,
49.131 + /// The "Minimum Mean Cycle-Canceling" algorithm, which is a
49.132 + /// well-known strongly polynomial method
49.133 + /// \ref goldberg89cyclecanceling. It improves along a
49.134 + /// \ref min_mean_cycle "minimum mean cycle" in each iteration.
49.135 + /// Its running time complexity is O(n<sup>2</sup>m<sup>3</sup>log(n)).
49.136 + MINIMUM_MEAN_CYCLE_CANCELING,
49.137 + /// The "Cancel And Tighten" algorithm, which can be viewed as an
49.138 + /// improved version of the previous method
49.139 + /// \ref goldberg89cyclecanceling.
49.140 + /// It is faster both in theory and in practice, its running time
49.141 + /// complexity is O(n<sup>2</sup>m<sup>2</sup>log(n)).
49.142 + CANCEL_AND_TIGHTEN
49.143 + };
49.144 +
49.145 + private:
49.146 +
49.147 + TEMPLATE_DIGRAPH_TYPEDEFS(GR);
49.148 +
49.149 + typedef std::vector<int> IntVector;
49.150 + typedef std::vector<double> DoubleVector;
49.151 + typedef std::vector<Value> ValueVector;
49.152 + typedef std::vector<Cost> CostVector;
49.153 + typedef std::vector<char> BoolVector;
49.154 + // Note: vector<char> is used instead of vector<bool> for efficiency reasons
49.155 +
49.156 + private:
49.157 +
49.158 + template <typename KT, typename VT>
49.159 + class StaticVectorMap {
49.160 + public:
49.161 + typedef KT Key;
49.162 + typedef VT Value;
49.163 +
49.164 + StaticVectorMap(std::vector<Value>& v) : _v(v) {}
49.165 +
49.166 + const Value& operator[](const Key& key) const {
49.167 + return _v[StaticDigraph::id(key)];
49.168 + }
49.169 +
49.170 + Value& operator[](const Key& key) {
49.171 + return _v[StaticDigraph::id(key)];
49.172 + }
49.173 +
49.174 + void set(const Key& key, const Value& val) {
49.175 + _v[StaticDigraph::id(key)] = val;
49.176 + }
49.177 +
49.178 + private:
49.179 + std::vector<Value>& _v;
49.180 + };
49.181 +
49.182 + typedef StaticVectorMap<StaticDigraph::Node, Cost> CostNodeMap;
49.183 + typedef StaticVectorMap<StaticDigraph::Arc, Cost> CostArcMap;
49.184 +
49.185 + private:
49.186 +
49.187 +
49.188 + // Data related to the underlying digraph
49.189 + const GR &_graph;
49.190 + int _node_num;
49.191 + int _arc_num;
49.192 + int _res_node_num;
49.193 + int _res_arc_num;
49.194 + int _root;
49.195 +
49.196 + // Parameters of the problem
49.197 + bool _have_lower;
49.198 + Value _sum_supply;
49.199 +
49.200 + // Data structures for storing the digraph
49.201 + IntNodeMap _node_id;
49.202 + IntArcMap _arc_idf;
49.203 + IntArcMap _arc_idb;
49.204 + IntVector _first_out;
49.205 + BoolVector _forward;
49.206 + IntVector _source;
49.207 + IntVector _target;
49.208 + IntVector _reverse;
49.209 +
49.210 + // Node and arc data
49.211 + ValueVector _lower;
49.212 + ValueVector _upper;
49.213 + CostVector _cost;
49.214 + ValueVector _supply;
49.215 +
49.216 + ValueVector _res_cap;
49.217 + CostVector _pi;
49.218 +
49.219 + // Data for a StaticDigraph structure
49.220 + typedef std::pair<int, int> IntPair;
49.221 + StaticDigraph _sgr;
49.222 + std::vector<IntPair> _arc_vec;
49.223 + std::vector<Cost> _cost_vec;
49.224 + IntVector _id_vec;
49.225 + CostArcMap _cost_map;
49.226 + CostNodeMap _pi_map;
49.227 +
49.228 + public:
49.229 +
49.230 + /// \brief Constant for infinite upper bounds (capacities).
49.231 + ///
49.232 + /// Constant for infinite upper bounds (capacities).
49.233 + /// It is \c std::numeric_limits<Value>::infinity() if available,
49.234 + /// \c std::numeric_limits<Value>::max() otherwise.
49.235 + const Value INF;
49.236 +
49.237 + public:
49.238 +
49.239 + /// \brief Constructor.
49.240 + ///
49.241 + /// The constructor of the class.
49.242 + ///
49.243 + /// \param graph The digraph the algorithm runs on.
49.244 + CycleCanceling(const GR& graph) :
49.245 + _graph(graph), _node_id(graph), _arc_idf(graph), _arc_idb(graph),
49.246 + _cost_map(_cost_vec), _pi_map(_pi),
49.247 + INF(std::numeric_limits<Value>::has_infinity ?
49.248 + std::numeric_limits<Value>::infinity() :
49.249 + std::numeric_limits<Value>::max())
49.250 + {
49.251 + // Check the number types
49.252 + LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
49.253 + "The flow type of CycleCanceling must be signed");
49.254 + LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
49.255 + "The cost type of CycleCanceling must be signed");
49.256 +
49.257 + // Reset data structures
49.258 + reset();
49.259 + }
49.260 +
49.261 + /// \name Parameters
49.262 + /// The parameters of the algorithm can be specified using these
49.263 + /// functions.
49.264 +
49.265 + /// @{
49.266 +
49.267 + /// \brief Set the lower bounds on the arcs.
49.268 + ///
49.269 + /// This function sets the lower bounds on the arcs.
49.270 + /// If it is not used before calling \ref run(), the lower bounds
49.271 + /// will be set to zero on all arcs.
49.272 + ///
49.273 + /// \param map An arc map storing the lower bounds.
49.274 + /// Its \c Value type must be convertible to the \c Value type
49.275 + /// of the algorithm.
49.276 + ///
49.277 + /// \return <tt>(*this)</tt>
49.278 + template <typename LowerMap>
49.279 + CycleCanceling& lowerMap(const LowerMap& map) {
49.280 + _have_lower = true;
49.281 + for (ArcIt a(_graph); a != INVALID; ++a) {
49.282 + _lower[_arc_idf[a]] = map[a];
49.283 + _lower[_arc_idb[a]] = map[a];
49.284 + }
49.285 + return *this;
49.286 + }
49.287 +
49.288 + /// \brief Set the upper bounds (capacities) on the arcs.
49.289 + ///
49.290 + /// This function sets the upper bounds (capacities) on the arcs.
49.291 + /// If it is not used before calling \ref run(), the upper bounds
49.292 + /// will be set to \ref INF on all arcs (i.e. the flow value will be
49.293 + /// unbounded from above).
49.294 + ///
49.295 + /// \param map An arc map storing the upper bounds.
49.296 + /// Its \c Value type must be convertible to the \c Value type
49.297 + /// of the algorithm.
49.298 + ///
49.299 + /// \return <tt>(*this)</tt>
49.300 + template<typename UpperMap>
49.301 + CycleCanceling& upperMap(const UpperMap& map) {
49.302 + for (ArcIt a(_graph); a != INVALID; ++a) {
49.303 + _upper[_arc_idf[a]] = map[a];
49.304 + }
49.305 + return *this;
49.306 + }
49.307 +
49.308 + /// \brief Set the costs of the arcs.
49.309 + ///
49.310 + /// This function sets the costs of the arcs.
49.311 + /// If it is not used before calling \ref run(), the costs
49.312 + /// will be set to \c 1 on all arcs.
49.313 + ///
49.314 + /// \param map An arc map storing the costs.
49.315 + /// Its \c Value type must be convertible to the \c Cost type
49.316 + /// of the algorithm.
49.317 + ///
49.318 + /// \return <tt>(*this)</tt>
49.319 + template<typename CostMap>
49.320 + CycleCanceling& costMap(const CostMap& map) {
49.321 + for (ArcIt a(_graph); a != INVALID; ++a) {
49.322 + _cost[_arc_idf[a]] = map[a];
49.323 + _cost[_arc_idb[a]] = -map[a];
49.324 + }
49.325 + return *this;
49.326 + }
49.327 +
49.328 + /// \brief Set the supply values of the nodes.
49.329 + ///
49.330 + /// This function sets the supply values of the nodes.
49.331 + /// If neither this function nor \ref stSupply() is used before
49.332 + /// calling \ref run(), the supply of each node will be set to zero.
49.333 + ///
49.334 + /// \param map A node map storing the supply values.
49.335 + /// Its \c Value type must be convertible to the \c Value type
49.336 + /// of the algorithm.
49.337 + ///
49.338 + /// \return <tt>(*this)</tt>
49.339 + template<typename SupplyMap>
49.340 + CycleCanceling& supplyMap(const SupplyMap& map) {
49.341 + for (NodeIt n(_graph); n != INVALID; ++n) {
49.342 + _supply[_node_id[n]] = map[n];
49.343 + }
49.344 + return *this;
49.345 + }
49.346 +
49.347 + /// \brief Set single source and target nodes and a supply value.
49.348 + ///
49.349 + /// This function sets a single source node and a single target node
49.350 + /// and the required flow value.
49.351 + /// If neither this function nor \ref supplyMap() is used before
49.352 + /// calling \ref run(), the supply of each node will be set to zero.
49.353 + ///
49.354 + /// Using this function has the same effect as using \ref supplyMap()
49.355 + /// with such a map in which \c k is assigned to \c s, \c -k is
49.356 + /// assigned to \c t and all other nodes have zero supply value.
49.357 + ///
49.358 + /// \param s The source node.
49.359 + /// \param t The target node.
49.360 + /// \param k The required amount of flow from node \c s to node \c t
49.361 + /// (i.e. the supply of \c s and the demand of \c t).
49.362 + ///
49.363 + /// \return <tt>(*this)</tt>
49.364 + CycleCanceling& stSupply(const Node& s, const Node& t, Value k) {
49.365 + for (int i = 0; i != _res_node_num; ++i) {
49.366 + _supply[i] = 0;
49.367 + }
49.368 + _supply[_node_id[s]] = k;
49.369 + _supply[_node_id[t]] = -k;
49.370 + return *this;
49.371 + }
49.372 +
49.373 + /// @}
49.374 +
49.375 + /// \name Execution control
49.376 + /// The algorithm can be executed using \ref run().
49.377 +
49.378 + /// @{
49.379 +
49.380 + /// \brief Run the algorithm.
49.381 + ///
49.382 + /// This function runs the algorithm.
49.383 + /// The paramters can be specified using functions \ref lowerMap(),
49.384 + /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply().
49.385 + /// For example,
49.386 + /// \code
49.387 + /// CycleCanceling<ListDigraph> cc(graph);
49.388 + /// cc.lowerMap(lower).upperMap(upper).costMap(cost)
49.389 + /// .supplyMap(sup).run();
49.390 + /// \endcode
49.391 + ///
49.392 + /// This function can be called more than once. All the given parameters
49.393 + /// are kept for the next call, unless \ref resetParams() or \ref reset()
49.394 + /// is used, thus only the modified parameters have to be set again.
49.395 + /// If the underlying digraph was also modified after the construction
49.396 + /// of the class (or the last \ref reset() call), then the \ref reset()
49.397 + /// function must be called.
49.398 + ///
49.399 + /// \param method The cycle-canceling method that will be used.
49.400 + /// For more information, see \ref Method.
49.401 + ///
49.402 + /// \return \c INFEASIBLE if no feasible flow exists,
49.403 + /// \n \c OPTIMAL if the problem has optimal solution
49.404 + /// (i.e. it is feasible and bounded), and the algorithm has found
49.405 + /// optimal flow and node potentials (primal and dual solutions),
49.406 + /// \n \c UNBOUNDED if the digraph contains an arc of negative cost
49.407 + /// and infinite upper bound. It means that the objective function
49.408 + /// is unbounded on that arc, however, note that it could actually be
49.409 + /// bounded over the feasible flows, but this algroithm cannot handle
49.410 + /// these cases.
49.411 + ///
49.412 + /// \see ProblemType, Method
49.413 + /// \see resetParams(), reset()
49.414 + ProblemType run(Method method = CANCEL_AND_TIGHTEN) {
49.415 + ProblemType pt = init();
49.416 + if (pt != OPTIMAL) return pt;
49.417 + start(method);
49.418 + return OPTIMAL;
49.419 + }
49.420 +
49.421 + /// \brief Reset all the parameters that have been given before.
49.422 + ///
49.423 + /// This function resets all the paramaters that have been given
49.424 + /// before using functions \ref lowerMap(), \ref upperMap(),
49.425 + /// \ref costMap(), \ref supplyMap(), \ref stSupply().
49.426 + ///
49.427 + /// It is useful for multiple \ref run() calls. Basically, all the given
49.428 + /// parameters are kept for the next \ref run() call, unless
49.429 + /// \ref resetParams() or \ref reset() is used.
49.430 + /// If the underlying digraph was also modified after the construction
49.431 + /// of the class or the last \ref reset() call, then the \ref reset()
49.432 + /// function must be used, otherwise \ref resetParams() is sufficient.
49.433 + ///
49.434 + /// For example,
49.435 + /// \code
49.436 + /// CycleCanceling<ListDigraph> cs(graph);
49.437 + ///
49.438 + /// // First run
49.439 + /// cc.lowerMap(lower).upperMap(upper).costMap(cost)
49.440 + /// .supplyMap(sup).run();
49.441 + ///
49.442 + /// // Run again with modified cost map (resetParams() is not called,
49.443 + /// // so only the cost map have to be set again)
49.444 + /// cost[e] += 100;
49.445 + /// cc.costMap(cost).run();
49.446 + ///
49.447 + /// // Run again from scratch using resetParams()
49.448 + /// // (the lower bounds will be set to zero on all arcs)
49.449 + /// cc.resetParams();
49.450 + /// cc.upperMap(capacity).costMap(cost)
49.451 + /// .supplyMap(sup).run();
49.452 + /// \endcode
49.453 + ///
49.454 + /// \return <tt>(*this)</tt>
49.455 + ///
49.456 + /// \see reset(), run()
49.457 + CycleCanceling& resetParams() {
49.458 + for (int i = 0; i != _res_node_num; ++i) {
49.459 + _supply[i] = 0;
49.460 + }
49.461 + int limit = _first_out[_root];
49.462 + for (int j = 0; j != limit; ++j) {
49.463 + _lower[j] = 0;
49.464 + _upper[j] = INF;
49.465 + _cost[j] = _forward[j] ? 1 : -1;
49.466 + }
49.467 + for (int j = limit; j != _res_arc_num; ++j) {
49.468 + _lower[j] = 0;
49.469 + _upper[j] = INF;
49.470 + _cost[j] = 0;
49.471 + _cost[_reverse[j]] = 0;
49.472 + }
49.473 + _have_lower = false;
49.474 + return *this;
49.475 + }
49.476 +
49.477 + /// \brief Reset the internal data structures and all the parameters
49.478 + /// that have been given before.
49.479 + ///
49.480 + /// This function resets the internal data structures and all the
49.481 + /// paramaters that have been given before using functions \ref lowerMap(),
49.482 + /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply().
49.483 + ///
49.484 + /// It is useful for multiple \ref run() calls. Basically, all the given
49.485 + /// parameters are kept for the next \ref run() call, unless
49.486 + /// \ref resetParams() or \ref reset() is used.
49.487 + /// If the underlying digraph was also modified after the construction
49.488 + /// of the class or the last \ref reset() call, then the \ref reset()
49.489 + /// function must be used, otherwise \ref resetParams() is sufficient.
49.490 + ///
49.491 + /// See \ref resetParams() for examples.
49.492 + ///
49.493 + /// \return <tt>(*this)</tt>
49.494 + ///
49.495 + /// \see resetParams(), run()
49.496 + CycleCanceling& reset() {
49.497 + // Resize vectors
49.498 + _node_num = countNodes(_graph);
49.499 + _arc_num = countArcs(_graph);
49.500 + _res_node_num = _node_num + 1;
49.501 + _res_arc_num = 2 * (_arc_num + _node_num);
49.502 + _root = _node_num;
49.503 +
49.504 + _first_out.resize(_res_node_num + 1);
49.505 + _forward.resize(_res_arc_num);
49.506 + _source.resize(_res_arc_num);
49.507 + _target.resize(_res_arc_num);
49.508 + _reverse.resize(_res_arc_num);
49.509 +
49.510 + _lower.resize(_res_arc_num);
49.511 + _upper.resize(_res_arc_num);
49.512 + _cost.resize(_res_arc_num);
49.513 + _supply.resize(_res_node_num);
49.514 +
49.515 + _res_cap.resize(_res_arc_num);
49.516 + _pi.resize(_res_node_num);
49.517 +
49.518 + _arc_vec.reserve(_res_arc_num);
49.519 + _cost_vec.reserve(_res_arc_num);
49.520 + _id_vec.reserve(_res_arc_num);
49.521 +
49.522 + // Copy the graph
49.523 + int i = 0, j = 0, k = 2 * _arc_num + _node_num;
49.524 + for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
49.525 + _node_id[n] = i;
49.526 + }
49.527 + i = 0;
49.528 + for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
49.529 + _first_out[i] = j;
49.530 + for (OutArcIt a(_graph, n); a != INVALID; ++a, ++j) {
49.531 + _arc_idf[a] = j;
49.532 + _forward[j] = true;
49.533 + _source[j] = i;
49.534 + _target[j] = _node_id[_graph.runningNode(a)];
49.535 + }
49.536 + for (InArcIt a(_graph, n); a != INVALID; ++a, ++j) {
49.537 + _arc_idb[a] = j;
49.538 + _forward[j] = false;
49.539 + _source[j] = i;
49.540 + _target[j] = _node_id[_graph.runningNode(a)];
49.541 + }
49.542 + _forward[j] = false;
49.543 + _source[j] = i;
49.544 + _target[j] = _root;
49.545 + _reverse[j] = k;
49.546 + _forward[k] = true;
49.547 + _source[k] = _root;
49.548 + _target[k] = i;
49.549 + _reverse[k] = j;
49.550 + ++j; ++k;
49.551 + }
49.552 + _first_out[i] = j;
49.553 + _first_out[_res_node_num] = k;
49.554 + for (ArcIt a(_graph); a != INVALID; ++a) {
49.555 + int fi = _arc_idf[a];
49.556 + int bi = _arc_idb[a];
49.557 + _reverse[fi] = bi;
49.558 + _reverse[bi] = fi;
49.559 + }
49.560 +
49.561 + // Reset parameters
49.562 + resetParams();
49.563 + return *this;
49.564 + }
49.565 +
49.566 + /// @}
49.567 +
49.568 + /// \name Query Functions
49.569 + /// The results of the algorithm can be obtained using these
49.570 + /// functions.\n
49.571 + /// The \ref run() function must be called before using them.
49.572 +
49.573 + /// @{
49.574 +
49.575 + /// \brief Return the total cost of the found flow.
49.576 + ///
49.577 + /// This function returns the total cost of the found flow.
49.578 + /// Its complexity is O(e).
49.579 + ///
49.580 + /// \note The return type of the function can be specified as a
49.581 + /// template parameter. For example,
49.582 + /// \code
49.583 + /// cc.totalCost<double>();
49.584 + /// \endcode
49.585 + /// It is useful if the total cost cannot be stored in the \c Cost
49.586 + /// type of the algorithm, which is the default return type of the
49.587 + /// function.
49.588 + ///
49.589 + /// \pre \ref run() must be called before using this function.
49.590 + template <typename Number>
49.591 + Number totalCost() const {
49.592 + Number c = 0;
49.593 + for (ArcIt a(_graph); a != INVALID; ++a) {
49.594 + int i = _arc_idb[a];
49.595 + c += static_cast<Number>(_res_cap[i]) *
49.596 + (-static_cast<Number>(_cost[i]));
49.597 + }
49.598 + return c;
49.599 + }
49.600 +
49.601 +#ifndef DOXYGEN
49.602 + Cost totalCost() const {
49.603 + return totalCost<Cost>();
49.604 + }
49.605 +#endif
49.606 +
49.607 + /// \brief Return the flow on the given arc.
49.608 + ///
49.609 + /// This function returns the flow on the given arc.
49.610 + ///
49.611 + /// \pre \ref run() must be called before using this function.
49.612 + Value flow(const Arc& a) const {
49.613 + return _res_cap[_arc_idb[a]];
49.614 + }
49.615 +
49.616 + /// \brief Return the flow map (the primal solution).
49.617 + ///
49.618 + /// This function copies the flow value on each arc into the given
49.619 + /// map. The \c Value type of the algorithm must be convertible to
49.620 + /// the \c Value type of the map.
49.621 + ///
49.622 + /// \pre \ref run() must be called before using this function.
49.623 + template <typename FlowMap>
49.624 + void flowMap(FlowMap &map) const {
49.625 + for (ArcIt a(_graph); a != INVALID; ++a) {
49.626 + map.set(a, _res_cap[_arc_idb[a]]);
49.627 + }
49.628 + }
49.629 +
49.630 + /// \brief Return the potential (dual value) of the given node.
49.631 + ///
49.632 + /// This function returns the potential (dual value) of the
49.633 + /// given node.
49.634 + ///
49.635 + /// \pre \ref run() must be called before using this function.
49.636 + Cost potential(const Node& n) const {
49.637 + return static_cast<Cost>(_pi[_node_id[n]]);
49.638 + }
49.639 +
49.640 + /// \brief Return the potential map (the dual solution).
49.641 + ///
49.642 + /// This function copies the potential (dual value) of each node
49.643 + /// into the given map.
49.644 + /// The \c Cost type of the algorithm must be convertible to the
49.645 + /// \c Value type of the map.
49.646 + ///
49.647 + /// \pre \ref run() must be called before using this function.
49.648 + template <typename PotentialMap>
49.649 + void potentialMap(PotentialMap &map) const {
49.650 + for (NodeIt n(_graph); n != INVALID; ++n) {
49.651 + map.set(n, static_cast<Cost>(_pi[_node_id[n]]));
49.652 + }
49.653 + }
49.654 +
49.655 + /// @}
49.656 +
49.657 + private:
49.658 +
49.659 + // Initialize the algorithm
49.660 + ProblemType init() {
49.661 + if (_res_node_num <= 1) return INFEASIBLE;
49.662 +
49.663 + // Check the sum of supply values
49.664 + _sum_supply = 0;
49.665 + for (int i = 0; i != _root; ++i) {
49.666 + _sum_supply += _supply[i];
49.667 + }
49.668 + if (_sum_supply > 0) return INFEASIBLE;
49.669 +
49.670 +
49.671 + // Initialize vectors
49.672 + for (int i = 0; i != _res_node_num; ++i) {
49.673 + _pi[i] = 0;
49.674 + }
49.675 + ValueVector excess(_supply);
49.676 +
49.677 + // Remove infinite upper bounds and check negative arcs
49.678 + const Value MAX = std::numeric_limits<Value>::max();
49.679 + int last_out;
49.680 + if (_have_lower) {
49.681 + for (int i = 0; i != _root; ++i) {
49.682 + last_out = _first_out[i+1];
49.683 + for (int j = _first_out[i]; j != last_out; ++j) {
49.684 + if (_forward[j]) {
49.685 + Value c = _cost[j] < 0 ? _upper[j] : _lower[j];
49.686 + if (c >= MAX) return UNBOUNDED;
49.687 + excess[i] -= c;
49.688 + excess[_target[j]] += c;
49.689 + }
49.690 + }
49.691 + }
49.692 + } else {
49.693 + for (int i = 0; i != _root; ++i) {
49.694 + last_out = _first_out[i+1];
49.695 + for (int j = _first_out[i]; j != last_out; ++j) {
49.696 + if (_forward[j] && _cost[j] < 0) {
49.697 + Value c = _upper[j];
49.698 + if (c >= MAX) return UNBOUNDED;
49.699 + excess[i] -= c;
49.700 + excess[_target[j]] += c;
49.701 + }
49.702 + }
49.703 + }
49.704 + }
49.705 + Value ex, max_cap = 0;
49.706 + for (int i = 0; i != _res_node_num; ++i) {
49.707 + ex = excess[i];
49.708 + if (ex < 0) max_cap -= ex;
49.709 + }
49.710 + for (int j = 0; j != _res_arc_num; ++j) {
49.711 + if (_upper[j] >= MAX) _upper[j] = max_cap;
49.712 + }
49.713 +
49.714 + // Initialize maps for Circulation and remove non-zero lower bounds
49.715 + ConstMap<Arc, Value> low(0);
49.716 + typedef typename Digraph::template ArcMap<Value> ValueArcMap;
49.717 + typedef typename Digraph::template NodeMap<Value> ValueNodeMap;
49.718 + ValueArcMap cap(_graph), flow(_graph);
49.719 + ValueNodeMap sup(_graph);
49.720 + for (NodeIt n(_graph); n != INVALID; ++n) {
49.721 + sup[n] = _supply[_node_id[n]];
49.722 + }
49.723 + if (_have_lower) {
49.724 + for (ArcIt a(_graph); a != INVALID; ++a) {
49.725 + int j = _arc_idf[a];
49.726 + Value c = _lower[j];
49.727 + cap[a] = _upper[j] - c;
49.728 + sup[_graph.source(a)] -= c;
49.729 + sup[_graph.target(a)] += c;
49.730 + }
49.731 + } else {
49.732 + for (ArcIt a(_graph); a != INVALID; ++a) {
49.733 + cap[a] = _upper[_arc_idf[a]];
49.734 + }
49.735 + }
49.736 +
49.737 + // Find a feasible flow using Circulation
49.738 + Circulation<Digraph, ConstMap<Arc, Value>, ValueArcMap, ValueNodeMap>
49.739 + circ(_graph, low, cap, sup);
49.740 + if (!circ.flowMap(flow).run()) return INFEASIBLE;
49.741 +
49.742 + // Set residual capacities and handle GEQ supply type
49.743 + if (_sum_supply < 0) {
49.744 + for (ArcIt a(_graph); a != INVALID; ++a) {
49.745 + Value fa = flow[a];
49.746 + _res_cap[_arc_idf[a]] = cap[a] - fa;
49.747 + _res_cap[_arc_idb[a]] = fa;
49.748 + sup[_graph.source(a)] -= fa;
49.749 + sup[_graph.target(a)] += fa;
49.750 + }
49.751 + for (NodeIt n(_graph); n != INVALID; ++n) {
49.752 + excess[_node_id[n]] = sup[n];
49.753 + }
49.754 + for (int a = _first_out[_root]; a != _res_arc_num; ++a) {
49.755 + int u = _target[a];
49.756 + int ra = _reverse[a];
49.757 + _res_cap[a] = -_sum_supply + 1;
49.758 + _res_cap[ra] = -excess[u];
49.759 + _cost[a] = 0;
49.760 + _cost[ra] = 0;
49.761 + }
49.762 + } else {
49.763 + for (ArcIt a(_graph); a != INVALID; ++a) {
49.764 + Value fa = flow[a];
49.765 + _res_cap[_arc_idf[a]] = cap[a] - fa;
49.766 + _res_cap[_arc_idb[a]] = fa;
49.767 + }
49.768 + for (int a = _first_out[_root]; a != _res_arc_num; ++a) {
49.769 + int ra = _reverse[a];
49.770 + _res_cap[a] = 1;
49.771 + _res_cap[ra] = 0;
49.772 + _cost[a] = 0;
49.773 + _cost[ra] = 0;
49.774 + }
49.775 + }
49.776 +
49.777 + return OPTIMAL;
49.778 + }
49.779 +
49.780 + // Build a StaticDigraph structure containing the current
49.781 + // residual network
49.782 + void buildResidualNetwork() {
49.783 + _arc_vec.clear();
49.784 + _cost_vec.clear();
49.785 + _id_vec.clear();
49.786 + for (int j = 0; j != _res_arc_num; ++j) {
49.787 + if (_res_cap[j] > 0) {
49.788 + _arc_vec.push_back(IntPair(_source[j], _target[j]));
49.789 + _cost_vec.push_back(_cost[j]);
49.790 + _id_vec.push_back(j);
49.791 + }
49.792 + }
49.793 + _sgr.build(_res_node_num, _arc_vec.begin(), _arc_vec.end());
49.794 + }
49.795 +
49.796 + // Execute the algorithm and transform the results
49.797 + void start(Method method) {
49.798 + // Execute the algorithm
49.799 + switch (method) {
49.800 + case SIMPLE_CYCLE_CANCELING:
49.801 + startSimpleCycleCanceling();
49.802 + break;
49.803 + case MINIMUM_MEAN_CYCLE_CANCELING:
49.804 + startMinMeanCycleCanceling();
49.805 + break;
49.806 + case CANCEL_AND_TIGHTEN:
49.807 + startCancelAndTighten();
49.808 + break;
49.809 + }
49.810 +
49.811 + // Compute node potentials
49.812 + if (method != SIMPLE_CYCLE_CANCELING) {
49.813 + buildResidualNetwork();
49.814 + typename BellmanFord<StaticDigraph, CostArcMap>
49.815 + ::template SetDistMap<CostNodeMap>::Create bf(_sgr, _cost_map);
49.816 + bf.distMap(_pi_map);
49.817 + bf.init(0);
49.818 + bf.start();
49.819 + }
49.820 +
49.821 + // Handle non-zero lower bounds
49.822 + if (_have_lower) {
49.823 + int limit = _first_out[_root];
49.824 + for (int j = 0; j != limit; ++j) {
49.825 + if (!_forward[j]) _res_cap[j] += _lower[j];
49.826 + }
49.827 + }
49.828 + }
49.829 +
49.830 + // Execute the "Simple Cycle Canceling" method
49.831 + void startSimpleCycleCanceling() {
49.832 + // Constants for computing the iteration limits
49.833 + const int BF_FIRST_LIMIT = 2;
49.834 + const double BF_LIMIT_FACTOR = 1.5;
49.835 +
49.836 + typedef StaticVectorMap<StaticDigraph::Arc, Value> FilterMap;
49.837 + typedef FilterArcs<StaticDigraph, FilterMap> ResDigraph;
49.838 + typedef StaticVectorMap<StaticDigraph::Node, StaticDigraph::Arc> PredMap;
49.839 + typedef typename BellmanFord<ResDigraph, CostArcMap>
49.840 + ::template SetDistMap<CostNodeMap>
49.841 + ::template SetPredMap<PredMap>::Create BF;
49.842 +
49.843 + // Build the residual network
49.844 + _arc_vec.clear();
49.845 + _cost_vec.clear();
49.846 + for (int j = 0; j != _res_arc_num; ++j) {
49.847 + _arc_vec.push_back(IntPair(_source[j], _target[j]));
49.848 + _cost_vec.push_back(_cost[j]);
49.849 + }
49.850 + _sgr.build(_res_node_num, _arc_vec.begin(), _arc_vec.end());
49.851 +
49.852 + FilterMap filter_map(_res_cap);
49.853 + ResDigraph rgr(_sgr, filter_map);
49.854 + std::vector<int> cycle;
49.855 + std::vector<StaticDigraph::Arc> pred(_res_arc_num);
49.856 + PredMap pred_map(pred);
49.857 + BF bf(rgr, _cost_map);
49.858 + bf.distMap(_pi_map).predMap(pred_map);
49.859 +
49.860 + int length_bound = BF_FIRST_LIMIT;
49.861 + bool optimal = false;
49.862 + while (!optimal) {
49.863 + bf.init(0);
49.864 + int iter_num = 0;
49.865 + bool cycle_found = false;
49.866 + while (!cycle_found) {
49.867 + // Perform some iterations of the Bellman-Ford algorithm
49.868 + int curr_iter_num = iter_num + length_bound <= _node_num ?
49.869 + length_bound : _node_num - iter_num;
49.870 + iter_num += curr_iter_num;
49.871 + int real_iter_num = curr_iter_num;
49.872 + for (int i = 0; i < curr_iter_num; ++i) {
49.873 + if (bf.processNextWeakRound()) {
49.874 + real_iter_num = i;
49.875 + break;
49.876 + }
49.877 + }
49.878 + if (real_iter_num < curr_iter_num) {
49.879 + // Optimal flow is found
49.880 + optimal = true;
49.881 + break;
49.882 + } else {
49.883 + // Search for node disjoint negative cycles
49.884 + std::vector<int> state(_res_node_num, 0);
49.885 + int id = 0;
49.886 + for (int u = 0; u != _res_node_num; ++u) {
49.887 + if (state[u] != 0) continue;
49.888 + ++id;
49.889 + int v = u;
49.890 + for (; v != -1 && state[v] == 0; v = pred[v] == INVALID ?
49.891 + -1 : rgr.id(rgr.source(pred[v]))) {
49.892 + state[v] = id;
49.893 + }
49.894 + if (v != -1 && state[v] == id) {
49.895 + // A negative cycle is found
49.896 + cycle_found = true;
49.897 + cycle.clear();
49.898 + StaticDigraph::Arc a = pred[v];
49.899 + Value d, delta = _res_cap[rgr.id(a)];
49.900 + cycle.push_back(rgr.id(a));
49.901 + while (rgr.id(rgr.source(a)) != v) {
49.902 + a = pred_map[rgr.source(a)];
49.903 + d = _res_cap[rgr.id(a)];
49.904 + if (d < delta) delta = d;
49.905 + cycle.push_back(rgr.id(a));
49.906 + }
49.907 +
49.908 + // Augment along the cycle
49.909 + for (int i = 0; i < int(cycle.size()); ++i) {
49.910 + int j = cycle[i];
49.911 + _res_cap[j] -= delta;
49.912 + _res_cap[_reverse[j]] += delta;
49.913 + }
49.914 + }
49.915 + }
49.916 + }
49.917 +
49.918 + // Increase iteration limit if no cycle is found
49.919 + if (!cycle_found) {
49.920 + length_bound = static_cast<int>(length_bound * BF_LIMIT_FACTOR);
49.921 + }
49.922 + }
49.923 + }
49.924 + }
49.925 +
49.926 + // Execute the "Minimum Mean Cycle Canceling" method
49.927 + void startMinMeanCycleCanceling() {
49.928 + typedef SimplePath<StaticDigraph> SPath;
49.929 + typedef typename SPath::ArcIt SPathArcIt;
49.930 + typedef typename HowardMmc<StaticDigraph, CostArcMap>
49.931 + ::template SetPath<SPath>::Create MMC;
49.932 +
49.933 + SPath cycle;
49.934 + MMC mmc(_sgr, _cost_map);
49.935 + mmc.cycle(cycle);
49.936 + buildResidualNetwork();
49.937 + while (mmc.findCycleMean() && mmc.cycleCost() < 0) {
49.938 + // Find the cycle
49.939 + mmc.findCycle();
49.940 +
49.941 + // Compute delta value
49.942 + Value delta = INF;
49.943 + for (SPathArcIt a(cycle); a != INVALID; ++a) {
49.944 + Value d = _res_cap[_id_vec[_sgr.id(a)]];
49.945 + if (d < delta) delta = d;
49.946 + }
49.947 +
49.948 + // Augment along the cycle
49.949 + for (SPathArcIt a(cycle); a != INVALID; ++a) {
49.950 + int j = _id_vec[_sgr.id(a)];
49.951 + _res_cap[j] -= delta;
49.952 + _res_cap[_reverse[j]] += delta;
49.953 + }
49.954 +
49.955 + // Rebuild the residual network
49.956 + buildResidualNetwork();
49.957 + }
49.958 + }
49.959 +
49.960 + // Execute the "Cancel And Tighten" method
49.961 + void startCancelAndTighten() {
49.962 + // Constants for the min mean cycle computations
49.963 + const double LIMIT_FACTOR = 1.0;
49.964 + const int MIN_LIMIT = 5;
49.965 +
49.966 + // Contruct auxiliary data vectors
49.967 + DoubleVector pi(_res_node_num, 0.0);
49.968 + IntVector level(_res_node_num);
49.969 + BoolVector reached(_res_node_num);
49.970 + BoolVector processed(_res_node_num);
49.971 + IntVector pred_node(_res_node_num);
49.972 + IntVector pred_arc(_res_node_num);
49.973 + std::vector<int> stack(_res_node_num);
49.974 + std::vector<int> proc_vector(_res_node_num);
49.975 +
49.976 + // Initialize epsilon
49.977 + double epsilon = 0;
49.978 + for (int a = 0; a != _res_arc_num; ++a) {
49.979 + if (_res_cap[a] > 0 && -_cost[a] > epsilon)
49.980 + epsilon = -_cost[a];
49.981 + }
49.982 +
49.983 + // Start phases
49.984 + Tolerance<double> tol;
49.985 + tol.epsilon(1e-6);
49.986 + int limit = int(LIMIT_FACTOR * std::sqrt(double(_res_node_num)));
49.987 + if (limit < MIN_LIMIT) limit = MIN_LIMIT;
49.988 + int iter = limit;
49.989 + while (epsilon * _res_node_num >= 1) {
49.990 + // Find and cancel cycles in the admissible network using DFS
49.991 + for (int u = 0; u != _res_node_num; ++u) {
49.992 + reached[u] = false;
49.993 + processed[u] = false;
49.994 + }
49.995 + int stack_head = -1;
49.996 + int proc_head = -1;
49.997 + for (int start = 0; start != _res_node_num; ++start) {
49.998 + if (reached[start]) continue;
49.999 +
49.1000 + // New start node
49.1001 + reached[start] = true;
49.1002 + pred_arc[start] = -1;
49.1003 + pred_node[start] = -1;
49.1004 +
49.1005 + // Find the first admissible outgoing arc
49.1006 + double p = pi[start];
49.1007 + int a = _first_out[start];
49.1008 + int last_out = _first_out[start+1];
49.1009 + for (; a != last_out && (_res_cap[a] == 0 ||
49.1010 + !tol.negative(_cost[a] + p - pi[_target[a]])); ++a) ;
49.1011 + if (a == last_out) {
49.1012 + processed[start] = true;
49.1013 + proc_vector[++proc_head] = start;
49.1014 + continue;
49.1015 + }
49.1016 + stack[++stack_head] = a;
49.1017 +
49.1018 + while (stack_head >= 0) {
49.1019 + int sa = stack[stack_head];
49.1020 + int u = _source[sa];
49.1021 + int v = _target[sa];
49.1022 +
49.1023 + if (!reached[v]) {
49.1024 + // A new node is reached
49.1025 + reached[v] = true;
49.1026 + pred_node[v] = u;
49.1027 + pred_arc[v] = sa;
49.1028 + p = pi[v];
49.1029 + a = _first_out[v];
49.1030 + last_out = _first_out[v+1];
49.1031 + for (; a != last_out && (_res_cap[a] == 0 ||
49.1032 + !tol.negative(_cost[a] + p - pi[_target[a]])); ++a) ;
49.1033 + stack[++stack_head] = a == last_out ? -1 : a;
49.1034 + } else {
49.1035 + if (!processed[v]) {
49.1036 + // A cycle is found
49.1037 + int n, w = u;
49.1038 + Value d, delta = _res_cap[sa];
49.1039 + for (n = u; n != v; n = pred_node[n]) {
49.1040 + d = _res_cap[pred_arc[n]];
49.1041 + if (d <= delta) {
49.1042 + delta = d;
49.1043 + w = pred_node[n];
49.1044 + }
49.1045 + }
49.1046 +
49.1047 + // Augment along the cycle
49.1048 + _res_cap[sa] -= delta;
49.1049 + _res_cap[_reverse[sa]] += delta;
49.1050 + for (n = u; n != v; n = pred_node[n]) {
49.1051 + int pa = pred_arc[n];
49.1052 + _res_cap[pa] -= delta;
49.1053 + _res_cap[_reverse[pa]] += delta;
49.1054 + }
49.1055 + for (n = u; stack_head > 0 && n != w; n = pred_node[n]) {
49.1056 + --stack_head;
49.1057 + reached[n] = false;
49.1058 + }
49.1059 + u = w;
49.1060 + }
49.1061 + v = u;
49.1062 +
49.1063 + // Find the next admissible outgoing arc
49.1064 + p = pi[v];
49.1065 + a = stack[stack_head] + 1;
49.1066 + last_out = _first_out[v+1];
49.1067 + for (; a != last_out && (_res_cap[a] == 0 ||
49.1068 + !tol.negative(_cost[a] + p - pi[_target[a]])); ++a) ;
49.1069 + stack[stack_head] = a == last_out ? -1 : a;
49.1070 + }
49.1071 +
49.1072 + while (stack_head >= 0 && stack[stack_head] == -1) {
49.1073 + processed[v] = true;
49.1074 + proc_vector[++proc_head] = v;
49.1075 + if (--stack_head >= 0) {
49.1076 + // Find the next admissible outgoing arc
49.1077 + v = _source[stack[stack_head]];
49.1078 + p = pi[v];
49.1079 + a = stack[stack_head] + 1;
49.1080 + last_out = _first_out[v+1];
49.1081 + for (; a != last_out && (_res_cap[a] == 0 ||
49.1082 + !tol.negative(_cost[a] + p - pi[_target[a]])); ++a) ;
49.1083 + stack[stack_head] = a == last_out ? -1 : a;
49.1084 + }
49.1085 + }
49.1086 + }
49.1087 + }
49.1088 +
49.1089 + // Tighten potentials and epsilon
49.1090 + if (--iter > 0) {
49.1091 + for (int u = 0; u != _res_node_num; ++u) {
49.1092 + level[u] = 0;
49.1093 + }
49.1094 + for (int i = proc_head; i > 0; --i) {
49.1095 + int u = proc_vector[i];
49.1096 + double p = pi[u];
49.1097 + int l = level[u] + 1;
49.1098 + int last_out = _first_out[u+1];
49.1099 + for (int a = _first_out[u]; a != last_out; ++a) {
49.1100 + int v = _target[a];
49.1101 + if (_res_cap[a] > 0 && tol.negative(_cost[a] + p - pi[v]) &&
49.1102 + l > level[v]) level[v] = l;
49.1103 + }
49.1104 + }
49.1105 +
49.1106 + // Modify potentials
49.1107 + double q = std::numeric_limits<double>::max();
49.1108 + for (int u = 0; u != _res_node_num; ++u) {
49.1109 + int lu = level[u];
49.1110 + double p, pu = pi[u];
49.1111 + int last_out = _first_out[u+1];
49.1112 + for (int a = _first_out[u]; a != last_out; ++a) {
49.1113 + if (_res_cap[a] == 0) continue;
49.1114 + int v = _target[a];
49.1115 + int ld = lu - level[v];
49.1116 + if (ld > 0) {
49.1117 + p = (_cost[a] + pu - pi[v] + epsilon) / (ld + 1);
49.1118 + if (p < q) q = p;
49.1119 + }
49.1120 + }
49.1121 + }
49.1122 + for (int u = 0; u != _res_node_num; ++u) {
49.1123 + pi[u] -= q * level[u];
49.1124 + }
49.1125 +
49.1126 + // Modify epsilon
49.1127 + epsilon = 0;
49.1128 + for (int u = 0; u != _res_node_num; ++u) {
49.1129 + double curr, pu = pi[u];
49.1130 + int last_out = _first_out[u+1];
49.1131 + for (int a = _first_out[u]; a != last_out; ++a) {
49.1132 + if (_res_cap[a] == 0) continue;
49.1133 + curr = _cost[a] + pu - pi[_target[a]];
49.1134 + if (-curr > epsilon) epsilon = -curr;
49.1135 + }
49.1136 + }
49.1137 + } else {
49.1138 + typedef HowardMmc<StaticDigraph, CostArcMap> MMC;
49.1139 + typedef typename BellmanFord<StaticDigraph, CostArcMap>
49.1140 + ::template SetDistMap<CostNodeMap>::Create BF;
49.1141 +
49.1142 + // Set epsilon to the minimum cycle mean
49.1143 + buildResidualNetwork();
49.1144 + MMC mmc(_sgr, _cost_map);
49.1145 + mmc.findCycleMean();
49.1146 + epsilon = -mmc.cycleMean();
49.1147 + Cost cycle_cost = mmc.cycleCost();
49.1148 + int cycle_size = mmc.cycleSize();
49.1149 +
49.1150 + // Compute feasible potentials for the current epsilon
49.1151 + for (int i = 0; i != int(_cost_vec.size()); ++i) {
49.1152 + _cost_vec[i] = cycle_size * _cost_vec[i] - cycle_cost;
49.1153 + }
49.1154 + BF bf(_sgr, _cost_map);
49.1155 + bf.distMap(_pi_map);
49.1156 + bf.init(0);
49.1157 + bf.start();
49.1158 + for (int u = 0; u != _res_node_num; ++u) {
49.1159 + pi[u] = static_cast<double>(_pi[u]) / cycle_size;
49.1160 + }
49.1161 +
49.1162 + iter = limit;
49.1163 + }
49.1164 + }
49.1165 + }
49.1166 +
49.1167 + }; //class CycleCanceling
49.1168 +
49.1169 + ///@}
49.1170 +
49.1171 +} //namespace lemon
49.1172 +
49.1173 +#endif //LEMON_CYCLE_CANCELING_H
50.1 --- a/lemon/dfs.h Tue Dec 20 17:44:38 2011 +0100
50.2 +++ b/lemon/dfs.h Tue Dec 20 18:15:14 2011 +0100
50.3 @@ -2,7 +2,7 @@
50.4 *
50.5 * This file is a part of LEMON, a generic C++ optimization library.
50.6 *
50.7 - * Copyright (C) 2003-2009
50.8 + * Copyright (C) 2003-2010
50.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
50.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
50.11 *
50.12 @@ -47,7 +47,7 @@
50.13 ///
50.14 ///The type of the map that stores the predecessor
50.15 ///arcs of the %DFS paths.
50.16 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
50.17 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
50.18 typedef typename Digraph::template NodeMap<typename Digraph::Arc> PredMap;
50.19 ///Instantiates a \c PredMap.
50.20
50.21 @@ -62,7 +62,8 @@
50.22 ///The type of the map that indicates which nodes are processed.
50.23
50.24 ///The type of the map that indicates which nodes are processed.
50.25 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
50.26 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
50.27 + ///By default, it is a NullMap.
50.28 typedef NullMap<typename Digraph::Node,bool> ProcessedMap;
50.29 ///Instantiates a \c ProcessedMap.
50.30
50.31 @@ -81,7 +82,8 @@
50.32 ///The type of the map that indicates which nodes are reached.
50.33
50.34 ///The type of the map that indicates which nodes are reached.
50.35 - ///It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
50.36 + ///It must conform to
50.37 + ///the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
50.38 typedef typename Digraph::template NodeMap<bool> ReachedMap;
50.39 ///Instantiates a \c ReachedMap.
50.40
50.41 @@ -96,7 +98,7 @@
50.42 ///The type of the map that stores the distances of the nodes.
50.43
50.44 ///The type of the map that stores the distances of the nodes.
50.45 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
50.46 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
50.47 typedef typename Digraph::template NodeMap<int> DistMap;
50.48 ///Instantiates a \c DistMap.
50.49
50.50 @@ -120,6 +122,11 @@
50.51 ///
50.52 ///\tparam GR The type of the digraph the algorithm runs on.
50.53 ///The default type is \ref ListDigraph.
50.54 + ///\tparam TR The traits class that defines various types used by the
50.55 + ///algorithm. By default, it is \ref DfsDefaultTraits
50.56 + ///"DfsDefaultTraits<GR>".
50.57 + ///In most cases, this parameter should not be set directly,
50.58 + ///consider to use the named template parameters instead.
50.59 #ifdef DOXYGEN
50.60 template <typename GR,
50.61 typename TR>
50.62 @@ -224,7 +231,7 @@
50.63 ///
50.64 ///\ref named-templ-param "Named parameter" for setting
50.65 ///\c PredMap type.
50.66 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
50.67 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
50.68 template <class T>
50.69 struct SetPredMap : public Dfs<Digraph, SetPredMapTraits<T> > {
50.70 typedef Dfs<Digraph, SetPredMapTraits<T> > Create;
50.71 @@ -244,7 +251,7 @@
50.72 ///
50.73 ///\ref named-templ-param "Named parameter" for setting
50.74 ///\c DistMap type.
50.75 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
50.76 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
50.77 template <class T>
50.78 struct SetDistMap : public Dfs< Digraph, SetDistMapTraits<T> > {
50.79 typedef Dfs<Digraph, SetDistMapTraits<T> > Create;
50.80 @@ -264,7 +271,8 @@
50.81 ///
50.82 ///\ref named-templ-param "Named parameter" for setting
50.83 ///\c ReachedMap type.
50.84 - ///It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
50.85 + ///It must conform to
50.86 + ///the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
50.87 template <class T>
50.88 struct SetReachedMap : public Dfs< Digraph, SetReachedMapTraits<T> > {
50.89 typedef Dfs< Digraph, SetReachedMapTraits<T> > Create;
50.90 @@ -284,7 +292,7 @@
50.91 ///
50.92 ///\ref named-templ-param "Named parameter" for setting
50.93 ///\c ProcessedMap type.
50.94 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
50.95 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
50.96 template <class T>
50.97 struct SetProcessedMap : public Dfs< Digraph, SetProcessedMapTraits<T> > {
50.98 typedef Dfs< Digraph, SetProcessedMapTraits<T> > Create;
50.99 @@ -411,8 +419,8 @@
50.100 ///\name Execution Control
50.101 ///The simplest way to execute the DFS algorithm is to use one of the
50.102 ///member functions called \ref run(Node) "run()".\n
50.103 - ///If you need more control on the execution, first you have to call
50.104 - ///\ref init(), then you can add a source node with \ref addSource()
50.105 + ///If you need better control on the execution, you have to call
50.106 + ///\ref init() first, then you can add a source node with \ref addSource()
50.107 ///and perform the actual computation with \ref start().
50.108 ///This procedure can be repeated if there are nodes that have not
50.109 ///been reached.
50.110 @@ -632,12 +640,8 @@
50.111
50.112 ///Runs the algorithm to visit all nodes in the digraph.
50.113
50.114 - ///This method runs the %DFS algorithm in order to compute the
50.115 - ///%DFS path to each node.
50.116 - ///
50.117 - ///The algorithm computes
50.118 - ///- the %DFS tree (forest),
50.119 - ///- the distance of each node from the root(s) in the %DFS tree.
50.120 + ///This method runs the %DFS algorithm in order to visit all nodes
50.121 + ///in the digraph.
50.122 ///
50.123 ///\note <tt>d.run()</tt> is just a shortcut of the following code.
50.124 ///\code
50.125 @@ -669,9 +673,9 @@
50.126
50.127 ///@{
50.128
50.129 - ///The DFS path to a node.
50.130 + ///The DFS path to the given node.
50.131
50.132 - ///Returns the DFS path to a node.
50.133 + ///Returns the DFS path to the given node from the root(s).
50.134 ///
50.135 ///\warning \c t should be reached from the root(s).
50.136 ///
50.137 @@ -679,9 +683,9 @@
50.138 ///must be called before using this function.
50.139 Path path(Node t) const { return Path(*G, *_pred, t); }
50.140
50.141 - ///The distance of a node from the root(s).
50.142 + ///The distance of the given node from the root(s).
50.143
50.144 - ///Returns the distance of a node from the root(s).
50.145 + ///Returns the distance of the given node from the root(s).
50.146 ///
50.147 ///\warning If node \c v is not reached from the root(s), then
50.148 ///the return value of this function is undefined.
50.149 @@ -690,7 +694,7 @@
50.150 ///must be called before using this function.
50.151 int dist(Node v) const { return (*_dist)[v]; }
50.152
50.153 - ///Returns the 'previous arc' of the %DFS tree for a node.
50.154 + ///Returns the 'previous arc' of the %DFS tree for the given node.
50.155
50.156 ///This function returns the 'previous arc' of the %DFS tree for the
50.157 ///node \c v, i.e. it returns the last arc of a %DFS path from a
50.158 @@ -698,21 +702,21 @@
50.159 ///root(s) or if \c v is a root.
50.160 ///
50.161 ///The %DFS tree used here is equal to the %DFS tree used in
50.162 - ///\ref predNode().
50.163 + ///\ref predNode() and \ref predMap().
50.164 ///
50.165 ///\pre Either \ref run(Node) "run()" or \ref init()
50.166 ///must be called before using this function.
50.167 Arc predArc(Node v) const { return (*_pred)[v];}
50.168
50.169 - ///Returns the 'previous node' of the %DFS tree.
50.170 + ///Returns the 'previous node' of the %DFS tree for the given node.
50.171
50.172 ///This function returns the 'previous node' of the %DFS
50.173 ///tree for the node \c v, i.e. it returns the last but one node
50.174 - ///from a %DFS path from a root to \c v. It is \c INVALID
50.175 + ///of a %DFS path from a root to \c v. It is \c INVALID
50.176 ///if \c v is not reached from the root(s) or if \c v is a root.
50.177 ///
50.178 ///The %DFS tree used here is equal to the %DFS tree used in
50.179 - ///\ref predArc().
50.180 + ///\ref predArc() and \ref predMap().
50.181 ///
50.182 ///\pre Either \ref run(Node) "run()" or \ref init()
50.183 ///must be called before using this function.
50.184 @@ -733,13 +737,13 @@
50.185 ///predecessor arcs.
50.186 ///
50.187 ///Returns a const reference to the node map that stores the predecessor
50.188 - ///arcs, which form the DFS tree.
50.189 + ///arcs, which form the DFS tree (forest).
50.190 ///
50.191 ///\pre Either \ref run(Node) "run()" or \ref init()
50.192 ///must be called before using this function.
50.193 const PredMap &predMap() const { return *_pred;}
50.194
50.195 - ///Checks if a node is reached from the root(s).
50.196 + ///Checks if the given node. node is reached from the root(s).
50.197
50.198 ///Returns \c true if \c v is reached from the root(s).
50.199 ///
50.200 @@ -765,7 +769,7 @@
50.201 ///
50.202 ///The type of the map that stores the predecessor
50.203 ///arcs of the %DFS paths.
50.204 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
50.205 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
50.206 typedef typename Digraph::template NodeMap<typename Digraph::Arc> PredMap;
50.207 ///Instantiates a PredMap.
50.208
50.209 @@ -780,8 +784,8 @@
50.210 ///The type of the map that indicates which nodes are processed.
50.211
50.212 ///The type of the map that indicates which nodes are processed.
50.213 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
50.214 - ///By default it is a NullMap.
50.215 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
50.216 + ///By default, it is a NullMap.
50.217 typedef NullMap<typename Digraph::Node,bool> ProcessedMap;
50.218 ///Instantiates a ProcessedMap.
50.219
50.220 @@ -800,7 +804,8 @@
50.221 ///The type of the map that indicates which nodes are reached.
50.222
50.223 ///The type of the map that indicates which nodes are reached.
50.224 - ///It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
50.225 + ///It must conform to
50.226 + ///the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
50.227 typedef typename Digraph::template NodeMap<bool> ReachedMap;
50.228 ///Instantiates a ReachedMap.
50.229
50.230 @@ -815,7 +820,7 @@
50.231 ///The type of the map that stores the distances of the nodes.
50.232
50.233 ///The type of the map that stores the distances of the nodes.
50.234 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
50.235 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
50.236 typedef typename Digraph::template NodeMap<int> DistMap;
50.237 ///Instantiates a DistMap.
50.238
50.239 @@ -830,18 +835,14 @@
50.240 ///The type of the DFS paths.
50.241
50.242 ///The type of the DFS paths.
50.243 - ///It must meet the \ref concepts::Path "Path" concept.
50.244 + ///It must conform to the \ref concepts::Path "Path" concept.
50.245 typedef lemon::Path<Digraph> Path;
50.246 };
50.247
50.248 /// Default traits class used by DfsWizard
50.249
50.250 - /// To make it easier to use Dfs algorithm
50.251 - /// we have created a wizard class.
50.252 - /// This \ref DfsWizard class needs default traits,
50.253 - /// as well as the \ref Dfs class.
50.254 - /// The \ref DfsWizardBase is a class to be the default traits of the
50.255 - /// \ref DfsWizard class.
50.256 + /// Default traits class used by DfsWizard.
50.257 + /// \tparam GR The type of the digraph.
50.258 template<class GR>
50.259 class DfsWizardBase : public DfsWizardDefaultTraits<GR>
50.260 {
50.261 @@ -869,7 +870,7 @@
50.262 public:
50.263 /// Constructor.
50.264
50.265 - /// This constructor does not require parameters, therefore it initiates
50.266 + /// This constructor does not require parameters, it initiates
50.267 /// all of the attributes to \c 0.
50.268 DfsWizardBase() : _g(0), _reached(0), _processed(0), _pred(0),
50.269 _dist(0), _path(0), _di(0) {}
50.270 @@ -894,12 +895,14 @@
50.271 ///
50.272 /// This class should only be used through the \ref dfs() function,
50.273 /// which makes it easier to use the algorithm.
50.274 + ///
50.275 + /// \tparam TR The traits class that defines various types used by the
50.276 + /// algorithm.
50.277 template<class TR>
50.278 class DfsWizard : public TR
50.279 {
50.280 typedef TR Base;
50.281
50.282 - ///The type of the digraph the algorithm runs on.
50.283 typedef typename TR::Digraph Digraph;
50.284
50.285 typedef typename Digraph::Node Node;
50.286 @@ -907,16 +910,10 @@
50.287 typedef typename Digraph::Arc Arc;
50.288 typedef typename Digraph::OutArcIt OutArcIt;
50.289
50.290 - ///\brief The type of the map that stores the predecessor
50.291 - ///arcs of the DFS paths.
50.292 typedef typename TR::PredMap PredMap;
50.293 - ///\brief The type of the map that stores the distances of the nodes.
50.294 typedef typename TR::DistMap DistMap;
50.295 - ///\brief The type of the map that indicates which nodes are reached.
50.296 typedef typename TR::ReachedMap ReachedMap;
50.297 - ///\brief The type of the map that indicates which nodes are processed.
50.298 typedef typename TR::ProcessedMap ProcessedMap;
50.299 - ///The type of the DFS paths
50.300 typedef typename TR::Path Path;
50.301
50.302 public:
50.303 @@ -986,8 +983,8 @@
50.304
50.305 ///Runs DFS algorithm to visit all nodes in the digraph.
50.306
50.307 - ///This method runs DFS algorithm in order to compute
50.308 - ///the DFS path to each node.
50.309 + ///This method runs DFS algorithm in order to visit all nodes
50.310 + ///in the digraph.
50.311 void run()
50.312 {
50.313 run(INVALID);
50.314 @@ -999,11 +996,12 @@
50.315 static PredMap *createPredMap(const Digraph &) { return 0; };
50.316 SetPredMapBase(const TR &b) : TR(b) {}
50.317 };
50.318 - ///\brief \ref named-func-param "Named parameter"
50.319 - ///for setting PredMap object.
50.320 +
50.321 + ///\brief \ref named-templ-param "Named parameter" for setting
50.322 + ///the predecessor map.
50.323 ///
50.324 - ///\ref named-func-param "Named parameter"
50.325 - ///for setting PredMap object.
50.326 + ///\ref named-templ-param "Named parameter" function for setting
50.327 + ///the map that stores the predecessor arcs of the nodes.
50.328 template<class T>
50.329 DfsWizard<SetPredMapBase<T> > predMap(const T &t)
50.330 {
50.331 @@ -1017,11 +1015,12 @@
50.332 static ReachedMap *createReachedMap(const Digraph &) { return 0; };
50.333 SetReachedMapBase(const TR &b) : TR(b) {}
50.334 };
50.335 - ///\brief \ref named-func-param "Named parameter"
50.336 - ///for setting ReachedMap object.
50.337 +
50.338 + ///\brief \ref named-templ-param "Named parameter" for setting
50.339 + ///the reached map.
50.340 ///
50.341 - /// \ref named-func-param "Named parameter"
50.342 - ///for setting ReachedMap object.
50.343 + ///\ref named-templ-param "Named parameter" function for setting
50.344 + ///the map that indicates which nodes are reached.
50.345 template<class T>
50.346 DfsWizard<SetReachedMapBase<T> > reachedMap(const T &t)
50.347 {
50.348 @@ -1035,11 +1034,13 @@
50.349 static DistMap *createDistMap(const Digraph &) { return 0; };
50.350 SetDistMapBase(const TR &b) : TR(b) {}
50.351 };
50.352 - ///\brief \ref named-func-param "Named parameter"
50.353 - ///for setting DistMap object.
50.354 +
50.355 + ///\brief \ref named-templ-param "Named parameter" for setting
50.356 + ///the distance map.
50.357 ///
50.358 - /// \ref named-func-param "Named parameter"
50.359 - ///for setting DistMap object.
50.360 + ///\ref named-templ-param "Named parameter" function for setting
50.361 + ///the map that stores the distances of the nodes calculated
50.362 + ///by the algorithm.
50.363 template<class T>
50.364 DfsWizard<SetDistMapBase<T> > distMap(const T &t)
50.365 {
50.366 @@ -1053,11 +1054,12 @@
50.367 static ProcessedMap *createProcessedMap(const Digraph &) { return 0; };
50.368 SetProcessedMapBase(const TR &b) : TR(b) {}
50.369 };
50.370 - ///\brief \ref named-func-param "Named parameter"
50.371 - ///for setting ProcessedMap object.
50.372 +
50.373 + ///\brief \ref named-func-param "Named parameter" for setting
50.374 + ///the processed map.
50.375 ///
50.376 - /// \ref named-func-param "Named parameter"
50.377 - ///for setting ProcessedMap object.
50.378 + ///\ref named-templ-param "Named parameter" function for setting
50.379 + ///the map that indicates which nodes are processed.
50.380 template<class T>
50.381 DfsWizard<SetProcessedMapBase<T> > processedMap(const T &t)
50.382 {
50.383 @@ -1208,7 +1210,8 @@
50.384 /// \brief The type of the map that indicates which nodes are reached.
50.385 ///
50.386 /// The type of the map that indicates which nodes are reached.
50.387 - /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
50.388 + /// It must conform to the
50.389 + /// \ref concepts::ReadWriteMap "ReadWriteMap" concept.
50.390 typedef typename Digraph::template NodeMap<bool> ReachedMap;
50.391
50.392 /// \brief Instantiates a ReachedMap.
50.393 @@ -1246,11 +1249,11 @@
50.394 /// \ref DfsVisitor "DfsVisitor<GR>" is an empty visitor, which
50.395 /// does not observe the DFS events. If you want to observe the DFS
50.396 /// events, you should implement your own visitor class.
50.397 - /// \tparam TR Traits class to set various data types used by the
50.398 - /// algorithm. The default traits class is
50.399 - /// \ref DfsVisitDefaultTraits "DfsVisitDefaultTraits<GR>".
50.400 - /// See \ref DfsVisitDefaultTraits for the documentation of
50.401 - /// a DFS visit traits class.
50.402 + /// \tparam TR The traits class that defines various types used by the
50.403 + /// algorithm. By default, it is \ref DfsVisitDefaultTraits
50.404 + /// "DfsVisitDefaultTraits<GR>".
50.405 + /// In most cases, this parameter should not be set directly,
50.406 + /// consider to use the named template parameters instead.
50.407 #ifdef DOXYGEN
50.408 template <typename GR, typename VS, typename TR>
50.409 #else
50.410 @@ -1369,8 +1372,8 @@
50.411 /// \name Execution Control
50.412 /// The simplest way to execute the DFS algorithm is to use one of the
50.413 /// member functions called \ref run(Node) "run()".\n
50.414 - /// If you need more control on the execution, first you have to call
50.415 - /// \ref init(), then you can add a source node with \ref addSource()
50.416 + /// If you need better control on the execution, you have to call
50.417 + /// \ref init() first, then you can add a source node with \ref addSource()
50.418 /// and perform the actual computation with \ref start().
50.419 /// This procedure can be repeated if there are nodes that have not
50.420 /// been reached.
50.421 @@ -1583,12 +1586,8 @@
50.422
50.423 /// \brief Runs the algorithm to visit all nodes in the digraph.
50.424
50.425 - /// This method runs the %DFS algorithm in order to
50.426 - /// compute the %DFS path to each node.
50.427 - ///
50.428 - /// The algorithm computes
50.429 - /// - the %DFS tree (forest),
50.430 - /// - the distance of each node from the root(s) in the %DFS tree.
50.431 + /// This method runs the %DFS algorithm in order to visit all nodes
50.432 + /// in the digraph.
50.433 ///
50.434 /// \note <tt>d.run()</tt> is just a shortcut of the following code.
50.435 ///\code
50.436 @@ -1620,7 +1619,7 @@
50.437
50.438 ///@{
50.439
50.440 - /// \brief Checks if a node is reached from the root(s).
50.441 + /// \brief Checks if the given node is reached from the root(s).
50.442 ///
50.443 /// Returns \c true if \c v is reached from the root(s).
50.444 ///
51.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
51.2 +++ b/lemon/dheap.h Tue Dec 20 18:15:14 2011 +0100
51.3 @@ -0,0 +1,352 @@
51.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
51.5 + *
51.6 + * This file is a part of LEMON, a generic C++ optimization library.
51.7 + *
51.8 + * Copyright (C) 2003-2009
51.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
51.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
51.11 + *
51.12 + * Permission to use, modify and distribute this software is granted
51.13 + * provided that this copyright notice appears in all copies. For
51.14 + * precise terms see the accompanying LICENSE file.
51.15 + *
51.16 + * This software is provided "AS IS" with no warranty of any kind,
51.17 + * express or implied, and with no claim as to its suitability for any
51.18 + * purpose.
51.19 + *
51.20 + */
51.21 +
51.22 +#ifndef LEMON_DHEAP_H
51.23 +#define LEMON_DHEAP_H
51.24 +
51.25 +///\ingroup heaps
51.26 +///\file
51.27 +///\brief D-ary heap implementation.
51.28 +
51.29 +#include <vector>
51.30 +#include <utility>
51.31 +#include <functional>
51.32 +
51.33 +namespace lemon {
51.34 +
51.35 + /// \ingroup heaps
51.36 + ///
51.37 + ///\brief D-ary heap data structure.
51.38 + ///
51.39 + /// This class implements the \e D-ary \e heap data structure.
51.40 + /// It fully conforms to the \ref concepts::Heap "heap concept".
51.41 + ///
51.42 + /// The \ref DHeap "D-ary heap" is a generalization of the
51.43 + /// \ref BinHeap "binary heap" structure, its nodes have at most
51.44 + /// \c D children, instead of two.
51.45 + /// \ref BinHeap and \ref QuadHeap are specialized implementations
51.46 + /// of this structure for <tt>D=2</tt> and <tt>D=4</tt>, respectively.
51.47 + ///
51.48 + /// \tparam PR Type of the priorities of the items.
51.49 + /// \tparam IM A read-writable item map with \c int values, used
51.50 + /// internally to handle the cross references.
51.51 + /// \tparam D The degree of the heap, each node have at most \e D
51.52 + /// children. The default is 16. Powers of two are suggested to use
51.53 + /// so that the multiplications and divisions needed to traverse the
51.54 + /// nodes of the heap could be performed faster.
51.55 + /// \tparam CMP A functor class for comparing the priorities.
51.56 + /// The default is \c std::less<PR>.
51.57 + ///
51.58 + ///\sa BinHeap
51.59 + ///\sa FouraryHeap
51.60 +#ifdef DOXYGEN
51.61 + template <typename PR, typename IM, int D, typename CMP>
51.62 +#else
51.63 + template <typename PR, typename IM, int D = 16,
51.64 + typename CMP = std::less<PR> >
51.65 +#endif
51.66 + class DHeap {
51.67 + public:
51.68 + /// Type of the item-int map.
51.69 + typedef IM ItemIntMap;
51.70 + /// Type of the priorities.
51.71 + typedef PR Prio;
51.72 + /// Type of the items stored in the heap.
51.73 + typedef typename ItemIntMap::Key Item;
51.74 + /// Type of the item-priority pairs.
51.75 + typedef std::pair<Item,Prio> Pair;
51.76 + /// Functor type for comparing the priorities.
51.77 + typedef CMP Compare;
51.78 +
51.79 + /// \brief Type to represent the states of the items.
51.80 + ///
51.81 + /// Each item has a state associated to it. It can be "in heap",
51.82 + /// "pre-heap" or "post-heap". The latter two are indifferent from the
51.83 + /// heap's point of view, but may be useful to the user.
51.84 + ///
51.85 + /// The item-int map must be initialized in such way that it assigns
51.86 + /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
51.87 + enum State {
51.88 + IN_HEAP = 0, ///< = 0.
51.89 + PRE_HEAP = -1, ///< = -1.
51.90 + POST_HEAP = -2 ///< = -2.
51.91 + };
51.92 +
51.93 + private:
51.94 + std::vector<Pair> _data;
51.95 + Compare _comp;
51.96 + ItemIntMap &_iim;
51.97 +
51.98 + public:
51.99 + /// \brief Constructor.
51.100 + ///
51.101 + /// Constructor.
51.102 + /// \param map A map that assigns \c int values to the items.
51.103 + /// It is used internally to handle the cross references.
51.104 + /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
51.105 + explicit DHeap(ItemIntMap &map) : _iim(map) {}
51.106 +
51.107 + /// \brief Constructor.
51.108 + ///
51.109 + /// Constructor.
51.110 + /// \param map A map that assigns \c int values to the items.
51.111 + /// It is used internally to handle the cross references.
51.112 + /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
51.113 + /// \param comp The function object used for comparing the priorities.
51.114 + DHeap(ItemIntMap &map, const Compare &comp)
51.115 + : _iim(map), _comp(comp) {}
51.116 +
51.117 + /// \brief The number of items stored in the heap.
51.118 + ///
51.119 + /// This function returns the number of items stored in the heap.
51.120 + int size() const { return _data.size(); }
51.121 +
51.122 + /// \brief Check if the heap is empty.
51.123 + ///
51.124 + /// This function returns \c true if the heap is empty.
51.125 + bool empty() const { return _data.empty(); }
51.126 +
51.127 + /// \brief Make the heap empty.
51.128 + ///
51.129 + /// This functon makes the heap empty.
51.130 + /// It does not change the cross reference map. If you want to reuse
51.131 + /// a heap that is not surely empty, you should first clear it and
51.132 + /// then you should set the cross reference map to \c PRE_HEAP
51.133 + /// for each item.
51.134 + void clear() { _data.clear(); }
51.135 +
51.136 + private:
51.137 + int parent(int i) { return (i-1)/D; }
51.138 + int firstChild(int i) { return D*i+1; }
51.139 +
51.140 + bool less(const Pair &p1, const Pair &p2) const {
51.141 + return _comp(p1.second, p2.second);
51.142 + }
51.143 +
51.144 + void bubbleUp(int hole, Pair p) {
51.145 + int par = parent(hole);
51.146 + while( hole>0 && less(p,_data[par]) ) {
51.147 + move(_data[par],hole);
51.148 + hole = par;
51.149 + par = parent(hole);
51.150 + }
51.151 + move(p, hole);
51.152 + }
51.153 +
51.154 + void bubbleDown(int hole, Pair p, int length) {
51.155 + if( length>1 ) {
51.156 + int child = firstChild(hole);
51.157 + while( child+D<=length ) {
51.158 + int min=child;
51.159 + for (int i=1; i<D; ++i) {
51.160 + if( less(_data[child+i], _data[min]) )
51.161 + min=child+i;
51.162 + }
51.163 + if( !less(_data[min], p) )
51.164 + goto ok;
51.165 + move(_data[min], hole);
51.166 + hole = min;
51.167 + child = firstChild(hole);
51.168 + }
51.169 + if ( child<length ) {
51.170 + int min = child;
51.171 + while (++child < length) {
51.172 + if( less(_data[child], _data[min]) )
51.173 + min=child;
51.174 + }
51.175 + if( less(_data[min], p) ) {
51.176 + move(_data[min], hole);
51.177 + hole = min;
51.178 + }
51.179 + }
51.180 + }
51.181 + ok:
51.182 + move(p, hole);
51.183 + }
51.184 +
51.185 + void move(const Pair &p, int i) {
51.186 + _data[i] = p;
51.187 + _iim.set(p.first, i);
51.188 + }
51.189 +
51.190 + public:
51.191 + /// \brief Insert a pair of item and priority into the heap.
51.192 + ///
51.193 + /// This function inserts \c p.first to the heap with priority
51.194 + /// \c p.second.
51.195 + /// \param p The pair to insert.
51.196 + /// \pre \c p.first must not be stored in the heap.
51.197 + void push(const Pair &p) {
51.198 + int n = _data.size();
51.199 + _data.resize(n+1);
51.200 + bubbleUp(n, p);
51.201 + }
51.202 +
51.203 + /// \brief Insert an item into the heap with the given priority.
51.204 + ///
51.205 + /// This function inserts the given item into the heap with the
51.206 + /// given priority.
51.207 + /// \param i The item to insert.
51.208 + /// \param p The priority of the item.
51.209 + /// \pre \e i must not be stored in the heap.
51.210 + void push(const Item &i, const Prio &p) { push(Pair(i,p)); }
51.211 +
51.212 + /// \brief Return the item having minimum priority.
51.213 + ///
51.214 + /// This function returns the item having minimum priority.
51.215 + /// \pre The heap must be non-empty.
51.216 + Item top() const { return _data[0].first; }
51.217 +
51.218 + /// \brief The minimum priority.
51.219 + ///
51.220 + /// This function returns the minimum priority.
51.221 + /// \pre The heap must be non-empty.
51.222 + Prio prio() const { return _data[0].second; }
51.223 +
51.224 + /// \brief Remove the item having minimum priority.
51.225 + ///
51.226 + /// This function removes the item having minimum priority.
51.227 + /// \pre The heap must be non-empty.
51.228 + void pop() {
51.229 + int n = _data.size()-1;
51.230 + _iim.set(_data[0].first, POST_HEAP);
51.231 + if (n>0) bubbleDown(0, _data[n], n);
51.232 + _data.pop_back();
51.233 + }
51.234 +
51.235 + /// \brief Remove the given item from the heap.
51.236 + ///
51.237 + /// This function removes the given item from the heap if it is
51.238 + /// already stored.
51.239 + /// \param i The item to delete.
51.240 + /// \pre \e i must be in the heap.
51.241 + void erase(const Item &i) {
51.242 + int h = _iim[i];
51.243 + int n = _data.size()-1;
51.244 + _iim.set(_data[h].first, POST_HEAP);
51.245 + if( h<n ) {
51.246 + if( less(_data[parent(h)], _data[n]) )
51.247 + bubbleDown(h, _data[n], n);
51.248 + else
51.249 + bubbleUp(h, _data[n]);
51.250 + }
51.251 + _data.pop_back();
51.252 + }
51.253 +
51.254 + /// \brief The priority of the given item.
51.255 + ///
51.256 + /// This function returns the priority of the given item.
51.257 + /// \param i The item.
51.258 + /// \pre \e i must be in the heap.
51.259 + Prio operator[](const Item &i) const {
51.260 + int idx = _iim[i];
51.261 + return _data[idx].second;
51.262 + }
51.263 +
51.264 + /// \brief Set the priority of an item or insert it, if it is
51.265 + /// not stored in the heap.
51.266 + ///
51.267 + /// This method sets the priority of the given item if it is
51.268 + /// already stored in the heap. Otherwise it inserts the given
51.269 + /// item into the heap with the given priority.
51.270 + /// \param i The item.
51.271 + /// \param p The priority.
51.272 + void set(const Item &i, const Prio &p) {
51.273 + int idx = _iim[i];
51.274 + if( idx<0 )
51.275 + push(i,p);
51.276 + else if( _comp(p, _data[idx].second) )
51.277 + bubbleUp(idx, Pair(i,p));
51.278 + else
51.279 + bubbleDown(idx, Pair(i,p), _data.size());
51.280 + }
51.281 +
51.282 + /// \brief Decrease the priority of an item to the given value.
51.283 + ///
51.284 + /// This function decreases the priority of an item to the given value.
51.285 + /// \param i The item.
51.286 + /// \param p The priority.
51.287 + /// \pre \e i must be stored in the heap with priority at least \e p.
51.288 + void decrease(const Item &i, const Prio &p) {
51.289 + int idx = _iim[i];
51.290 + bubbleUp(idx, Pair(i,p));
51.291 + }
51.292 +
51.293 + /// \brief Increase the priority of an item to the given value.
51.294 + ///
51.295 + /// This function increases the priority of an item to the given value.
51.296 + /// \param i The item.
51.297 + /// \param p The priority.
51.298 + /// \pre \e i must be stored in the heap with priority at most \e p.
51.299 + void increase(const Item &i, const Prio &p) {
51.300 + int idx = _iim[i];
51.301 + bubbleDown(idx, Pair(i,p), _data.size());
51.302 + }
51.303 +
51.304 + /// \brief Return the state of an item.
51.305 + ///
51.306 + /// This method returns \c PRE_HEAP if the given item has never
51.307 + /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
51.308 + /// and \c POST_HEAP otherwise.
51.309 + /// In the latter case it is possible that the item will get back
51.310 + /// to the heap again.
51.311 + /// \param i The item.
51.312 + State state(const Item &i) const {
51.313 + int s = _iim[i];
51.314 + if (s>=0) s=0;
51.315 + return State(s);
51.316 + }
51.317 +
51.318 + /// \brief Set the state of an item in the heap.
51.319 + ///
51.320 + /// This function sets the state of the given item in the heap.
51.321 + /// It can be used to manually clear the heap when it is important
51.322 + /// to achive better time complexity.
51.323 + /// \param i The item.
51.324 + /// \param st The state. It should not be \c IN_HEAP.
51.325 + void state(const Item& i, State st) {
51.326 + switch (st) {
51.327 + case POST_HEAP:
51.328 + case PRE_HEAP:
51.329 + if (state(i) == IN_HEAP) erase(i);
51.330 + _iim[i] = st;
51.331 + break;
51.332 + case IN_HEAP:
51.333 + break;
51.334 + }
51.335 + }
51.336 +
51.337 + /// \brief Replace an item in the heap.
51.338 + ///
51.339 + /// This function replaces item \c i with item \c j.
51.340 + /// Item \c i must be in the heap, while \c j must be out of the heap.
51.341 + /// After calling this method, item \c i will be out of the
51.342 + /// heap and \c j will be in the heap with the same prioriority
51.343 + /// as item \c i had before.
51.344 + void replace(const Item& i, const Item& j) {
51.345 + int idx=_iim[i];
51.346 + _iim.set(i, _iim[j]);
51.347 + _iim.set(j, idx);
51.348 + _data[idx].first=j;
51.349 + }
51.350 +
51.351 + }; // class DHeap
51.352 +
51.353 +} // namespace lemon
51.354 +
51.355 +#endif // LEMON_DHEAP_H
52.1 --- a/lemon/dijkstra.h Tue Dec 20 17:44:38 2011 +0100
52.2 +++ b/lemon/dijkstra.h Tue Dec 20 18:15:14 2011 +0100
52.3 @@ -2,7 +2,7 @@
52.4 *
52.5 * This file is a part of LEMON, a generic C++ optimization library.
52.6 *
52.7 - * Copyright (C) 2003-2009
52.8 + * Copyright (C) 2003-2010
52.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
52.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
52.11 *
52.12 @@ -70,9 +70,9 @@
52.13 ///The type of the map that stores the arc lengths.
52.14
52.15 ///The type of the map that stores the arc lengths.
52.16 - ///It must meet the \ref concepts::ReadMap "ReadMap" concept.
52.17 + ///It must conform to the \ref concepts::ReadMap "ReadMap" concept.
52.18 typedef LEN LengthMap;
52.19 - ///The type of the length of the arcs.
52.20 + ///The type of the arc lengths.
52.21 typedef typename LEN::Value Value;
52.22
52.23 /// Operation traits for %Dijkstra algorithm.
52.24 @@ -116,7 +116,7 @@
52.25 ///
52.26 ///The type of the map that stores the predecessor
52.27 ///arcs of the shortest paths.
52.28 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
52.29 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
52.30 typedef typename Digraph::template NodeMap<typename Digraph::Arc> PredMap;
52.31 ///Instantiates a \c PredMap.
52.32
52.33 @@ -131,8 +131,8 @@
52.34 ///The type of the map that indicates which nodes are processed.
52.35
52.36 ///The type of the map that indicates which nodes are processed.
52.37 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
52.38 - ///By default it is a NullMap.
52.39 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
52.40 + ///By default, it is a NullMap.
52.41 typedef NullMap<typename Digraph::Node,bool> ProcessedMap;
52.42 ///Instantiates a \c ProcessedMap.
52.43
52.44 @@ -151,7 +151,7 @@
52.45 ///The type of the map that stores the distances of the nodes.
52.46
52.47 ///The type of the map that stores the distances of the nodes.
52.48 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
52.49 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
52.50 typedef typename Digraph::template NodeMap<typename LEN::Value> DistMap;
52.51 ///Instantiates a \c DistMap.
52.52
52.53 @@ -169,6 +169,10 @@
52.54 /// \ingroup shortest_path
52.55 ///This class provides an efficient implementation of the %Dijkstra algorithm.
52.56 ///
52.57 + ///The %Dijkstra algorithm solves the single-source shortest path problem
52.58 + ///when all arc lengths are non-negative. If there are negative lengths,
52.59 + ///the BellmanFord algorithm should be used instead.
52.60 + ///
52.61 ///The arc lengths are passed to the algorithm using a
52.62 ///\ref concepts::ReadMap "ReadMap",
52.63 ///so it is easy to change it to any kind of length.
52.64 @@ -188,6 +192,11 @@
52.65 ///relatively time consuming process to compute the arc lengths if
52.66 ///it is necessary. The default map type is \ref
52.67 ///concepts::Digraph::ArcMap "GR::ArcMap<int>".
52.68 + ///\tparam TR The traits class that defines various types used by the
52.69 + ///algorithm. By default, it is \ref DijkstraDefaultTraits
52.70 + ///"DijkstraDefaultTraits<GR, LEN>".
52.71 + ///In most cases, this parameter should not be set directly,
52.72 + ///consider to use the named template parameters instead.
52.73 #ifdef DOXYGEN
52.74 template <typename GR, typename LEN, typename TR>
52.75 #else
52.76 @@ -201,8 +210,8 @@
52.77 ///The type of the digraph the algorithm runs on.
52.78 typedef typename TR::Digraph Digraph;
52.79
52.80 - ///The type of the length of the arcs.
52.81 - typedef typename TR::LengthMap::Value Value;
52.82 + ///The type of the arc lengths.
52.83 + typedef typename TR::Value Value;
52.84 ///The type of the map that stores the arc lengths.
52.85 typedef typename TR::LengthMap LengthMap;
52.86 ///\brief The type of the map that stores the predecessor arcs of the
52.87 @@ -304,7 +313,7 @@
52.88 ///
52.89 ///\ref named-templ-param "Named parameter" for setting
52.90 ///\c PredMap type.
52.91 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
52.92 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
52.93 template <class T>
52.94 struct SetPredMap
52.95 : public Dijkstra< Digraph, LengthMap, SetPredMapTraits<T> > {
52.96 @@ -325,7 +334,7 @@
52.97 ///
52.98 ///\ref named-templ-param "Named parameter" for setting
52.99 ///\c DistMap type.
52.100 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
52.101 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
52.102 template <class T>
52.103 struct SetDistMap
52.104 : public Dijkstra< Digraph, LengthMap, SetDistMapTraits<T> > {
52.105 @@ -346,7 +355,7 @@
52.106 ///
52.107 ///\ref named-templ-param "Named parameter" for setting
52.108 ///\c ProcessedMap type.
52.109 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
52.110 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
52.111 template <class T>
52.112 struct SetProcessedMap
52.113 : public Dijkstra< Digraph, LengthMap, SetProcessedMapTraits<T> > {
52.114 @@ -422,7 +431,7 @@
52.115 ///automatically created by the algorithm (i.e. the digraph should be
52.116 ///passed to the constructor of the cross reference and the cross
52.117 ///reference should be passed to the constructor of the heap).
52.118 - ///However external heap and cross reference objects could also be
52.119 + ///However, external heap and cross reference objects could also be
52.120 ///passed to the algorithm using the \ref heap() function before
52.121 ///calling \ref run(Node) "run()" or \ref init().
52.122 ///\sa SetHeap
52.123 @@ -443,6 +452,7 @@
52.124 ///
52.125 ///\ref named-templ-param "Named parameter" for setting
52.126 ///\c OperationTraits type.
52.127 + /// For more information, see \ref DijkstraDefaultOperationTraits.
52.128 template <class T>
52.129 struct SetOperationTraits
52.130 : public Dijkstra<Digraph, LengthMap, SetOperationTraitsTraits<T> > {
52.131 @@ -584,8 +594,8 @@
52.132 ///\name Execution Control
52.133 ///The simplest way to execute the %Dijkstra algorithm is to use
52.134 ///one of the member functions called \ref run(Node) "run()".\n
52.135 - ///If you need more control on the execution, first you have to call
52.136 - ///\ref init(), then you can add several source nodes with
52.137 + ///If you need better control on the execution, you have to call
52.138 + ///\ref init() first, then you can add several source nodes with
52.139 ///\ref addSource(). Finally the actual path computation can be
52.140 ///performed with one of the \ref start() functions.
52.141
52.142 @@ -801,14 +811,14 @@
52.143 ///\name Query Functions
52.144 ///The results of the %Dijkstra algorithm can be obtained using these
52.145 ///functions.\n
52.146 - ///Either \ref run(Node) "run()" or \ref start() should be called
52.147 + ///Either \ref run(Node) "run()" or \ref init() should be called
52.148 ///before using them.
52.149
52.150 ///@{
52.151
52.152 - ///The shortest path to a node.
52.153 + ///The shortest path to the given node.
52.154
52.155 - ///Returns the shortest path to a node.
52.156 + ///Returns the shortest path to the given node from the root(s).
52.157 ///
52.158 ///\warning \c t should be reached from the root(s).
52.159 ///
52.160 @@ -816,9 +826,9 @@
52.161 ///must be called before using this function.
52.162 Path path(Node t) const { return Path(*G, *_pred, t); }
52.163
52.164 - ///The distance of a node from the root(s).
52.165 + ///The distance of the given node from the root(s).
52.166
52.167 - ///Returns the distance of a node from the root(s).
52.168 + ///Returns the distance of the given node from the root(s).
52.169 ///
52.170 ///\warning If node \c v is not reached from the root(s), then
52.171 ///the return value of this function is undefined.
52.172 @@ -827,29 +837,31 @@
52.173 ///must be called before using this function.
52.174 Value dist(Node v) const { return (*_dist)[v]; }
52.175
52.176 - ///Returns the 'previous arc' of the shortest path tree for a node.
52.177 -
52.178 + ///\brief Returns the 'previous arc' of the shortest path tree for
52.179 + ///the given node.
52.180 + ///
52.181 ///This function returns the 'previous arc' of the shortest path
52.182 ///tree for the node \c v, i.e. it returns the last arc of a
52.183 ///shortest path from a root to \c v. It is \c INVALID if \c v
52.184 ///is not reached from the root(s) or if \c v is a root.
52.185 ///
52.186 ///The shortest path tree used here is equal to the shortest path
52.187 - ///tree used in \ref predNode().
52.188 + ///tree used in \ref predNode() and \ref predMap().
52.189 ///
52.190 ///\pre Either \ref run(Node) "run()" or \ref init()
52.191 ///must be called before using this function.
52.192 Arc predArc(Node v) const { return (*_pred)[v]; }
52.193
52.194 - ///Returns the 'previous node' of the shortest path tree for a node.
52.195 -
52.196 + ///\brief Returns the 'previous node' of the shortest path tree for
52.197 + ///the given node.
52.198 + ///
52.199 ///This function returns the 'previous node' of the shortest path
52.200 ///tree for the node \c v, i.e. it returns the last but one node
52.201 - ///from a shortest path from a root to \c v. It is \c INVALID
52.202 + ///of a shortest path from a root to \c v. It is \c INVALID
52.203 ///if \c v is not reached from the root(s) or if \c v is a root.
52.204 ///
52.205 ///The shortest path tree used here is equal to the shortest path
52.206 - ///tree used in \ref predArc().
52.207 + ///tree used in \ref predArc() and \ref predMap().
52.208 ///
52.209 ///\pre Either \ref run(Node) "run()" or \ref init()
52.210 ///must be called before using this function.
52.211 @@ -870,13 +882,13 @@
52.212 ///predecessor arcs.
52.213 ///
52.214 ///Returns a const reference to the node map that stores the predecessor
52.215 - ///arcs, which form the shortest path tree.
52.216 + ///arcs, which form the shortest path tree (forest).
52.217 ///
52.218 ///\pre Either \ref run(Node) "run()" or \ref init()
52.219 ///must be called before using this function.
52.220 const PredMap &predMap() const { return *_pred;}
52.221
52.222 - ///Checks if a node is reached from the root(s).
52.223 + ///Checks if the given node is reached from the root(s).
52.224
52.225 ///Returns \c true if \c v is reached from the root(s).
52.226 ///
52.227 @@ -895,9 +907,9 @@
52.228 bool processed(Node v) const { return (*_heap_cross_ref)[v] ==
52.229 Heap::POST_HEAP; }
52.230
52.231 - ///The current distance of a node from the root(s).
52.232 + ///The current distance of the given node from the root(s).
52.233
52.234 - ///Returns the current distance of a node from the root(s).
52.235 + ///Returns the current distance of the given node from the root(s).
52.236 ///It may be decreased in the following processes.
52.237 ///
52.238 ///\pre Either \ref run(Node) "run()" or \ref init()
52.239 @@ -924,9 +936,9 @@
52.240 ///The type of the map that stores the arc lengths.
52.241
52.242 ///The type of the map that stores the arc lengths.
52.243 - ///It must meet the \ref concepts::ReadMap "ReadMap" concept.
52.244 + ///It must conform to the \ref concepts::ReadMap "ReadMap" concept.
52.245 typedef LEN LengthMap;
52.246 - ///The type of the length of the arcs.
52.247 + ///The type of the arc lengths.
52.248 typedef typename LEN::Value Value;
52.249
52.250 /// Operation traits for Dijkstra algorithm.
52.251 @@ -973,7 +985,7 @@
52.252 ///
52.253 ///The type of the map that stores the predecessor
52.254 ///arcs of the shortest paths.
52.255 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
52.256 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
52.257 typedef typename Digraph::template NodeMap<typename Digraph::Arc> PredMap;
52.258 ///Instantiates a PredMap.
52.259
52.260 @@ -988,8 +1000,8 @@
52.261 ///The type of the map that indicates which nodes are processed.
52.262
52.263 ///The type of the map that indicates which nodes are processed.
52.264 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
52.265 - ///By default it is a NullMap.
52.266 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
52.267 + ///By default, it is a NullMap.
52.268 typedef NullMap<typename Digraph::Node,bool> ProcessedMap;
52.269 ///Instantiates a ProcessedMap.
52.270
52.271 @@ -1008,7 +1020,7 @@
52.272 ///The type of the map that stores the distances of the nodes.
52.273
52.274 ///The type of the map that stores the distances of the nodes.
52.275 - ///It must meet the \ref concepts::WriteMap "WriteMap" concept.
52.276 + ///It must conform to the \ref concepts::WriteMap "WriteMap" concept.
52.277 typedef typename Digraph::template NodeMap<typename LEN::Value> DistMap;
52.278 ///Instantiates a DistMap.
52.279
52.280 @@ -1023,18 +1035,15 @@
52.281 ///The type of the shortest paths.
52.282
52.283 ///The type of the shortest paths.
52.284 - ///It must meet the \ref concepts::Path "Path" concept.
52.285 + ///It must conform to the \ref concepts::Path "Path" concept.
52.286 typedef lemon::Path<Digraph> Path;
52.287 };
52.288
52.289 /// Default traits class used by DijkstraWizard
52.290
52.291 - /// To make it easier to use Dijkstra algorithm
52.292 - /// we have created a wizard class.
52.293 - /// This \ref DijkstraWizard class needs default traits,
52.294 - /// as well as the \ref Dijkstra class.
52.295 - /// The \ref DijkstraWizardBase is a class to be the default traits of the
52.296 - /// \ref DijkstraWizard class.
52.297 + /// Default traits class used by DijkstraWizard.
52.298 + /// \tparam GR The type of the digraph.
52.299 + /// \tparam LEN The type of the length map.
52.300 template<typename GR, typename LEN>
52.301 class DijkstraWizardBase : public DijkstraWizardDefaultTraits<GR,LEN>
52.302 {
52.303 @@ -1088,12 +1097,14 @@
52.304 ///
52.305 /// This class should only be used through the \ref dijkstra() function,
52.306 /// which makes it easier to use the algorithm.
52.307 + ///
52.308 + /// \tparam TR The traits class that defines various types used by the
52.309 + /// algorithm.
52.310 template<class TR>
52.311 class DijkstraWizard : public TR
52.312 {
52.313 typedef TR Base;
52.314
52.315 - ///The type of the digraph the algorithm runs on.
52.316 typedef typename TR::Digraph Digraph;
52.317
52.318 typedef typename Digraph::Node Node;
52.319 @@ -1101,20 +1112,12 @@
52.320 typedef typename Digraph::Arc Arc;
52.321 typedef typename Digraph::OutArcIt OutArcIt;
52.322
52.323 - ///The type of the map that stores the arc lengths.
52.324 typedef typename TR::LengthMap LengthMap;
52.325 - ///The type of the length of the arcs.
52.326 typedef typename LengthMap::Value Value;
52.327 - ///\brief The type of the map that stores the predecessor
52.328 - ///arcs of the shortest paths.
52.329 typedef typename TR::PredMap PredMap;
52.330 - ///The type of the map that stores the distances of the nodes.
52.331 typedef typename TR::DistMap DistMap;
52.332 - ///The type of the map that indicates which nodes are processed.
52.333 typedef typename TR::ProcessedMap ProcessedMap;
52.334 - ///The type of the shortest paths
52.335 typedef typename TR::Path Path;
52.336 - ///The heap type used by the dijkstra algorithm.
52.337 typedef typename TR::Heap Heap;
52.338
52.339 public:
52.340 @@ -1186,11 +1189,12 @@
52.341 static PredMap *createPredMap(const Digraph &) { return 0; };
52.342 SetPredMapBase(const TR &b) : TR(b) {}
52.343 };
52.344 - ///\brief \ref named-func-param "Named parameter"
52.345 - ///for setting PredMap object.
52.346 +
52.347 + ///\brief \ref named-templ-param "Named parameter" for setting
52.348 + ///the predecessor map.
52.349 ///
52.350 - ///\ref named-func-param "Named parameter"
52.351 - ///for setting PredMap object.
52.352 + ///\ref named-templ-param "Named parameter" function for setting
52.353 + ///the map that stores the predecessor arcs of the nodes.
52.354 template<class T>
52.355 DijkstraWizard<SetPredMapBase<T> > predMap(const T &t)
52.356 {
52.357 @@ -1204,11 +1208,13 @@
52.358 static DistMap *createDistMap(const Digraph &) { return 0; };
52.359 SetDistMapBase(const TR &b) : TR(b) {}
52.360 };
52.361 - ///\brief \ref named-func-param "Named parameter"
52.362 - ///for setting DistMap object.
52.363 +
52.364 + ///\brief \ref named-templ-param "Named parameter" for setting
52.365 + ///the distance map.
52.366 ///
52.367 - ///\ref named-func-param "Named parameter"
52.368 - ///for setting DistMap object.
52.369 + ///\ref named-templ-param "Named parameter" function for setting
52.370 + ///the map that stores the distances of the nodes calculated
52.371 + ///by the algorithm.
52.372 template<class T>
52.373 DijkstraWizard<SetDistMapBase<T> > distMap(const T &t)
52.374 {
52.375 @@ -1222,11 +1228,12 @@
52.376 static ProcessedMap *createProcessedMap(const Digraph &) { return 0; };
52.377 SetProcessedMapBase(const TR &b) : TR(b) {}
52.378 };
52.379 - ///\brief \ref named-func-param "Named parameter"
52.380 - ///for setting ProcessedMap object.
52.381 +
52.382 + ///\brief \ref named-func-param "Named parameter" for setting
52.383 + ///the processed map.
52.384 ///
52.385 - /// \ref named-func-param "Named parameter"
52.386 - ///for setting ProcessedMap object.
52.387 + ///\ref named-templ-param "Named parameter" function for setting
52.388 + ///the map that indicates which nodes are processed.
52.389 template<class T>
52.390 DijkstraWizard<SetProcessedMapBase<T> > processedMap(const T &t)
52.391 {
52.392 @@ -1239,6 +1246,7 @@
52.393 typedef T Path;
52.394 SetPathBase(const TR &b) : TR(b) {}
52.395 };
52.396 +
52.397 ///\brief \ref named-func-param "Named parameter"
52.398 ///for getting the shortest path to the target node.
52.399 ///
53.1 --- a/lemon/dim2.h Tue Dec 20 17:44:38 2011 +0100
53.2 +++ b/lemon/dim2.h Tue Dec 20 18:15:14 2011 +0100
53.3 @@ -21,16 +21,9 @@
53.4
53.5 #include <iostream>
53.6
53.7 -///\ingroup misc
53.8 +///\ingroup geomdat
53.9 ///\file
53.10 ///\brief A simple two dimensional vector and a bounding box implementation
53.11 -///
53.12 -/// The class \ref lemon::dim2::Point "dim2::Point" implements
53.13 -/// a two dimensional vector with the usual operations.
53.14 -///
53.15 -/// The class \ref lemon::dim2::Box "dim2::Box" can be used to determine
53.16 -/// the rectangular bounding box of a set of
53.17 -/// \ref lemon::dim2::Point "dim2::Point"'s.
53.18
53.19 namespace lemon {
53.20
53.21 @@ -40,7 +33,7 @@
53.22 ///tools for handling two dimensional coordinates
53.23 namespace dim2 {
53.24
53.25 - /// \addtogroup misc
53.26 + /// \addtogroup geomdat
53.27 /// @{
53.28
53.29 /// Two dimensional vector (plain vector)
54.1 --- a/lemon/dimacs.h Tue Dec 20 17:44:38 2011 +0100
54.2 +++ b/lemon/dimacs.h Tue Dec 20 18:15:14 2011 +0100
54.3 @@ -2,7 +2,7 @@
54.4 *
54.5 * This file is a part of LEMON, a generic C++ optimization library.
54.6 *
54.7 - * Copyright (C) 2003-2009
54.8 + * Copyright (C) 2003-2010
54.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
54.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
54.11 *
54.12 @@ -61,7 +61,7 @@
54.13 ///Discover the type of a DIMACS file
54.14
54.15 ///This function starts seeking the beginning of the given file for the
54.16 - ///problem type and size info.
54.17 + ///problem type and size info.
54.18 ///The found data is returned in a special struct that can be evaluated
54.19 ///and passed to the appropriate reader function.
54.20 DimacsDescriptor dimacsType(std::istream& is)
54.21 @@ -212,7 +212,7 @@
54.22 infty = std::numeric_limits<Capacity>::has_infinity ?
54.23 std::numeric_limits<Capacity>::infinity() :
54.24 std::numeric_limits<Capacity>::max();
54.25 -
54.26 +
54.27 while (is >> c) {
54.28 switch (c) {
54.29 case 'c': // comment line
54.30 @@ -237,7 +237,7 @@
54.31 getline(is, str);
54.32 e = g.addArc(nodes[i], nodes[j]);
54.33 capacity.set(e, _cap);
54.34 - }
54.35 + }
54.36 else if (desc.type==DimacsDescriptor::MAX) {
54.37 is >> i >> j >> _cap;
54.38 getline(is, str);
54.39 @@ -362,11 +362,11 @@
54.40 {
54.41 g.addArc(s,t);
54.42 }
54.43 -
54.44 +
54.45 /// \brief DIMACS plain (di)graph reader function.
54.46 ///
54.47 /// This function reads a plain (di)graph without any designated nodes
54.48 - /// and maps (e.g. a matching instance) from DIMACS format, i.e. from
54.49 + /// and maps (e.g. a matching instance) from DIMACS format, i.e. from
54.50 /// DIMACS files having a line starting with
54.51 /// \code
54.52 /// p mat
54.53 @@ -392,7 +392,7 @@
54.54 for (int k = 1; k <= desc.nodeNum; ++k) {
54.55 nodes[k] = g.addNode();
54.56 }
54.57 -
54.58 +
54.59 while (is >> c) {
54.60 switch (c) {
54.61 case 'c': // comment line
55.1 --- a/lemon/edge_set.h Tue Dec 20 17:44:38 2011 +0100
55.2 +++ b/lemon/edge_set.h Tue Dec 20 18:15:14 2011 +0100
55.3 @@ -2,7 +2,7 @@
55.4 *
55.5 * This file is a part of LEMON, a generic C++ optimization library.
55.6 *
55.7 - * Copyright (C) 2003-2008
55.8 + * Copyright (C) 2003-2010
55.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
55.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
55.11 *
55.12 @@ -255,13 +255,14 @@
55.13 /// that node can be removed from the underlying graph, in this case
55.14 /// all arcs incident to the given node is erased from the arc set.
55.15 ///
55.16 + /// This class fully conforms to the \ref concepts::Digraph
55.17 + /// "Digraph" concept.
55.18 + /// It provides only linear time counting for nodes and arcs.
55.19 + ///
55.20 /// \param GR The type of the graph which shares its node set with
55.21 /// this class. Its interface must conform to the
55.22 /// \ref concepts::Digraph "Digraph" or \ref concepts::Graph "Graph"
55.23 /// concept.
55.24 - ///
55.25 - /// This class fully conforms to the \ref concepts::Digraph
55.26 - /// "Digraph" concept.
55.27 template <typename GR>
55.28 class ListArcSet : public ArcSetExtender<ListArcSetBase<GR> > {
55.29 typedef ArcSetExtender<ListArcSetBase<GR> > Parent;
55.30 @@ -685,13 +686,14 @@
55.31 /// be removed from the underlying graph, in this case all edges
55.32 /// incident to the given node is erased from the arc set.
55.33 ///
55.34 + /// This class fully conforms to the \ref concepts::Graph "Graph"
55.35 + /// concept.
55.36 + /// It provides only linear time counting for nodes, edges and arcs.
55.37 + ///
55.38 /// \param GR The type of the graph which shares its node set
55.39 /// with this class. Its interface must conform to the
55.40 /// \ref concepts::Digraph "Digraph" or \ref concepts::Graph "Graph"
55.41 /// concept.
55.42 - ///
55.43 - /// This class fully conforms to the \ref concepts::Graph "Graph"
55.44 - /// concept.
55.45 template <typename GR>
55.46 class ListEdgeSet : public EdgeSetExtender<ListEdgeSetBase<GR> > {
55.47 typedef EdgeSetExtender<ListEdgeSetBase<GR> > Parent;
55.48 @@ -867,7 +869,7 @@
55.49 arc.id = arcs.size() - 1;
55.50 }
55.51
55.52 - void next(Arc& arc) const {
55.53 + static void next(Arc& arc) {
55.54 --arc.id;
55.55 }
55.56
55.57 @@ -954,13 +956,14 @@
55.58 /// single-linked lists for enumerate outgoing and incoming
55.59 /// arcs. Therefore the arcs cannot be erased from the arc sets.
55.60 ///
55.61 + /// This class fully conforms to the \ref concepts::Digraph "Digraph"
55.62 + /// concept.
55.63 + /// It provides only linear time counting for nodes and arcs.
55.64 + ///
55.65 /// \warning If a node is erased from the underlying graph and this
55.66 /// node is the source or target of one arc in the arc set, then
55.67 /// the arc set is invalidated, and it cannot be used anymore. The
55.68 /// validity can be checked with the \c valid() member function.
55.69 - ///
55.70 - /// This class fully conforms to the \ref concepts::Digraph
55.71 - /// "Digraph" concept.
55.72 template <typename GR>
55.73 class SmartArcSet : public ArcSetExtender<SmartArcSetBase<GR> > {
55.74 typedef ArcSetExtender<SmartArcSetBase<GR> > Parent;
55.75 @@ -1173,7 +1176,7 @@
55.76 arc.id = arcs.size() - 1;
55.77 }
55.78
55.79 - void next(Arc& arc) const {
55.80 + static void next(Arc& arc) {
55.81 --arc.id;
55.82 }
55.83
55.84 @@ -1181,7 +1184,7 @@
55.85 arc.id = arcs.size() / 2 - 1;
55.86 }
55.87
55.88 - void next(Edge& arc) const {
55.89 + static void next(Edge& arc) {
55.90 --arc.id;
55.91 }
55.92
55.93 @@ -1304,13 +1307,14 @@
55.94 /// single-linked lists for enumerate incident edges. Therefore the
55.95 /// edges cannot be erased from the edge sets.
55.96 ///
55.97 + /// This class fully conforms to the \ref concepts::Graph "Graph"
55.98 + /// concept.
55.99 + /// It provides only linear time counting for nodes, edges and arcs.
55.100 + ///
55.101 /// \warning If a node is erased from the underlying graph and this
55.102 /// node is incident to one edge in the edge set, then the edge set
55.103 /// is invalidated, and it cannot be used anymore. The validity can
55.104 /// be checked with the \c valid() member function.
55.105 - ///
55.106 - /// This class fully conforms to the \ref concepts::Graph
55.107 - /// "Graph" concept.
55.108 template <typename GR>
55.109 class SmartEdgeSet : public EdgeSetExtender<SmartEdgeSetBase<GR> > {
55.110 typedef EdgeSetExtender<SmartEdgeSetBase<GR> > Parent;
56.1 --- a/lemon/euler.h Tue Dec 20 17:44:38 2011 +0100
56.2 +++ b/lemon/euler.h Tue Dec 20 18:15:14 2011 +0100
56.3 @@ -2,7 +2,7 @@
56.4 *
56.5 * This file is a part of LEMON, a generic C++ optimization library.
56.6 *
56.7 - * Copyright (C) 2003-2009
56.8 + * Copyright (C) 2003-2010
56.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
56.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
56.11 *
56.12 @@ -26,7 +26,7 @@
56.13
56.14 /// \ingroup graph_properties
56.15 /// \file
56.16 -/// \brief Euler tour iterators and a function for checking the \e Eulerian
56.17 +/// \brief Euler tour iterators and a function for checking the \e Eulerian
56.18 /// property.
56.19 ///
56.20 ///This file provides Euler tour iterators and a function to check
56.21 @@ -41,7 +41,7 @@
56.22 ///graph (if there exists) and it converts to the \c Arc type of the digraph.
56.23 ///
56.24 ///For example, if the given digraph has an Euler tour (i.e it has only one
56.25 - ///non-trivial component and the in-degree is equal to the out-degree
56.26 + ///non-trivial component and the in-degree is equal to the out-degree
56.27 ///for all nodes), then the following code will put the arcs of \c g
56.28 ///to the vector \c et according to an Euler tour of \c g.
56.29 ///\code
56.30 @@ -138,7 +138,7 @@
56.31 ///\e undirected graph (if there exists) and it converts to the \c Arc
56.32 ///and \c Edge types of the graph.
56.33 ///
56.34 - ///For example, if the given graph has an Euler tour (i.e it has only one
56.35 + ///For example, if the given graph has an Euler tour (i.e it has only one
56.36 ///non-trivial component and the degree of each node is even),
56.37 ///the following code will print the arc IDs according to an
56.38 ///Euler tour of \c g.
56.39 @@ -147,7 +147,7 @@
56.40 /// std::cout << g.id(Edge(e)) << std::eol;
56.41 /// }
56.42 ///\endcode
56.43 - ///Although this iterator is for undirected graphs, it still returns
56.44 + ///Although this iterator is for undirected graphs, it still returns
56.45 ///arcs in order to indicate the direction of the tour.
56.46 ///(But arcs convert to edges, of course.)
56.47 ///
56.48 @@ -233,7 +233,7 @@
56.49
56.50 /// Postfix incrementation.
56.51 ///
56.52 - ///\warning This incrementation returns an \c Arc (which converts to
56.53 + ///\warning This incrementation returns an \c Arc (which converts to
56.54 ///an \c Edge), not an \ref EulerIt, as one may expect.
56.55 Arc operator++(int)
56.56 {
57.1 --- a/lemon/fib_heap.h Tue Dec 20 17:44:38 2011 +0100
57.2 +++ b/lemon/fib_heap.h Tue Dec 20 18:15:14 2011 +0100
57.3 @@ -20,53 +20,49 @@
57.4 #define LEMON_FIB_HEAP_H
57.5
57.6 ///\file
57.7 -///\ingroup auxdat
57.8 -///\brief Fibonacci Heap implementation.
57.9 +///\ingroup heaps
57.10 +///\brief Fibonacci heap implementation.
57.11
57.12 #include <vector>
57.13 +#include <utility>
57.14 #include <functional>
57.15 #include <lemon/math.h>
57.16
57.17 namespace lemon {
57.18
57.19 - /// \ingroup auxdat
57.20 + /// \ingroup heaps
57.21 ///
57.22 - ///\brief Fibonacci Heap.
57.23 + /// \brief Fibonacci heap data structure.
57.24 ///
57.25 - ///This class implements the \e Fibonacci \e heap data structure. A \e heap
57.26 - ///is a data structure for storing items with specified values called \e
57.27 - ///priorities in such a way that finding the item with minimum priority is
57.28 - ///efficient. \c CMP specifies the ordering of the priorities. In a heap
57.29 - ///one can change the priority of an item, add or erase an item, etc.
57.30 + /// This class implements the \e Fibonacci \e heap data structure.
57.31 + /// It fully conforms to the \ref concepts::Heap "heap concept".
57.32 ///
57.33 - ///The methods \ref increase and \ref erase are not efficient in a Fibonacci
57.34 - ///heap. In case of many calls to these operations, it is better to use a
57.35 - ///\ref BinHeap "binary heap".
57.36 + /// The methods \ref increase() and \ref erase() are not efficient in a
57.37 + /// Fibonacci heap. In case of many calls of these operations, it is
57.38 + /// better to use other heap structure, e.g. \ref BinHeap "binary heap".
57.39 ///
57.40 - ///\param PRIO Type of the priority of the items.
57.41 - ///\param IM A read and writable Item int map, used internally
57.42 - ///to handle the cross references.
57.43 - ///\param CMP A class for the ordering of the priorities. The
57.44 - ///default is \c std::less<PRIO>.
57.45 - ///
57.46 - ///\sa BinHeap
57.47 - ///\sa Dijkstra
57.48 + /// \tparam PR Type of the priorities of the items.
57.49 + /// \tparam IM A read-writable item map with \c int values, used
57.50 + /// internally to handle the cross references.
57.51 + /// \tparam CMP A functor class for comparing the priorities.
57.52 + /// The default is \c std::less<PR>.
57.53 #ifdef DOXYGEN
57.54 - template <typename PRIO, typename IM, typename CMP>
57.55 + template <typename PR, typename IM, typename CMP>
57.56 #else
57.57 - template <typename PRIO, typename IM, typename CMP = std::less<PRIO> >
57.58 + template <typename PR, typename IM, typename CMP = std::less<PR> >
57.59 #endif
57.60 class FibHeap {
57.61 public:
57.62 - ///\e
57.63 +
57.64 + /// Type of the item-int map.
57.65 typedef IM ItemIntMap;
57.66 - ///\e
57.67 - typedef PRIO Prio;
57.68 - ///\e
57.69 + /// Type of the priorities.
57.70 + typedef PR Prio;
57.71 + /// Type of the items stored in the heap.
57.72 typedef typename ItemIntMap::Key Item;
57.73 - ///\e
57.74 + /// Type of the item-priority pairs.
57.75 typedef std::pair<Item,Prio> Pair;
57.76 - ///\e
57.77 + /// Functor type for comparing the priorities.
57.78 typedef CMP Compare;
57.79
57.80 private:
57.81 @@ -80,10 +76,10 @@
57.82
57.83 public:
57.84
57.85 - /// \brief Type to represent the items states.
57.86 + /// \brief Type to represent the states of the items.
57.87 ///
57.88 - /// Each Item element have a state associated to it. It may be "in heap",
57.89 - /// "pre heap" or "post heap". The latter two are indifferent from the
57.90 + /// Each item has a state associated to it. It can be "in heap",
57.91 + /// "pre-heap" or "post-heap". The latter two are indifferent from the
57.92 /// heap's point of view, but may be useful to the user.
57.93 ///
57.94 /// The item-int map must be initialized in such way that it assigns
57.95 @@ -94,60 +90,54 @@
57.96 POST_HEAP = -2 ///< = -2.
57.97 };
57.98
57.99 - /// \brief The constructor
57.100 + /// \brief Constructor.
57.101 ///
57.102 - /// \c map should be given to the constructor, since it is
57.103 - /// used internally to handle the cross references.
57.104 + /// Constructor.
57.105 + /// \param map A map that assigns \c int values to the items.
57.106 + /// It is used internally to handle the cross references.
57.107 + /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
57.108 explicit FibHeap(ItemIntMap &map)
57.109 : _minimum(0), _iim(map), _num() {}
57.110
57.111 - /// \brief The constructor
57.112 + /// \brief Constructor.
57.113 ///
57.114 - /// \c map should be given to the constructor, since it is used
57.115 - /// internally to handle the cross references. \c comp is an
57.116 - /// object for ordering of the priorities.
57.117 + /// Constructor.
57.118 + /// \param map A map that assigns \c int values to the items.
57.119 + /// It is used internally to handle the cross references.
57.120 + /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
57.121 + /// \param comp The function object used for comparing the priorities.
57.122 FibHeap(ItemIntMap &map, const Compare &comp)
57.123 : _minimum(0), _iim(map), _comp(comp), _num() {}
57.124
57.125 /// \brief The number of items stored in the heap.
57.126 ///
57.127 - /// Returns the number of items stored in the heap.
57.128 + /// This function returns the number of items stored in the heap.
57.129 int size() const { return _num; }
57.130
57.131 - /// \brief Checks if the heap stores no items.
57.132 + /// \brief Check if the heap is empty.
57.133 ///
57.134 - /// Returns \c true if and only if the heap stores no items.
57.135 + /// This function returns \c true if the heap is empty.
57.136 bool empty() const { return _num==0; }
57.137
57.138 - /// \brief Make empty this heap.
57.139 + /// \brief Make the heap empty.
57.140 ///
57.141 - /// Make empty this heap. It does not change the cross reference
57.142 - /// map. If you want to reuse a heap what is not surely empty you
57.143 - /// should first clear the heap and after that you should set the
57.144 - /// cross reference map for each item to \c PRE_HEAP.
57.145 + /// This functon makes the heap empty.
57.146 + /// It does not change the cross reference map. If you want to reuse
57.147 + /// a heap that is not surely empty, you should first clear it and
57.148 + /// then you should set the cross reference map to \c PRE_HEAP
57.149 + /// for each item.
57.150 void clear() {
57.151 _data.clear(); _minimum = 0; _num = 0;
57.152 }
57.153
57.154 - /// \brief \c item gets to the heap with priority \c value independently
57.155 - /// if \c item was already there.
57.156 + /// \brief Insert an item into the heap with the given priority.
57.157 ///
57.158 - /// This method calls \ref push(\c item, \c value) if \c item is not
57.159 - /// stored in the heap and it calls \ref decrease(\c item, \c value) or
57.160 - /// \ref increase(\c item, \c value) otherwise.
57.161 - void set (const Item& item, const Prio& value) {
57.162 - int i=_iim[item];
57.163 - if ( i >= 0 && _data[i].in ) {
57.164 - if ( _comp(value, _data[i].prio) ) decrease(item, value);
57.165 - if ( _comp(_data[i].prio, value) ) increase(item, value);
57.166 - } else push(item, value);
57.167 - }
57.168 -
57.169 - /// \brief Adds \c item to the heap with priority \c value.
57.170 - ///
57.171 - /// Adds \c item to the heap with priority \c value.
57.172 - /// \pre \c item must not be stored in the heap.
57.173 - void push (const Item& item, const Prio& value) {
57.174 + /// This function inserts the given item into the heap with the
57.175 + /// given priority.
57.176 + /// \param item The item to insert.
57.177 + /// \param prio The priority of the item.
57.178 + /// \pre \e item must not be stored in the heap.
57.179 + void push (const Item& item, const Prio& prio) {
57.180 int i=_iim[item];
57.181 if ( i < 0 ) {
57.182 int s=_data.size();
57.183 @@ -168,47 +158,37 @@
57.184 _data[i].right_neighbor=_data[_minimum].right_neighbor;
57.185 _data[_minimum].right_neighbor=i;
57.186 _data[i].left_neighbor=_minimum;
57.187 - if ( _comp( value, _data[_minimum].prio) ) _minimum=i;
57.188 + if ( _comp( prio, _data[_minimum].prio) ) _minimum=i;
57.189 } else {
57.190 _data[i].right_neighbor=_data[i].left_neighbor=i;
57.191 _minimum=i;
57.192 }
57.193 - _data[i].prio=value;
57.194 + _data[i].prio=prio;
57.195 ++_num;
57.196 }
57.197
57.198 - /// \brief Returns the item with minimum priority relative to \c Compare.
57.199 + /// \brief Return the item having minimum priority.
57.200 ///
57.201 - /// This method returns the item with minimum priority relative to \c
57.202 - /// Compare.
57.203 - /// \pre The heap must be nonempty.
57.204 + /// This function returns the item having minimum priority.
57.205 + /// \pre The heap must be non-empty.
57.206 Item top() const { return _data[_minimum].name; }
57.207
57.208 - /// \brief Returns the minimum priority relative to \c Compare.
57.209 + /// \brief The minimum priority.
57.210 ///
57.211 - /// It returns the minimum priority relative to \c Compare.
57.212 - /// \pre The heap must be nonempty.
57.213 - const Prio& prio() const { return _data[_minimum].prio; }
57.214 + /// This function returns the minimum priority.
57.215 + /// \pre The heap must be non-empty.
57.216 + Prio prio() const { return _data[_minimum].prio; }
57.217
57.218 - /// \brief Returns the priority of \c item.
57.219 + /// \brief Remove the item having minimum priority.
57.220 ///
57.221 - /// It returns the priority of \c item.
57.222 - /// \pre \c item must be in the heap.
57.223 - const Prio& operator[](const Item& item) const {
57.224 - return _data[_iim[item]].prio;
57.225 - }
57.226 -
57.227 - /// \brief Deletes the item with minimum priority relative to \c Compare.
57.228 - ///
57.229 - /// This method deletes the item with minimum priority relative to \c
57.230 - /// Compare from the heap.
57.231 + /// This function removes the item having minimum priority.
57.232 /// \pre The heap must be non-empty.
57.233 void pop() {
57.234 /*The first case is that there are only one root.*/
57.235 if ( _data[_minimum].left_neighbor==_minimum ) {
57.236 _data[_minimum].in=false;
57.237 if ( _data[_minimum].degree!=0 ) {
57.238 - makeroot(_data[_minimum].child);
57.239 + makeRoot(_data[_minimum].child);
57.240 _minimum=_data[_minimum].child;
57.241 balance();
57.242 }
57.243 @@ -221,7 +201,7 @@
57.244 int child=_data[_minimum].child;
57.245 int last_child=_data[child].left_neighbor;
57.246
57.247 - makeroot(child);
57.248 + makeRoot(child);
57.249
57.250 _data[left].right_neighbor=child;
57.251 _data[child].left_neighbor=left;
57.252 @@ -234,10 +214,12 @@
57.253 --_num;
57.254 }
57.255
57.256 - /// \brief Deletes \c item from the heap.
57.257 + /// \brief Remove the given item from the heap.
57.258 ///
57.259 - /// This method deletes \c item from the heap, if \c item was already
57.260 - /// stored in the heap. It is quite inefficient in Fibonacci heaps.
57.261 + /// This function removes the given item from the heap if it is
57.262 + /// already stored.
57.263 + /// \param item The item to delete.
57.264 + /// \pre \e item must be in the heap.
57.265 void erase (const Item& item) {
57.266 int i=_iim[item];
57.267
57.268 @@ -252,43 +234,68 @@
57.269 }
57.270 }
57.271
57.272 - /// \brief Decreases the priority of \c item to \c value.
57.273 + /// \brief The priority of the given item.
57.274 ///
57.275 - /// This method decreases the priority of \c item to \c value.
57.276 - /// \pre \c item must be stored in the heap with priority at least \c
57.277 - /// value relative to \c Compare.
57.278 - void decrease (Item item, const Prio& value) {
57.279 + /// This function returns the priority of the given item.
57.280 + /// \param item The item.
57.281 + /// \pre \e item must be in the heap.
57.282 + Prio operator[](const Item& item) const {
57.283 + return _data[_iim[item]].prio;
57.284 + }
57.285 +
57.286 + /// \brief Set the priority of an item or insert it, if it is
57.287 + /// not stored in the heap.
57.288 + ///
57.289 + /// This method sets the priority of the given item if it is
57.290 + /// already stored in the heap. Otherwise it inserts the given
57.291 + /// item into the heap with the given priority.
57.292 + /// \param item The item.
57.293 + /// \param prio The priority.
57.294 + void set (const Item& item, const Prio& prio) {
57.295 int i=_iim[item];
57.296 - _data[i].prio=value;
57.297 + if ( i >= 0 && _data[i].in ) {
57.298 + if ( _comp(prio, _data[i].prio) ) decrease(item, prio);
57.299 + if ( _comp(_data[i].prio, prio) ) increase(item, prio);
57.300 + } else push(item, prio);
57.301 + }
57.302 +
57.303 + /// \brief Decrease the priority of an item to the given value.
57.304 + ///
57.305 + /// This function decreases the priority of an item to the given value.
57.306 + /// \param item The item.
57.307 + /// \param prio The priority.
57.308 + /// \pre \e item must be stored in the heap with priority at least \e prio.
57.309 + void decrease (const Item& item, const Prio& prio) {
57.310 + int i=_iim[item];
57.311 + _data[i].prio=prio;
57.312 int p=_data[i].parent;
57.313
57.314 - if ( p!=-1 && _comp(value, _data[p].prio) ) {
57.315 + if ( p!=-1 && _comp(prio, _data[p].prio) ) {
57.316 cut(i,p);
57.317 cascade(p);
57.318 }
57.319 - if ( _comp(value, _data[_minimum].prio) ) _minimum=i;
57.320 + if ( _comp(prio, _data[_minimum].prio) ) _minimum=i;
57.321 }
57.322
57.323 - /// \brief Increases the priority of \c item to \c value.
57.324 + /// \brief Increase the priority of an item to the given value.
57.325 ///
57.326 - /// This method sets the priority of \c item to \c value. Though
57.327 - /// there is no precondition on the priority of \c item, this
57.328 - /// method should be used only if it is indeed necessary to increase
57.329 - /// (relative to \c Compare) the priority of \c item, because this
57.330 - /// method is inefficient.
57.331 - void increase (Item item, const Prio& value) {
57.332 + /// This function increases the priority of an item to the given value.
57.333 + /// \param item The item.
57.334 + /// \param prio The priority.
57.335 + /// \pre \e item must be stored in the heap with priority at most \e prio.
57.336 + void increase (const Item& item, const Prio& prio) {
57.337 erase(item);
57.338 - push(item, value);
57.339 + push(item, prio);
57.340 }
57.341
57.342 -
57.343 - /// \brief Returns if \c item is in, has already been in, or has never
57.344 - /// been in the heap.
57.345 + /// \brief Return the state of an item.
57.346 ///
57.347 - /// This method returns PRE_HEAP if \c item has never been in the
57.348 - /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
57.349 - /// otherwise. In the latter case it is possible that \c item will
57.350 - /// get back to the heap again.
57.351 + /// This method returns \c PRE_HEAP if the given item has never
57.352 + /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
57.353 + /// and \c POST_HEAP otherwise.
57.354 + /// In the latter case it is possible that the item will get back
57.355 + /// to the heap again.
57.356 + /// \param item The item.
57.357 State state(const Item &item) const {
57.358 int i=_iim[item];
57.359 if( i>=0 ) {
57.360 @@ -298,11 +305,11 @@
57.361 return State(i);
57.362 }
57.363
57.364 - /// \brief Sets the state of the \c item in the heap.
57.365 + /// \brief Set the state of an item in the heap.
57.366 ///
57.367 - /// Sets the state of the \c item in the heap. It can be used to
57.368 - /// manually clear the heap when it is important to achive the
57.369 - /// better time _complexity.
57.370 + /// This function sets the state of the given item in the heap.
57.371 + /// It can be used to manually clear the heap when it is important
57.372 + /// to achive better time complexity.
57.373 /// \param i The item.
57.374 /// \param st The state. It should not be \c IN_HEAP.
57.375 void state(const Item& i, State st) {
57.376 @@ -365,7 +372,7 @@
57.377 } while ( s != m );
57.378 }
57.379
57.380 - void makeroot(int c) {
57.381 + void makeRoot(int c) {
57.382 int s=c;
57.383 do {
57.384 _data[s].parent=-1;
58.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
58.2 +++ b/lemon/fractional_matching.h Tue Dec 20 18:15:14 2011 +0100
58.3 @@ -0,0 +1,2139 @@
58.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
58.5 + *
58.6 + * This file is a part of LEMON, a generic C++ optimization library.
58.7 + *
58.8 + * Copyright (C) 2003-2010
58.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
58.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
58.11 + *
58.12 + * Permission to use, modify and distribute this software is granted
58.13 + * provided that this copyright notice appears in all copies. For
58.14 + * precise terms see the accompanying LICENSE file.
58.15 + *
58.16 + * This software is provided "AS IS" with no warranty of any kind,
58.17 + * express or implied, and with no claim as to its suitability for any
58.18 + * purpose.
58.19 + *
58.20 + */
58.21 +
58.22 +#ifndef LEMON_FRACTIONAL_MATCHING_H
58.23 +#define LEMON_FRACTIONAL_MATCHING_H
58.24 +
58.25 +#include <vector>
58.26 +#include <queue>
58.27 +#include <set>
58.28 +#include <limits>
58.29 +
58.30 +#include <lemon/core.h>
58.31 +#include <lemon/unionfind.h>
58.32 +#include <lemon/bin_heap.h>
58.33 +#include <lemon/maps.h>
58.34 +#include <lemon/assert.h>
58.35 +#include <lemon/elevator.h>
58.36 +
58.37 +///\ingroup matching
58.38 +///\file
58.39 +///\brief Fractional matching algorithms in general graphs.
58.40 +
58.41 +namespace lemon {
58.42 +
58.43 + /// \brief Default traits class of MaxFractionalMatching class.
58.44 + ///
58.45 + /// Default traits class of MaxFractionalMatching class.
58.46 + /// \tparam GR Graph type.
58.47 + template <typename GR>
58.48 + struct MaxFractionalMatchingDefaultTraits {
58.49 +
58.50 + /// \brief The type of the graph the algorithm runs on.
58.51 + typedef GR Graph;
58.52 +
58.53 + /// \brief The type of the map that stores the matching.
58.54 + ///
58.55 + /// The type of the map that stores the matching arcs.
58.56 + /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
58.57 + typedef typename Graph::template NodeMap<typename GR::Arc> MatchingMap;
58.58 +
58.59 + /// \brief Instantiates a MatchingMap.
58.60 + ///
58.61 + /// This function instantiates a \ref MatchingMap.
58.62 + /// \param graph The graph for which we would like to define
58.63 + /// the matching map.
58.64 + static MatchingMap* createMatchingMap(const Graph& graph) {
58.65 + return new MatchingMap(graph);
58.66 + }
58.67 +
58.68 + /// \brief The elevator type used by MaxFractionalMatching algorithm.
58.69 + ///
58.70 + /// The elevator type used by MaxFractionalMatching algorithm.
58.71 + ///
58.72 + /// \sa Elevator
58.73 + /// \sa LinkedElevator
58.74 + typedef LinkedElevator<Graph, typename Graph::Node> Elevator;
58.75 +
58.76 + /// \brief Instantiates an Elevator.
58.77 + ///
58.78 + /// This function instantiates an \ref Elevator.
58.79 + /// \param graph The graph for which we would like to define
58.80 + /// the elevator.
58.81 + /// \param max_level The maximum level of the elevator.
58.82 + static Elevator* createElevator(const Graph& graph, int max_level) {
58.83 + return new Elevator(graph, max_level);
58.84 + }
58.85 + };
58.86 +
58.87 + /// \ingroup matching
58.88 + ///
58.89 + /// \brief Max cardinality fractional matching
58.90 + ///
58.91 + /// This class provides an implementation of fractional matching
58.92 + /// algorithm based on push-relabel principle.
58.93 + ///
58.94 + /// The maximum cardinality fractional matching is a relaxation of the
58.95 + /// maximum cardinality matching problem where the odd set constraints
58.96 + /// are omitted.
58.97 + /// It can be formulated with the following linear program.
58.98 + /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
58.99 + /// \f[x_e \ge 0\quad \forall e\in E\f]
58.100 + /// \f[\max \sum_{e\in E}x_e\f]
58.101 + /// where \f$\delta(X)\f$ is the set of edges incident to a node in
58.102 + /// \f$X\f$. The result can be represented as the union of a
58.103 + /// matching with one value edges and a set of odd length cycles
58.104 + /// with half value edges.
58.105 + ///
58.106 + /// The algorithm calculates an optimal fractional matching and a
58.107 + /// barrier. The number of adjacents of any node set minus the size
58.108 + /// of node set is a lower bound on the uncovered nodes in the
58.109 + /// graph. For maximum matching a barrier is computed which
58.110 + /// maximizes this difference.
58.111 + ///
58.112 + /// The algorithm can be executed with the run() function. After it
58.113 + /// the matching (the primal solution) and the barrier (the dual
58.114 + /// solution) can be obtained using the query functions.
58.115 + ///
58.116 + /// The primal solution is multiplied by
58.117 + /// \ref MaxFractionalMatching::primalScale "2".
58.118 + ///
58.119 + /// \tparam GR The undirected graph type the algorithm runs on.
58.120 +#ifdef DOXYGEN
58.121 + template <typename GR, typename TR>
58.122 +#else
58.123 + template <typename GR,
58.124 + typename TR = MaxFractionalMatchingDefaultTraits<GR> >
58.125 +#endif
58.126 + class MaxFractionalMatching {
58.127 + public:
58.128 +
58.129 + /// \brief The \ref MaxFractionalMatchingDefaultTraits "traits
58.130 + /// class" of the algorithm.
58.131 + typedef TR Traits;
58.132 + /// The type of the graph the algorithm runs on.
58.133 + typedef typename TR::Graph Graph;
58.134 + /// The type of the matching map.
58.135 + typedef typename TR::MatchingMap MatchingMap;
58.136 + /// The type of the elevator.
58.137 + typedef typename TR::Elevator Elevator;
58.138 +
58.139 + /// \brief Scaling factor for primal solution
58.140 + ///
58.141 + /// Scaling factor for primal solution.
58.142 + static const int primalScale = 2;
58.143 +
58.144 + private:
58.145 +
58.146 + const Graph &_graph;
58.147 + int _node_num;
58.148 + bool _allow_loops;
58.149 + int _empty_level;
58.150 +
58.151 + TEMPLATE_GRAPH_TYPEDEFS(Graph);
58.152 +
58.153 + bool _local_matching;
58.154 + MatchingMap *_matching;
58.155 +
58.156 + bool _local_level;
58.157 + Elevator *_level;
58.158 +
58.159 + typedef typename Graph::template NodeMap<int> InDegMap;
58.160 + InDegMap *_indeg;
58.161 +
58.162 + void createStructures() {
58.163 + _node_num = countNodes(_graph);
58.164 +
58.165 + if (!_matching) {
58.166 + _local_matching = true;
58.167 + _matching = Traits::createMatchingMap(_graph);
58.168 + }
58.169 + if (!_level) {
58.170 + _local_level = true;
58.171 + _level = Traits::createElevator(_graph, _node_num);
58.172 + }
58.173 + if (!_indeg) {
58.174 + _indeg = new InDegMap(_graph);
58.175 + }
58.176 + }
58.177 +
58.178 + void destroyStructures() {
58.179 + if (_local_matching) {
58.180 + delete _matching;
58.181 + }
58.182 + if (_local_level) {
58.183 + delete _level;
58.184 + }
58.185 + if (_indeg) {
58.186 + delete _indeg;
58.187 + }
58.188 + }
58.189 +
58.190 + void postprocessing() {
58.191 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.192 + if ((*_indeg)[n] != 0) continue;
58.193 + _indeg->set(n, -1);
58.194 + Node u = n;
58.195 + while ((*_matching)[u] != INVALID) {
58.196 + Node v = _graph.target((*_matching)[u]);
58.197 + _indeg->set(v, -1);
58.198 + Arc a = _graph.oppositeArc((*_matching)[u]);
58.199 + u = _graph.target((*_matching)[v]);
58.200 + _indeg->set(u, -1);
58.201 + _matching->set(v, a);
58.202 + }
58.203 + }
58.204 +
58.205 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.206 + if ((*_indeg)[n] != 1) continue;
58.207 + _indeg->set(n, -1);
58.208 +
58.209 + int num = 1;
58.210 + Node u = _graph.target((*_matching)[n]);
58.211 + while (u != n) {
58.212 + _indeg->set(u, -1);
58.213 + u = _graph.target((*_matching)[u]);
58.214 + ++num;
58.215 + }
58.216 + if (num % 2 == 0 && num > 2) {
58.217 + Arc prev = _graph.oppositeArc((*_matching)[n]);
58.218 + Node v = _graph.target((*_matching)[n]);
58.219 + u = _graph.target((*_matching)[v]);
58.220 + _matching->set(v, prev);
58.221 + while (u != n) {
58.222 + prev = _graph.oppositeArc((*_matching)[u]);
58.223 + v = _graph.target((*_matching)[u]);
58.224 + u = _graph.target((*_matching)[v]);
58.225 + _matching->set(v, prev);
58.226 + }
58.227 + }
58.228 + }
58.229 + }
58.230 +
58.231 + public:
58.232 +
58.233 + typedef MaxFractionalMatching Create;
58.234 +
58.235 + ///\name Named Template Parameters
58.236 +
58.237 + ///@{
58.238 +
58.239 + template <typename T>
58.240 + struct SetMatchingMapTraits : public Traits {
58.241 + typedef T MatchingMap;
58.242 + static MatchingMap *createMatchingMap(const Graph&) {
58.243 + LEMON_ASSERT(false, "MatchingMap is not initialized");
58.244 + return 0; // ignore warnings
58.245 + }
58.246 + };
58.247 +
58.248 + /// \brief \ref named-templ-param "Named parameter" for setting
58.249 + /// MatchingMap type
58.250 + ///
58.251 + /// \ref named-templ-param "Named parameter" for setting MatchingMap
58.252 + /// type.
58.253 + template <typename T>
58.254 + struct SetMatchingMap
58.255 + : public MaxFractionalMatching<Graph, SetMatchingMapTraits<T> > {
58.256 + typedef MaxFractionalMatching<Graph, SetMatchingMapTraits<T> > Create;
58.257 + };
58.258 +
58.259 + template <typename T>
58.260 + struct SetElevatorTraits : public Traits {
58.261 + typedef T Elevator;
58.262 + static Elevator *createElevator(const Graph&, int) {
58.263 + LEMON_ASSERT(false, "Elevator is not initialized");
58.264 + return 0; // ignore warnings
58.265 + }
58.266 + };
58.267 +
58.268 + /// \brief \ref named-templ-param "Named parameter" for setting
58.269 + /// Elevator type
58.270 + ///
58.271 + /// \ref named-templ-param "Named parameter" for setting Elevator
58.272 + /// type. If this named parameter is used, then an external
58.273 + /// elevator object must be passed to the algorithm using the
58.274 + /// \ref elevator(Elevator&) "elevator()" function before calling
58.275 + /// \ref run() or \ref init().
58.276 + /// \sa SetStandardElevator
58.277 + template <typename T>
58.278 + struct SetElevator
58.279 + : public MaxFractionalMatching<Graph, SetElevatorTraits<T> > {
58.280 + typedef MaxFractionalMatching<Graph, SetElevatorTraits<T> > Create;
58.281 + };
58.282 +
58.283 + template <typename T>
58.284 + struct SetStandardElevatorTraits : public Traits {
58.285 + typedef T Elevator;
58.286 + static Elevator *createElevator(const Graph& graph, int max_level) {
58.287 + return new Elevator(graph, max_level);
58.288 + }
58.289 + };
58.290 +
58.291 + /// \brief \ref named-templ-param "Named parameter" for setting
58.292 + /// Elevator type with automatic allocation
58.293 + ///
58.294 + /// \ref named-templ-param "Named parameter" for setting Elevator
58.295 + /// type with automatic allocation.
58.296 + /// The Elevator should have standard constructor interface to be
58.297 + /// able to automatically created by the algorithm (i.e. the
58.298 + /// graph and the maximum level should be passed to it).
58.299 + /// However an external elevator object could also be passed to the
58.300 + /// algorithm with the \ref elevator(Elevator&) "elevator()" function
58.301 + /// before calling \ref run() or \ref init().
58.302 + /// \sa SetElevator
58.303 + template <typename T>
58.304 + struct SetStandardElevator
58.305 + : public MaxFractionalMatching<Graph, SetStandardElevatorTraits<T> > {
58.306 + typedef MaxFractionalMatching<Graph,
58.307 + SetStandardElevatorTraits<T> > Create;
58.308 + };
58.309 +
58.310 + /// @}
58.311 +
58.312 + protected:
58.313 +
58.314 + MaxFractionalMatching() {}
58.315 +
58.316 + public:
58.317 +
58.318 + /// \brief Constructor
58.319 + ///
58.320 + /// Constructor.
58.321 + ///
58.322 + MaxFractionalMatching(const Graph &graph, bool allow_loops = true)
58.323 + : _graph(graph), _allow_loops(allow_loops),
58.324 + _local_matching(false), _matching(0),
58.325 + _local_level(false), _level(0), _indeg(0)
58.326 + {}
58.327 +
58.328 + ~MaxFractionalMatching() {
58.329 + destroyStructures();
58.330 + }
58.331 +
58.332 + /// \brief Sets the matching map.
58.333 + ///
58.334 + /// Sets the matching map.
58.335 + /// If you don't use this function before calling \ref run() or
58.336 + /// \ref init(), an instance will be allocated automatically.
58.337 + /// The destructor deallocates this automatically allocated map,
58.338 + /// of course.
58.339 + /// \return <tt>(*this)</tt>
58.340 + MaxFractionalMatching& matchingMap(MatchingMap& map) {
58.341 + if (_local_matching) {
58.342 + delete _matching;
58.343 + _local_matching = false;
58.344 + }
58.345 + _matching = ↦
58.346 + return *this;
58.347 + }
58.348 +
58.349 + /// \brief Sets the elevator used by algorithm.
58.350 + ///
58.351 + /// Sets the elevator used by algorithm.
58.352 + /// If you don't use this function before calling \ref run() or
58.353 + /// \ref init(), an instance will be allocated automatically.
58.354 + /// The destructor deallocates this automatically allocated elevator,
58.355 + /// of course.
58.356 + /// \return <tt>(*this)</tt>
58.357 + MaxFractionalMatching& elevator(Elevator& elevator) {
58.358 + if (_local_level) {
58.359 + delete _level;
58.360 + _local_level = false;
58.361 + }
58.362 + _level = &elevator;
58.363 + return *this;
58.364 + }
58.365 +
58.366 + /// \brief Returns a const reference to the elevator.
58.367 + ///
58.368 + /// Returns a const reference to the elevator.
58.369 + ///
58.370 + /// \pre Either \ref run() or \ref init() must be called before
58.371 + /// using this function.
58.372 + const Elevator& elevator() const {
58.373 + return *_level;
58.374 + }
58.375 +
58.376 + /// \name Execution control
58.377 + /// The simplest way to execute the algorithm is to use one of the
58.378 + /// member functions called \c run(). \n
58.379 + /// If you need more control on the execution, first
58.380 + /// you must call \ref init() and then one variant of the start()
58.381 + /// member.
58.382 +
58.383 + /// @{
58.384 +
58.385 + /// \brief Initializes the internal data structures.
58.386 + ///
58.387 + /// Initializes the internal data structures and sets the initial
58.388 + /// matching.
58.389 + void init() {
58.390 + createStructures();
58.391 +
58.392 + _level->initStart();
58.393 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.394 + _indeg->set(n, 0);
58.395 + _matching->set(n, INVALID);
58.396 + _level->initAddItem(n);
58.397 + }
58.398 + _level->initFinish();
58.399 +
58.400 + _empty_level = _node_num;
58.401 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.402 + for (OutArcIt a(_graph, n); a != INVALID; ++a) {
58.403 + if (_graph.target(a) == n && !_allow_loops) continue;
58.404 + _matching->set(n, a);
58.405 + Node v = _graph.target((*_matching)[n]);
58.406 + _indeg->set(v, (*_indeg)[v] + 1);
58.407 + break;
58.408 + }
58.409 + }
58.410 +
58.411 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.412 + if ((*_indeg)[n] == 0) {
58.413 + _level->activate(n);
58.414 + }
58.415 + }
58.416 + }
58.417 +
58.418 + /// \brief Starts the algorithm and computes a fractional matching
58.419 + ///
58.420 + /// The algorithm computes a maximum fractional matching.
58.421 + ///
58.422 + /// \param postprocess The algorithm computes first a matching
58.423 + /// which is a union of a matching with one value edges, cycles
58.424 + /// with half value edges and even length paths with half value
58.425 + /// edges. If the parameter is true, then after the push-relabel
58.426 + /// algorithm it postprocesses the matching to contain only
58.427 + /// matching edges and half value odd cycles.
58.428 + void start(bool postprocess = true) {
58.429 + Node n;
58.430 + while ((n = _level->highestActive()) != INVALID) {
58.431 + int level = _level->highestActiveLevel();
58.432 + int new_level = _level->maxLevel();
58.433 + for (InArcIt a(_graph, n); a != INVALID; ++a) {
58.434 + Node u = _graph.source(a);
58.435 + if (n == u && !_allow_loops) continue;
58.436 + Node v = _graph.target((*_matching)[u]);
58.437 + if ((*_level)[v] < level) {
58.438 + _indeg->set(v, (*_indeg)[v] - 1);
58.439 + if ((*_indeg)[v] == 0) {
58.440 + _level->activate(v);
58.441 + }
58.442 + _matching->set(u, a);
58.443 + _indeg->set(n, (*_indeg)[n] + 1);
58.444 + _level->deactivate(n);
58.445 + goto no_more_push;
58.446 + } else if (new_level > (*_level)[v]) {
58.447 + new_level = (*_level)[v];
58.448 + }
58.449 + }
58.450 +
58.451 + if (new_level + 1 < _level->maxLevel()) {
58.452 + _level->liftHighestActive(new_level + 1);
58.453 + } else {
58.454 + _level->liftHighestActiveToTop();
58.455 + }
58.456 + if (_level->emptyLevel(level)) {
58.457 + _level->liftToTop(level);
58.458 + }
58.459 + no_more_push:
58.460 + ;
58.461 + }
58.462 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.463 + if ((*_matching)[n] == INVALID) continue;
58.464 + Node u = _graph.target((*_matching)[n]);
58.465 + if ((*_indeg)[u] > 1) {
58.466 + _indeg->set(u, (*_indeg)[u] - 1);
58.467 + _matching->set(n, INVALID);
58.468 + }
58.469 + }
58.470 + if (postprocess) {
58.471 + postprocessing();
58.472 + }
58.473 + }
58.474 +
58.475 + /// \brief Starts the algorithm and computes a perfect fractional
58.476 + /// matching
58.477 + ///
58.478 + /// The algorithm computes a perfect fractional matching. If it
58.479 + /// does not exists, then the algorithm returns false and the
58.480 + /// matching is undefined and the barrier.
58.481 + ///
58.482 + /// \param postprocess The algorithm computes first a matching
58.483 + /// which is a union of a matching with one value edges, cycles
58.484 + /// with half value edges and even length paths with half value
58.485 + /// edges. If the parameter is true, then after the push-relabel
58.486 + /// algorithm it postprocesses the matching to contain only
58.487 + /// matching edges and half value odd cycles.
58.488 + bool startPerfect(bool postprocess = true) {
58.489 + Node n;
58.490 + while ((n = _level->highestActive()) != INVALID) {
58.491 + int level = _level->highestActiveLevel();
58.492 + int new_level = _level->maxLevel();
58.493 + for (InArcIt a(_graph, n); a != INVALID; ++a) {
58.494 + Node u = _graph.source(a);
58.495 + if (n == u && !_allow_loops) continue;
58.496 + Node v = _graph.target((*_matching)[u]);
58.497 + if ((*_level)[v] < level) {
58.498 + _indeg->set(v, (*_indeg)[v] - 1);
58.499 + if ((*_indeg)[v] == 0) {
58.500 + _level->activate(v);
58.501 + }
58.502 + _matching->set(u, a);
58.503 + _indeg->set(n, (*_indeg)[n] + 1);
58.504 + _level->deactivate(n);
58.505 + goto no_more_push;
58.506 + } else if (new_level > (*_level)[v]) {
58.507 + new_level = (*_level)[v];
58.508 + }
58.509 + }
58.510 +
58.511 + if (new_level + 1 < _level->maxLevel()) {
58.512 + _level->liftHighestActive(new_level + 1);
58.513 + } else {
58.514 + _level->liftHighestActiveToTop();
58.515 + _empty_level = _level->maxLevel() - 1;
58.516 + return false;
58.517 + }
58.518 + if (_level->emptyLevel(level)) {
58.519 + _level->liftToTop(level);
58.520 + _empty_level = level;
58.521 + return false;
58.522 + }
58.523 + no_more_push:
58.524 + ;
58.525 + }
58.526 + if (postprocess) {
58.527 + postprocessing();
58.528 + }
58.529 + return true;
58.530 + }
58.531 +
58.532 + /// \brief Runs the algorithm
58.533 + ///
58.534 + /// Just a shortcut for the next code:
58.535 + ///\code
58.536 + /// init();
58.537 + /// start();
58.538 + ///\endcode
58.539 + void run(bool postprocess = true) {
58.540 + init();
58.541 + start(postprocess);
58.542 + }
58.543 +
58.544 + /// \brief Runs the algorithm to find a perfect fractional matching
58.545 + ///
58.546 + /// Just a shortcut for the next code:
58.547 + ///\code
58.548 + /// init();
58.549 + /// startPerfect();
58.550 + ///\endcode
58.551 + bool runPerfect(bool postprocess = true) {
58.552 + init();
58.553 + return startPerfect(postprocess);
58.554 + }
58.555 +
58.556 + ///@}
58.557 +
58.558 + /// \name Query Functions
58.559 + /// The result of the %Matching algorithm can be obtained using these
58.560 + /// functions.\n
58.561 + /// Before the use of these functions,
58.562 + /// either run() or start() must be called.
58.563 + ///@{
58.564 +
58.565 +
58.566 + /// \brief Return the number of covered nodes in the matching.
58.567 + ///
58.568 + /// This function returns the number of covered nodes in the matching.
58.569 + ///
58.570 + /// \pre Either run() or start() must be called before using this function.
58.571 + int matchingSize() const {
58.572 + int num = 0;
58.573 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.574 + if ((*_matching)[n] != INVALID) {
58.575 + ++num;
58.576 + }
58.577 + }
58.578 + return num;
58.579 + }
58.580 +
58.581 + /// \brief Returns a const reference to the matching map.
58.582 + ///
58.583 + /// Returns a const reference to the node map storing the found
58.584 + /// fractional matching. This method can be called after
58.585 + /// running the algorithm.
58.586 + ///
58.587 + /// \pre Either \ref run() or \ref init() must be called before
58.588 + /// using this function.
58.589 + const MatchingMap& matchingMap() const {
58.590 + return *_matching;
58.591 + }
58.592 +
58.593 + /// \brief Return \c true if the given edge is in the matching.
58.594 + ///
58.595 + /// This function returns \c true if the given edge is in the
58.596 + /// found matching. The result is scaled by \ref primalScale
58.597 + /// "primal scale".
58.598 + ///
58.599 + /// \pre Either run() or start() must be called before using this function.
58.600 + int matching(const Edge& edge) const {
58.601 + return (edge == (*_matching)[_graph.u(edge)] ? 1 : 0) +
58.602 + (edge == (*_matching)[_graph.v(edge)] ? 1 : 0);
58.603 + }
58.604 +
58.605 + /// \brief Return the fractional matching arc (or edge) incident
58.606 + /// to the given node.
58.607 + ///
58.608 + /// This function returns one of the fractional matching arc (or
58.609 + /// edge) incident to the given node in the found matching or \c
58.610 + /// INVALID if the node is not covered by the matching or if the
58.611 + /// node is on an odd length cycle then it is the successor edge
58.612 + /// on the cycle.
58.613 + ///
58.614 + /// \pre Either run() or start() must be called before using this function.
58.615 + Arc matching(const Node& node) const {
58.616 + return (*_matching)[node];
58.617 + }
58.618 +
58.619 + /// \brief Returns true if the node is in the barrier
58.620 + ///
58.621 + /// The barrier is a subset of the nodes. If the nodes in the
58.622 + /// barrier have less adjacent nodes than the size of the barrier,
58.623 + /// then at least as much nodes cannot be covered as the
58.624 + /// difference of the two subsets.
58.625 + bool barrier(const Node& node) const {
58.626 + return (*_level)[node] >= _empty_level;
58.627 + }
58.628 +
58.629 + /// @}
58.630 +
58.631 + };
58.632 +
58.633 + /// \ingroup matching
58.634 + ///
58.635 + /// \brief Weighted fractional matching in general graphs
58.636 + ///
58.637 + /// This class provides an efficient implementation of fractional
58.638 + /// matching algorithm. The implementation uses priority queues and
58.639 + /// provides \f$O(nm\log n)\f$ time complexity.
58.640 + ///
58.641 + /// The maximum weighted fractional matching is a relaxation of the
58.642 + /// maximum weighted matching problem where the odd set constraints
58.643 + /// are omitted.
58.644 + /// It can be formulated with the following linear program.
58.645 + /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
58.646 + /// \f[x_e \ge 0\quad \forall e\in E\f]
58.647 + /// \f[\max \sum_{e\in E}x_ew_e\f]
58.648 + /// where \f$\delta(X)\f$ is the set of edges incident to a node in
58.649 + /// \f$X\f$. The result must be the union of a matching with one
58.650 + /// value edges and a set of odd length cycles with half value edges.
58.651 + ///
58.652 + /// The algorithm calculates an optimal fractional matching and a
58.653 + /// proof of the optimality. The solution of the dual problem can be
58.654 + /// used to check the result of the algorithm. The dual linear
58.655 + /// problem is the following.
58.656 + /// \f[ y_u + y_v \ge w_{uv} \quad \forall uv\in E\f]
58.657 + /// \f[y_u \ge 0 \quad \forall u \in V\f]
58.658 + /// \f[\min \sum_{u \in V}y_u \f]
58.659 + ///
58.660 + /// The algorithm can be executed with the run() function.
58.661 + /// After it the matching (the primal solution) and the dual solution
58.662 + /// can be obtained using the query functions.
58.663 + ///
58.664 + /// The primal solution is multiplied by
58.665 + /// \ref MaxWeightedFractionalMatching::primalScale "2".
58.666 + /// If the value type is integer, then the dual
58.667 + /// solution is scaled by
58.668 + /// \ref MaxWeightedFractionalMatching::dualScale "4".
58.669 + ///
58.670 + /// \tparam GR The undirected graph type the algorithm runs on.
58.671 + /// \tparam WM The type edge weight map. The default type is
58.672 + /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
58.673 +#ifdef DOXYGEN
58.674 + template <typename GR, typename WM>
58.675 +#else
58.676 + template <typename GR,
58.677 + typename WM = typename GR::template EdgeMap<int> >
58.678 +#endif
58.679 + class MaxWeightedFractionalMatching {
58.680 + public:
58.681 +
58.682 + /// The graph type of the algorithm
58.683 + typedef GR Graph;
58.684 + /// The type of the edge weight map
58.685 + typedef WM WeightMap;
58.686 + /// The value type of the edge weights
58.687 + typedef typename WeightMap::Value Value;
58.688 +
58.689 + /// The type of the matching map
58.690 + typedef typename Graph::template NodeMap<typename Graph::Arc>
58.691 + MatchingMap;
58.692 +
58.693 + /// \brief Scaling factor for primal solution
58.694 + ///
58.695 + /// Scaling factor for primal solution.
58.696 + static const int primalScale = 2;
58.697 +
58.698 + /// \brief Scaling factor for dual solution
58.699 + ///
58.700 + /// Scaling factor for dual solution. It is equal to 4 or 1
58.701 + /// according to the value type.
58.702 + static const int dualScale =
58.703 + std::numeric_limits<Value>::is_integer ? 4 : 1;
58.704 +
58.705 + private:
58.706 +
58.707 + TEMPLATE_GRAPH_TYPEDEFS(Graph);
58.708 +
58.709 + typedef typename Graph::template NodeMap<Value> NodePotential;
58.710 +
58.711 + const Graph& _graph;
58.712 + const WeightMap& _weight;
58.713 +
58.714 + MatchingMap* _matching;
58.715 + NodePotential* _node_potential;
58.716 +
58.717 + int _node_num;
58.718 + bool _allow_loops;
58.719 +
58.720 + enum Status {
58.721 + EVEN = -1, MATCHED = 0, ODD = 1
58.722 + };
58.723 +
58.724 + typedef typename Graph::template NodeMap<Status> StatusMap;
58.725 + StatusMap* _status;
58.726 +
58.727 + typedef typename Graph::template NodeMap<Arc> PredMap;
58.728 + PredMap* _pred;
58.729 +
58.730 + typedef ExtendFindEnum<IntNodeMap> TreeSet;
58.731 +
58.732 + IntNodeMap *_tree_set_index;
58.733 + TreeSet *_tree_set;
58.734 +
58.735 + IntNodeMap *_delta1_index;
58.736 + BinHeap<Value, IntNodeMap> *_delta1;
58.737 +
58.738 + IntNodeMap *_delta2_index;
58.739 + BinHeap<Value, IntNodeMap> *_delta2;
58.740 +
58.741 + IntEdgeMap *_delta3_index;
58.742 + BinHeap<Value, IntEdgeMap> *_delta3;
58.743 +
58.744 + Value _delta_sum;
58.745 +
58.746 + void createStructures() {
58.747 + _node_num = countNodes(_graph);
58.748 +
58.749 + if (!_matching) {
58.750 + _matching = new MatchingMap(_graph);
58.751 + }
58.752 + if (!_node_potential) {
58.753 + _node_potential = new NodePotential(_graph);
58.754 + }
58.755 + if (!_status) {
58.756 + _status = new StatusMap(_graph);
58.757 + }
58.758 + if (!_pred) {
58.759 + _pred = new PredMap(_graph);
58.760 + }
58.761 + if (!_tree_set) {
58.762 + _tree_set_index = new IntNodeMap(_graph);
58.763 + _tree_set = new TreeSet(*_tree_set_index);
58.764 + }
58.765 + if (!_delta1) {
58.766 + _delta1_index = new IntNodeMap(_graph);
58.767 + _delta1 = new BinHeap<Value, IntNodeMap>(*_delta1_index);
58.768 + }
58.769 + if (!_delta2) {
58.770 + _delta2_index = new IntNodeMap(_graph);
58.771 + _delta2 = new BinHeap<Value, IntNodeMap>(*_delta2_index);
58.772 + }
58.773 + if (!_delta3) {
58.774 + _delta3_index = new IntEdgeMap(_graph);
58.775 + _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
58.776 + }
58.777 + }
58.778 +
58.779 + void destroyStructures() {
58.780 + if (_matching) {
58.781 + delete _matching;
58.782 + }
58.783 + if (_node_potential) {
58.784 + delete _node_potential;
58.785 + }
58.786 + if (_status) {
58.787 + delete _status;
58.788 + }
58.789 + if (_pred) {
58.790 + delete _pred;
58.791 + }
58.792 + if (_tree_set) {
58.793 + delete _tree_set_index;
58.794 + delete _tree_set;
58.795 + }
58.796 + if (_delta1) {
58.797 + delete _delta1_index;
58.798 + delete _delta1;
58.799 + }
58.800 + if (_delta2) {
58.801 + delete _delta2_index;
58.802 + delete _delta2;
58.803 + }
58.804 + if (_delta3) {
58.805 + delete _delta3_index;
58.806 + delete _delta3;
58.807 + }
58.808 + }
58.809 +
58.810 + void matchedToEven(Node node, int tree) {
58.811 + _tree_set->insert(node, tree);
58.812 + _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
58.813 + _delta1->push(node, (*_node_potential)[node]);
58.814 +
58.815 + if (_delta2->state(node) == _delta2->IN_HEAP) {
58.816 + _delta2->erase(node);
58.817 + }
58.818 +
58.819 + for (InArcIt a(_graph, node); a != INVALID; ++a) {
58.820 + Node v = _graph.source(a);
58.821 + Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
58.822 + dualScale * _weight[a];
58.823 + if (node == v) {
58.824 + if (_allow_loops && _graph.direction(a)) {
58.825 + _delta3->push(a, rw / 2);
58.826 + }
58.827 + } else if ((*_status)[v] == EVEN) {
58.828 + _delta3->push(a, rw / 2);
58.829 + } else if ((*_status)[v] == MATCHED) {
58.830 + if (_delta2->state(v) != _delta2->IN_HEAP) {
58.831 + _pred->set(v, a);
58.832 + _delta2->push(v, rw);
58.833 + } else if ((*_delta2)[v] > rw) {
58.834 + _pred->set(v, a);
58.835 + _delta2->decrease(v, rw);
58.836 + }
58.837 + }
58.838 + }
58.839 + }
58.840 +
58.841 + void matchedToOdd(Node node, int tree) {
58.842 + _tree_set->insert(node, tree);
58.843 + _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
58.844 +
58.845 + if (_delta2->state(node) == _delta2->IN_HEAP) {
58.846 + _delta2->erase(node);
58.847 + }
58.848 + }
58.849 +
58.850 + void evenToMatched(Node node, int tree) {
58.851 + _delta1->erase(node);
58.852 + _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
58.853 + Arc min = INVALID;
58.854 + Value minrw = std::numeric_limits<Value>::max();
58.855 + for (InArcIt a(_graph, node); a != INVALID; ++a) {
58.856 + Node v = _graph.source(a);
58.857 + Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
58.858 + dualScale * _weight[a];
58.859 +
58.860 + if (node == v) {
58.861 + if (_allow_loops && _graph.direction(a)) {
58.862 + _delta3->erase(a);
58.863 + }
58.864 + } else if ((*_status)[v] == EVEN) {
58.865 + _delta3->erase(a);
58.866 + if (minrw > rw) {
58.867 + min = _graph.oppositeArc(a);
58.868 + minrw = rw;
58.869 + }
58.870 + } else if ((*_status)[v] == MATCHED) {
58.871 + if ((*_pred)[v] == a) {
58.872 + Arc mina = INVALID;
58.873 + Value minrwa = std::numeric_limits<Value>::max();
58.874 + for (OutArcIt aa(_graph, v); aa != INVALID; ++aa) {
58.875 + Node va = _graph.target(aa);
58.876 + if ((*_status)[va] != EVEN ||
58.877 + _tree_set->find(va) == tree) continue;
58.878 + Value rwa = (*_node_potential)[v] + (*_node_potential)[va] -
58.879 + dualScale * _weight[aa];
58.880 + if (minrwa > rwa) {
58.881 + minrwa = rwa;
58.882 + mina = aa;
58.883 + }
58.884 + }
58.885 + if (mina != INVALID) {
58.886 + _pred->set(v, mina);
58.887 + _delta2->increase(v, minrwa);
58.888 + } else {
58.889 + _pred->set(v, INVALID);
58.890 + _delta2->erase(v);
58.891 + }
58.892 + }
58.893 + }
58.894 + }
58.895 + if (min != INVALID) {
58.896 + _pred->set(node, min);
58.897 + _delta2->push(node, minrw);
58.898 + } else {
58.899 + _pred->set(node, INVALID);
58.900 + }
58.901 + }
58.902 +
58.903 + void oddToMatched(Node node) {
58.904 + _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
58.905 + Arc min = INVALID;
58.906 + Value minrw = std::numeric_limits<Value>::max();
58.907 + for (InArcIt a(_graph, node); a != INVALID; ++a) {
58.908 + Node v = _graph.source(a);
58.909 + if ((*_status)[v] != EVEN) continue;
58.910 + Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
58.911 + dualScale * _weight[a];
58.912 +
58.913 + if (minrw > rw) {
58.914 + min = _graph.oppositeArc(a);
58.915 + minrw = rw;
58.916 + }
58.917 + }
58.918 + if (min != INVALID) {
58.919 + _pred->set(node, min);
58.920 + _delta2->push(node, minrw);
58.921 + } else {
58.922 + _pred->set(node, INVALID);
58.923 + }
58.924 + }
58.925 +
58.926 + void alternatePath(Node even, int tree) {
58.927 + Node odd;
58.928 +
58.929 + _status->set(even, MATCHED);
58.930 + evenToMatched(even, tree);
58.931 +
58.932 + Arc prev = (*_matching)[even];
58.933 + while (prev != INVALID) {
58.934 + odd = _graph.target(prev);
58.935 + even = _graph.target((*_pred)[odd]);
58.936 + _matching->set(odd, (*_pred)[odd]);
58.937 + _status->set(odd, MATCHED);
58.938 + oddToMatched(odd);
58.939 +
58.940 + prev = (*_matching)[even];
58.941 + _status->set(even, MATCHED);
58.942 + _matching->set(even, _graph.oppositeArc((*_matching)[odd]));
58.943 + evenToMatched(even, tree);
58.944 + }
58.945 + }
58.946 +
58.947 + void destroyTree(int tree) {
58.948 + for (typename TreeSet::ItemIt n(*_tree_set, tree); n != INVALID; ++n) {
58.949 + if ((*_status)[n] == EVEN) {
58.950 + _status->set(n, MATCHED);
58.951 + evenToMatched(n, tree);
58.952 + } else if ((*_status)[n] == ODD) {
58.953 + _status->set(n, MATCHED);
58.954 + oddToMatched(n);
58.955 + }
58.956 + }
58.957 + _tree_set->eraseClass(tree);
58.958 + }
58.959 +
58.960 +
58.961 + void unmatchNode(const Node& node) {
58.962 + int tree = _tree_set->find(node);
58.963 +
58.964 + alternatePath(node, tree);
58.965 + destroyTree(tree);
58.966 +
58.967 + _matching->set(node, INVALID);
58.968 + }
58.969 +
58.970 +
58.971 + void augmentOnEdge(const Edge& edge) {
58.972 + Node left = _graph.u(edge);
58.973 + int left_tree = _tree_set->find(left);
58.974 +
58.975 + alternatePath(left, left_tree);
58.976 + destroyTree(left_tree);
58.977 + _matching->set(left, _graph.direct(edge, true));
58.978 +
58.979 + Node right = _graph.v(edge);
58.980 + int right_tree = _tree_set->find(right);
58.981 +
58.982 + alternatePath(right, right_tree);
58.983 + destroyTree(right_tree);
58.984 + _matching->set(right, _graph.direct(edge, false));
58.985 + }
58.986 +
58.987 + void augmentOnArc(const Arc& arc) {
58.988 + Node left = _graph.source(arc);
58.989 + _status->set(left, MATCHED);
58.990 + _matching->set(left, arc);
58.991 + _pred->set(left, arc);
58.992 +
58.993 + Node right = _graph.target(arc);
58.994 + int right_tree = _tree_set->find(right);
58.995 +
58.996 + alternatePath(right, right_tree);
58.997 + destroyTree(right_tree);
58.998 + _matching->set(right, _graph.oppositeArc(arc));
58.999 + }
58.1000 +
58.1001 + void extendOnArc(const Arc& arc) {
58.1002 + Node base = _graph.target(arc);
58.1003 + int tree = _tree_set->find(base);
58.1004 +
58.1005 + Node odd = _graph.source(arc);
58.1006 + _tree_set->insert(odd, tree);
58.1007 + _status->set(odd, ODD);
58.1008 + matchedToOdd(odd, tree);
58.1009 + _pred->set(odd, arc);
58.1010 +
58.1011 + Node even = _graph.target((*_matching)[odd]);
58.1012 + _tree_set->insert(even, tree);
58.1013 + _status->set(even, EVEN);
58.1014 + matchedToEven(even, tree);
58.1015 + }
58.1016 +
58.1017 + void cycleOnEdge(const Edge& edge, int tree) {
58.1018 + Node nca = INVALID;
58.1019 + std::vector<Node> left_path, right_path;
58.1020 +
58.1021 + {
58.1022 + std::set<Node> left_set, right_set;
58.1023 + Node left = _graph.u(edge);
58.1024 + left_path.push_back(left);
58.1025 + left_set.insert(left);
58.1026 +
58.1027 + Node right = _graph.v(edge);
58.1028 + right_path.push_back(right);
58.1029 + right_set.insert(right);
58.1030 +
58.1031 + while (true) {
58.1032 +
58.1033 + if (left_set.find(right) != left_set.end()) {
58.1034 + nca = right;
58.1035 + break;
58.1036 + }
58.1037 +
58.1038 + if ((*_matching)[left] == INVALID) break;
58.1039 +
58.1040 + left = _graph.target((*_matching)[left]);
58.1041 + left_path.push_back(left);
58.1042 + left = _graph.target((*_pred)[left]);
58.1043 + left_path.push_back(left);
58.1044 +
58.1045 + left_set.insert(left);
58.1046 +
58.1047 + if (right_set.find(left) != right_set.end()) {
58.1048 + nca = left;
58.1049 + break;
58.1050 + }
58.1051 +
58.1052 + if ((*_matching)[right] == INVALID) break;
58.1053 +
58.1054 + right = _graph.target((*_matching)[right]);
58.1055 + right_path.push_back(right);
58.1056 + right = _graph.target((*_pred)[right]);
58.1057 + right_path.push_back(right);
58.1058 +
58.1059 + right_set.insert(right);
58.1060 +
58.1061 + }
58.1062 +
58.1063 + if (nca == INVALID) {
58.1064 + if ((*_matching)[left] == INVALID) {
58.1065 + nca = right;
58.1066 + while (left_set.find(nca) == left_set.end()) {
58.1067 + nca = _graph.target((*_matching)[nca]);
58.1068 + right_path.push_back(nca);
58.1069 + nca = _graph.target((*_pred)[nca]);
58.1070 + right_path.push_back(nca);
58.1071 + }
58.1072 + } else {
58.1073 + nca = left;
58.1074 + while (right_set.find(nca) == right_set.end()) {
58.1075 + nca = _graph.target((*_matching)[nca]);
58.1076 + left_path.push_back(nca);
58.1077 + nca = _graph.target((*_pred)[nca]);
58.1078 + left_path.push_back(nca);
58.1079 + }
58.1080 + }
58.1081 + }
58.1082 + }
58.1083 +
58.1084 + alternatePath(nca, tree);
58.1085 + Arc prev;
58.1086 +
58.1087 + prev = _graph.direct(edge, true);
58.1088 + for (int i = 0; left_path[i] != nca; i += 2) {
58.1089 + _matching->set(left_path[i], prev);
58.1090 + _status->set(left_path[i], MATCHED);
58.1091 + evenToMatched(left_path[i], tree);
58.1092 +
58.1093 + prev = _graph.oppositeArc((*_pred)[left_path[i + 1]]);
58.1094 + _status->set(left_path[i + 1], MATCHED);
58.1095 + oddToMatched(left_path[i + 1]);
58.1096 + }
58.1097 + _matching->set(nca, prev);
58.1098 +
58.1099 + for (int i = 0; right_path[i] != nca; i += 2) {
58.1100 + _status->set(right_path[i], MATCHED);
58.1101 + evenToMatched(right_path[i], tree);
58.1102 +
58.1103 + _matching->set(right_path[i + 1], (*_pred)[right_path[i + 1]]);
58.1104 + _status->set(right_path[i + 1], MATCHED);
58.1105 + oddToMatched(right_path[i + 1]);
58.1106 + }
58.1107 +
58.1108 + destroyTree(tree);
58.1109 + }
58.1110 +
58.1111 + void extractCycle(const Arc &arc) {
58.1112 + Node left = _graph.source(arc);
58.1113 + Node odd = _graph.target((*_matching)[left]);
58.1114 + Arc prev;
58.1115 + while (odd != left) {
58.1116 + Node even = _graph.target((*_matching)[odd]);
58.1117 + prev = (*_matching)[odd];
58.1118 + odd = _graph.target((*_matching)[even]);
58.1119 + _matching->set(even, _graph.oppositeArc(prev));
58.1120 + }
58.1121 + _matching->set(left, arc);
58.1122 +
58.1123 + Node right = _graph.target(arc);
58.1124 + int right_tree = _tree_set->find(right);
58.1125 + alternatePath(right, right_tree);
58.1126 + destroyTree(right_tree);
58.1127 + _matching->set(right, _graph.oppositeArc(arc));
58.1128 + }
58.1129 +
58.1130 + public:
58.1131 +
58.1132 + /// \brief Constructor
58.1133 + ///
58.1134 + /// Constructor.
58.1135 + MaxWeightedFractionalMatching(const Graph& graph, const WeightMap& weight,
58.1136 + bool allow_loops = true)
58.1137 + : _graph(graph), _weight(weight), _matching(0),
58.1138 + _node_potential(0), _node_num(0), _allow_loops(allow_loops),
58.1139 + _status(0), _pred(0),
58.1140 + _tree_set_index(0), _tree_set(0),
58.1141 +
58.1142 + _delta1_index(0), _delta1(0),
58.1143 + _delta2_index(0), _delta2(0),
58.1144 + _delta3_index(0), _delta3(0),
58.1145 +
58.1146 + _delta_sum() {}
58.1147 +
58.1148 + ~MaxWeightedFractionalMatching() {
58.1149 + destroyStructures();
58.1150 + }
58.1151 +
58.1152 + /// \name Execution Control
58.1153 + /// The simplest way to execute the algorithm is to use the
58.1154 + /// \ref run() member function.
58.1155 +
58.1156 + ///@{
58.1157 +
58.1158 + /// \brief Initialize the algorithm
58.1159 + ///
58.1160 + /// This function initializes the algorithm.
58.1161 + void init() {
58.1162 + createStructures();
58.1163 +
58.1164 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.1165 + (*_delta1_index)[n] = _delta1->PRE_HEAP;
58.1166 + (*_delta2_index)[n] = _delta2->PRE_HEAP;
58.1167 + }
58.1168 + for (EdgeIt e(_graph); e != INVALID; ++e) {
58.1169 + (*_delta3_index)[e] = _delta3->PRE_HEAP;
58.1170 + }
58.1171 +
58.1172 + _delta1->clear();
58.1173 + _delta2->clear();
58.1174 + _delta3->clear();
58.1175 + _tree_set->clear();
58.1176 +
58.1177 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.1178 + Value max = 0;
58.1179 + for (OutArcIt e(_graph, n); e != INVALID; ++e) {
58.1180 + if (_graph.target(e) == n && !_allow_loops) continue;
58.1181 + if ((dualScale * _weight[e]) / 2 > max) {
58.1182 + max = (dualScale * _weight[e]) / 2;
58.1183 + }
58.1184 + }
58.1185 + _node_potential->set(n, max);
58.1186 + _delta1->push(n, max);
58.1187 +
58.1188 + _tree_set->insert(n);
58.1189 +
58.1190 + _matching->set(n, INVALID);
58.1191 + _status->set(n, EVEN);
58.1192 + }
58.1193 +
58.1194 + for (EdgeIt e(_graph); e != INVALID; ++e) {
58.1195 + Node left = _graph.u(e);
58.1196 + Node right = _graph.v(e);
58.1197 + if (left == right && !_allow_loops) continue;
58.1198 + _delta3->push(e, ((*_node_potential)[left] +
58.1199 + (*_node_potential)[right] -
58.1200 + dualScale * _weight[e]) / 2);
58.1201 + }
58.1202 + }
58.1203 +
58.1204 + /// \brief Start the algorithm
58.1205 + ///
58.1206 + /// This function starts the algorithm.
58.1207 + ///
58.1208 + /// \pre \ref init() must be called before using this function.
58.1209 + void start() {
58.1210 + enum OpType {
58.1211 + D1, D2, D3
58.1212 + };
58.1213 +
58.1214 + int unmatched = _node_num;
58.1215 + while (unmatched > 0) {
58.1216 + Value d1 = !_delta1->empty() ?
58.1217 + _delta1->prio() : std::numeric_limits<Value>::max();
58.1218 +
58.1219 + Value d2 = !_delta2->empty() ?
58.1220 + _delta2->prio() : std::numeric_limits<Value>::max();
58.1221 +
58.1222 + Value d3 = !_delta3->empty() ?
58.1223 + _delta3->prio() : std::numeric_limits<Value>::max();
58.1224 +
58.1225 + _delta_sum = d3; OpType ot = D3;
58.1226 + if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
58.1227 + if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
58.1228 +
58.1229 + switch (ot) {
58.1230 + case D1:
58.1231 + {
58.1232 + Node n = _delta1->top();
58.1233 + unmatchNode(n);
58.1234 + --unmatched;
58.1235 + }
58.1236 + break;
58.1237 + case D2:
58.1238 + {
58.1239 + Node n = _delta2->top();
58.1240 + Arc a = (*_pred)[n];
58.1241 + if ((*_matching)[n] == INVALID) {
58.1242 + augmentOnArc(a);
58.1243 + --unmatched;
58.1244 + } else {
58.1245 + Node v = _graph.target((*_matching)[n]);
58.1246 + if ((*_matching)[n] !=
58.1247 + _graph.oppositeArc((*_matching)[v])) {
58.1248 + extractCycle(a);
58.1249 + --unmatched;
58.1250 + } else {
58.1251 + extendOnArc(a);
58.1252 + }
58.1253 + }
58.1254 + } break;
58.1255 + case D3:
58.1256 + {
58.1257 + Edge e = _delta3->top();
58.1258 +
58.1259 + Node left = _graph.u(e);
58.1260 + Node right = _graph.v(e);
58.1261 +
58.1262 + int left_tree = _tree_set->find(left);
58.1263 + int right_tree = _tree_set->find(right);
58.1264 +
58.1265 + if (left_tree == right_tree) {
58.1266 + cycleOnEdge(e, left_tree);
58.1267 + --unmatched;
58.1268 + } else {
58.1269 + augmentOnEdge(e);
58.1270 + unmatched -= 2;
58.1271 + }
58.1272 + } break;
58.1273 + }
58.1274 + }
58.1275 + }
58.1276 +
58.1277 + /// \brief Run the algorithm.
58.1278 + ///
58.1279 + /// This method runs the \c %MaxWeightedFractionalMatching algorithm.
58.1280 + ///
58.1281 + /// \note mwfm.run() is just a shortcut of the following code.
58.1282 + /// \code
58.1283 + /// mwfm.init();
58.1284 + /// mwfm.start();
58.1285 + /// \endcode
58.1286 + void run() {
58.1287 + init();
58.1288 + start();
58.1289 + }
58.1290 +
58.1291 + /// @}
58.1292 +
58.1293 + /// \name Primal Solution
58.1294 + /// Functions to get the primal solution, i.e. the maximum weighted
58.1295 + /// matching.\n
58.1296 + /// Either \ref run() or \ref start() function should be called before
58.1297 + /// using them.
58.1298 +
58.1299 + /// @{
58.1300 +
58.1301 + /// \brief Return the weight of the matching.
58.1302 + ///
58.1303 + /// This function returns the weight of the found matching. This
58.1304 + /// value is scaled by \ref primalScale "primal scale".
58.1305 + ///
58.1306 + /// \pre Either run() or start() must be called before using this function.
58.1307 + Value matchingWeight() const {
58.1308 + Value sum = 0;
58.1309 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.1310 + if ((*_matching)[n] != INVALID) {
58.1311 + sum += _weight[(*_matching)[n]];
58.1312 + }
58.1313 + }
58.1314 + return sum * primalScale / 2;
58.1315 + }
58.1316 +
58.1317 + /// \brief Return the number of covered nodes in the matching.
58.1318 + ///
58.1319 + /// This function returns the number of covered nodes in the matching.
58.1320 + ///
58.1321 + /// \pre Either run() or start() must be called before using this function.
58.1322 + int matchingSize() const {
58.1323 + int num = 0;
58.1324 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.1325 + if ((*_matching)[n] != INVALID) {
58.1326 + ++num;
58.1327 + }
58.1328 + }
58.1329 + return num;
58.1330 + }
58.1331 +
58.1332 + /// \brief Return \c true if the given edge is in the matching.
58.1333 + ///
58.1334 + /// This function returns \c true if the given edge is in the
58.1335 + /// found matching. The result is scaled by \ref primalScale
58.1336 + /// "primal scale".
58.1337 + ///
58.1338 + /// \pre Either run() or start() must be called before using this function.
58.1339 + int matching(const Edge& edge) const {
58.1340 + return (edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
58.1341 + + (edge == (*_matching)[_graph.v(edge)] ? 1 : 0);
58.1342 + }
58.1343 +
58.1344 + /// \brief Return the fractional matching arc (or edge) incident
58.1345 + /// to the given node.
58.1346 + ///
58.1347 + /// This function returns one of the fractional matching arc (or
58.1348 + /// edge) incident to the given node in the found matching or \c
58.1349 + /// INVALID if the node is not covered by the matching or if the
58.1350 + /// node is on an odd length cycle then it is the successor edge
58.1351 + /// on the cycle.
58.1352 + ///
58.1353 + /// \pre Either run() or start() must be called before using this function.
58.1354 + Arc matching(const Node& node) const {
58.1355 + return (*_matching)[node];
58.1356 + }
58.1357 +
58.1358 + /// \brief Return a const reference to the matching map.
58.1359 + ///
58.1360 + /// This function returns a const reference to a node map that stores
58.1361 + /// the matching arc (or edge) incident to each node.
58.1362 + const MatchingMap& matchingMap() const {
58.1363 + return *_matching;
58.1364 + }
58.1365 +
58.1366 + /// @}
58.1367 +
58.1368 + /// \name Dual Solution
58.1369 + /// Functions to get the dual solution.\n
58.1370 + /// Either \ref run() or \ref start() function should be called before
58.1371 + /// using them.
58.1372 +
58.1373 + /// @{
58.1374 +
58.1375 + /// \brief Return the value of the dual solution.
58.1376 + ///
58.1377 + /// This function returns the value of the dual solution.
58.1378 + /// It should be equal to the primal value scaled by \ref dualScale
58.1379 + /// "dual scale".
58.1380 + ///
58.1381 + /// \pre Either run() or start() must be called before using this function.
58.1382 + Value dualValue() const {
58.1383 + Value sum = 0;
58.1384 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.1385 + sum += nodeValue(n);
58.1386 + }
58.1387 + return sum;
58.1388 + }
58.1389 +
58.1390 + /// \brief Return the dual value (potential) of the given node.
58.1391 + ///
58.1392 + /// This function returns the dual value (potential) of the given node.
58.1393 + ///
58.1394 + /// \pre Either run() or start() must be called before using this function.
58.1395 + Value nodeValue(const Node& n) const {
58.1396 + return (*_node_potential)[n];
58.1397 + }
58.1398 +
58.1399 + /// @}
58.1400 +
58.1401 + };
58.1402 +
58.1403 + /// \ingroup matching
58.1404 + ///
58.1405 + /// \brief Weighted fractional perfect matching in general graphs
58.1406 + ///
58.1407 + /// This class provides an efficient implementation of fractional
58.1408 + /// matching algorithm. The implementation uses priority queues and
58.1409 + /// provides \f$O(nm\log n)\f$ time complexity.
58.1410 + ///
58.1411 + /// The maximum weighted fractional perfect matching is a relaxation
58.1412 + /// of the maximum weighted perfect matching problem where the odd
58.1413 + /// set constraints are omitted.
58.1414 + /// It can be formulated with the following linear program.
58.1415 + /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
58.1416 + /// \f[x_e \ge 0\quad \forall e\in E\f]
58.1417 + /// \f[\max \sum_{e\in E}x_ew_e\f]
58.1418 + /// where \f$\delta(X)\f$ is the set of edges incident to a node in
58.1419 + /// \f$X\f$. The result must be the union of a matching with one
58.1420 + /// value edges and a set of odd length cycles with half value edges.
58.1421 + ///
58.1422 + /// The algorithm calculates an optimal fractional matching and a
58.1423 + /// proof of the optimality. The solution of the dual problem can be
58.1424 + /// used to check the result of the algorithm. The dual linear
58.1425 + /// problem is the following.
58.1426 + /// \f[ y_u + y_v \ge w_{uv} \quad \forall uv\in E\f]
58.1427 + /// \f[\min \sum_{u \in V}y_u \f]
58.1428 + ///
58.1429 + /// The algorithm can be executed with the run() function.
58.1430 + /// After it the matching (the primal solution) and the dual solution
58.1431 + /// can be obtained using the query functions.
58.1432 + ///
58.1433 + /// The primal solution is multiplied by
58.1434 + /// \ref MaxWeightedPerfectFractionalMatching::primalScale "2".
58.1435 + /// If the value type is integer, then the dual
58.1436 + /// solution is scaled by
58.1437 + /// \ref MaxWeightedPerfectFractionalMatching::dualScale "4".
58.1438 + ///
58.1439 + /// \tparam GR The undirected graph type the algorithm runs on.
58.1440 + /// \tparam WM The type edge weight map. The default type is
58.1441 + /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
58.1442 +#ifdef DOXYGEN
58.1443 + template <typename GR, typename WM>
58.1444 +#else
58.1445 + template <typename GR,
58.1446 + typename WM = typename GR::template EdgeMap<int> >
58.1447 +#endif
58.1448 + class MaxWeightedPerfectFractionalMatching {
58.1449 + public:
58.1450 +
58.1451 + /// The graph type of the algorithm
58.1452 + typedef GR Graph;
58.1453 + /// The type of the edge weight map
58.1454 + typedef WM WeightMap;
58.1455 + /// The value type of the edge weights
58.1456 + typedef typename WeightMap::Value Value;
58.1457 +
58.1458 + /// The type of the matching map
58.1459 + typedef typename Graph::template NodeMap<typename Graph::Arc>
58.1460 + MatchingMap;
58.1461 +
58.1462 + /// \brief Scaling factor for primal solution
58.1463 + ///
58.1464 + /// Scaling factor for primal solution.
58.1465 + static const int primalScale = 2;
58.1466 +
58.1467 + /// \brief Scaling factor for dual solution
58.1468 + ///
58.1469 + /// Scaling factor for dual solution. It is equal to 4 or 1
58.1470 + /// according to the value type.
58.1471 + static const int dualScale =
58.1472 + std::numeric_limits<Value>::is_integer ? 4 : 1;
58.1473 +
58.1474 + private:
58.1475 +
58.1476 + TEMPLATE_GRAPH_TYPEDEFS(Graph);
58.1477 +
58.1478 + typedef typename Graph::template NodeMap<Value> NodePotential;
58.1479 +
58.1480 + const Graph& _graph;
58.1481 + const WeightMap& _weight;
58.1482 +
58.1483 + MatchingMap* _matching;
58.1484 + NodePotential* _node_potential;
58.1485 +
58.1486 + int _node_num;
58.1487 + bool _allow_loops;
58.1488 +
58.1489 + enum Status {
58.1490 + EVEN = -1, MATCHED = 0, ODD = 1
58.1491 + };
58.1492 +
58.1493 + typedef typename Graph::template NodeMap<Status> StatusMap;
58.1494 + StatusMap* _status;
58.1495 +
58.1496 + typedef typename Graph::template NodeMap<Arc> PredMap;
58.1497 + PredMap* _pred;
58.1498 +
58.1499 + typedef ExtendFindEnum<IntNodeMap> TreeSet;
58.1500 +
58.1501 + IntNodeMap *_tree_set_index;
58.1502 + TreeSet *_tree_set;
58.1503 +
58.1504 + IntNodeMap *_delta2_index;
58.1505 + BinHeap<Value, IntNodeMap> *_delta2;
58.1506 +
58.1507 + IntEdgeMap *_delta3_index;
58.1508 + BinHeap<Value, IntEdgeMap> *_delta3;
58.1509 +
58.1510 + Value _delta_sum;
58.1511 +
58.1512 + void createStructures() {
58.1513 + _node_num = countNodes(_graph);
58.1514 +
58.1515 + if (!_matching) {
58.1516 + _matching = new MatchingMap(_graph);
58.1517 + }
58.1518 + if (!_node_potential) {
58.1519 + _node_potential = new NodePotential(_graph);
58.1520 + }
58.1521 + if (!_status) {
58.1522 + _status = new StatusMap(_graph);
58.1523 + }
58.1524 + if (!_pred) {
58.1525 + _pred = new PredMap(_graph);
58.1526 + }
58.1527 + if (!_tree_set) {
58.1528 + _tree_set_index = new IntNodeMap(_graph);
58.1529 + _tree_set = new TreeSet(*_tree_set_index);
58.1530 + }
58.1531 + if (!_delta2) {
58.1532 + _delta2_index = new IntNodeMap(_graph);
58.1533 + _delta2 = new BinHeap<Value, IntNodeMap>(*_delta2_index);
58.1534 + }
58.1535 + if (!_delta3) {
58.1536 + _delta3_index = new IntEdgeMap(_graph);
58.1537 + _delta3 = new BinHeap<Value, IntEdgeMap>(*_delta3_index);
58.1538 + }
58.1539 + }
58.1540 +
58.1541 + void destroyStructures() {
58.1542 + if (_matching) {
58.1543 + delete _matching;
58.1544 + }
58.1545 + if (_node_potential) {
58.1546 + delete _node_potential;
58.1547 + }
58.1548 + if (_status) {
58.1549 + delete _status;
58.1550 + }
58.1551 + if (_pred) {
58.1552 + delete _pred;
58.1553 + }
58.1554 + if (_tree_set) {
58.1555 + delete _tree_set_index;
58.1556 + delete _tree_set;
58.1557 + }
58.1558 + if (_delta2) {
58.1559 + delete _delta2_index;
58.1560 + delete _delta2;
58.1561 + }
58.1562 + if (_delta3) {
58.1563 + delete _delta3_index;
58.1564 + delete _delta3;
58.1565 + }
58.1566 + }
58.1567 +
58.1568 + void matchedToEven(Node node, int tree) {
58.1569 + _tree_set->insert(node, tree);
58.1570 + _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
58.1571 +
58.1572 + if (_delta2->state(node) == _delta2->IN_HEAP) {
58.1573 + _delta2->erase(node);
58.1574 + }
58.1575 +
58.1576 + for (InArcIt a(_graph, node); a != INVALID; ++a) {
58.1577 + Node v = _graph.source(a);
58.1578 + Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
58.1579 + dualScale * _weight[a];
58.1580 + if (node == v) {
58.1581 + if (_allow_loops && _graph.direction(a)) {
58.1582 + _delta3->push(a, rw / 2);
58.1583 + }
58.1584 + } else if ((*_status)[v] == EVEN) {
58.1585 + _delta3->push(a, rw / 2);
58.1586 + } else if ((*_status)[v] == MATCHED) {
58.1587 + if (_delta2->state(v) != _delta2->IN_HEAP) {
58.1588 + _pred->set(v, a);
58.1589 + _delta2->push(v, rw);
58.1590 + } else if ((*_delta2)[v] > rw) {
58.1591 + _pred->set(v, a);
58.1592 + _delta2->decrease(v, rw);
58.1593 + }
58.1594 + }
58.1595 + }
58.1596 + }
58.1597 +
58.1598 + void matchedToOdd(Node node, int tree) {
58.1599 + _tree_set->insert(node, tree);
58.1600 + _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
58.1601 +
58.1602 + if (_delta2->state(node) == _delta2->IN_HEAP) {
58.1603 + _delta2->erase(node);
58.1604 + }
58.1605 + }
58.1606 +
58.1607 + void evenToMatched(Node node, int tree) {
58.1608 + _node_potential->set(node, (*_node_potential)[node] - _delta_sum);
58.1609 + Arc min = INVALID;
58.1610 + Value minrw = std::numeric_limits<Value>::max();
58.1611 + for (InArcIt a(_graph, node); a != INVALID; ++a) {
58.1612 + Node v = _graph.source(a);
58.1613 + Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
58.1614 + dualScale * _weight[a];
58.1615 +
58.1616 + if (node == v) {
58.1617 + if (_allow_loops && _graph.direction(a)) {
58.1618 + _delta3->erase(a);
58.1619 + }
58.1620 + } else if ((*_status)[v] == EVEN) {
58.1621 + _delta3->erase(a);
58.1622 + if (minrw > rw) {
58.1623 + min = _graph.oppositeArc(a);
58.1624 + minrw = rw;
58.1625 + }
58.1626 + } else if ((*_status)[v] == MATCHED) {
58.1627 + if ((*_pred)[v] == a) {
58.1628 + Arc mina = INVALID;
58.1629 + Value minrwa = std::numeric_limits<Value>::max();
58.1630 + for (OutArcIt aa(_graph, v); aa != INVALID; ++aa) {
58.1631 + Node va = _graph.target(aa);
58.1632 + if ((*_status)[va] != EVEN ||
58.1633 + _tree_set->find(va) == tree) continue;
58.1634 + Value rwa = (*_node_potential)[v] + (*_node_potential)[va] -
58.1635 + dualScale * _weight[aa];
58.1636 + if (minrwa > rwa) {
58.1637 + minrwa = rwa;
58.1638 + mina = aa;
58.1639 + }
58.1640 + }
58.1641 + if (mina != INVALID) {
58.1642 + _pred->set(v, mina);
58.1643 + _delta2->increase(v, minrwa);
58.1644 + } else {
58.1645 + _pred->set(v, INVALID);
58.1646 + _delta2->erase(v);
58.1647 + }
58.1648 + }
58.1649 + }
58.1650 + }
58.1651 + if (min != INVALID) {
58.1652 + _pred->set(node, min);
58.1653 + _delta2->push(node, minrw);
58.1654 + } else {
58.1655 + _pred->set(node, INVALID);
58.1656 + }
58.1657 + }
58.1658 +
58.1659 + void oddToMatched(Node node) {
58.1660 + _node_potential->set(node, (*_node_potential)[node] + _delta_sum);
58.1661 + Arc min = INVALID;
58.1662 + Value minrw = std::numeric_limits<Value>::max();
58.1663 + for (InArcIt a(_graph, node); a != INVALID; ++a) {
58.1664 + Node v = _graph.source(a);
58.1665 + if ((*_status)[v] != EVEN) continue;
58.1666 + Value rw = (*_node_potential)[node] + (*_node_potential)[v] -
58.1667 + dualScale * _weight[a];
58.1668 +
58.1669 + if (minrw > rw) {
58.1670 + min = _graph.oppositeArc(a);
58.1671 + minrw = rw;
58.1672 + }
58.1673 + }
58.1674 + if (min != INVALID) {
58.1675 + _pred->set(node, min);
58.1676 + _delta2->push(node, minrw);
58.1677 + } else {
58.1678 + _pred->set(node, INVALID);
58.1679 + }
58.1680 + }
58.1681 +
58.1682 + void alternatePath(Node even, int tree) {
58.1683 + Node odd;
58.1684 +
58.1685 + _status->set(even, MATCHED);
58.1686 + evenToMatched(even, tree);
58.1687 +
58.1688 + Arc prev = (*_matching)[even];
58.1689 + while (prev != INVALID) {
58.1690 + odd = _graph.target(prev);
58.1691 + even = _graph.target((*_pred)[odd]);
58.1692 + _matching->set(odd, (*_pred)[odd]);
58.1693 + _status->set(odd, MATCHED);
58.1694 + oddToMatched(odd);
58.1695 +
58.1696 + prev = (*_matching)[even];
58.1697 + _status->set(even, MATCHED);
58.1698 + _matching->set(even, _graph.oppositeArc((*_matching)[odd]));
58.1699 + evenToMatched(even, tree);
58.1700 + }
58.1701 + }
58.1702 +
58.1703 + void destroyTree(int tree) {
58.1704 + for (typename TreeSet::ItemIt n(*_tree_set, tree); n != INVALID; ++n) {
58.1705 + if ((*_status)[n] == EVEN) {
58.1706 + _status->set(n, MATCHED);
58.1707 + evenToMatched(n, tree);
58.1708 + } else if ((*_status)[n] == ODD) {
58.1709 + _status->set(n, MATCHED);
58.1710 + oddToMatched(n);
58.1711 + }
58.1712 + }
58.1713 + _tree_set->eraseClass(tree);
58.1714 + }
58.1715 +
58.1716 + void augmentOnEdge(const Edge& edge) {
58.1717 + Node left = _graph.u(edge);
58.1718 + int left_tree = _tree_set->find(left);
58.1719 +
58.1720 + alternatePath(left, left_tree);
58.1721 + destroyTree(left_tree);
58.1722 + _matching->set(left, _graph.direct(edge, true));
58.1723 +
58.1724 + Node right = _graph.v(edge);
58.1725 + int right_tree = _tree_set->find(right);
58.1726 +
58.1727 + alternatePath(right, right_tree);
58.1728 + destroyTree(right_tree);
58.1729 + _matching->set(right, _graph.direct(edge, false));
58.1730 + }
58.1731 +
58.1732 + void augmentOnArc(const Arc& arc) {
58.1733 + Node left = _graph.source(arc);
58.1734 + _status->set(left, MATCHED);
58.1735 + _matching->set(left, arc);
58.1736 + _pred->set(left, arc);
58.1737 +
58.1738 + Node right = _graph.target(arc);
58.1739 + int right_tree = _tree_set->find(right);
58.1740 +
58.1741 + alternatePath(right, right_tree);
58.1742 + destroyTree(right_tree);
58.1743 + _matching->set(right, _graph.oppositeArc(arc));
58.1744 + }
58.1745 +
58.1746 + void extendOnArc(const Arc& arc) {
58.1747 + Node base = _graph.target(arc);
58.1748 + int tree = _tree_set->find(base);
58.1749 +
58.1750 + Node odd = _graph.source(arc);
58.1751 + _tree_set->insert(odd, tree);
58.1752 + _status->set(odd, ODD);
58.1753 + matchedToOdd(odd, tree);
58.1754 + _pred->set(odd, arc);
58.1755 +
58.1756 + Node even = _graph.target((*_matching)[odd]);
58.1757 + _tree_set->insert(even, tree);
58.1758 + _status->set(even, EVEN);
58.1759 + matchedToEven(even, tree);
58.1760 + }
58.1761 +
58.1762 + void cycleOnEdge(const Edge& edge, int tree) {
58.1763 + Node nca = INVALID;
58.1764 + std::vector<Node> left_path, right_path;
58.1765 +
58.1766 + {
58.1767 + std::set<Node> left_set, right_set;
58.1768 + Node left = _graph.u(edge);
58.1769 + left_path.push_back(left);
58.1770 + left_set.insert(left);
58.1771 +
58.1772 + Node right = _graph.v(edge);
58.1773 + right_path.push_back(right);
58.1774 + right_set.insert(right);
58.1775 +
58.1776 + while (true) {
58.1777 +
58.1778 + if (left_set.find(right) != left_set.end()) {
58.1779 + nca = right;
58.1780 + break;
58.1781 + }
58.1782 +
58.1783 + if ((*_matching)[left] == INVALID) break;
58.1784 +
58.1785 + left = _graph.target((*_matching)[left]);
58.1786 + left_path.push_back(left);
58.1787 + left = _graph.target((*_pred)[left]);
58.1788 + left_path.push_back(left);
58.1789 +
58.1790 + left_set.insert(left);
58.1791 +
58.1792 + if (right_set.find(left) != right_set.end()) {
58.1793 + nca = left;
58.1794 + break;
58.1795 + }
58.1796 +
58.1797 + if ((*_matching)[right] == INVALID) break;
58.1798 +
58.1799 + right = _graph.target((*_matching)[right]);
58.1800 + right_path.push_back(right);
58.1801 + right = _graph.target((*_pred)[right]);
58.1802 + right_path.push_back(right);
58.1803 +
58.1804 + right_set.insert(right);
58.1805 +
58.1806 + }
58.1807 +
58.1808 + if (nca == INVALID) {
58.1809 + if ((*_matching)[left] == INVALID) {
58.1810 + nca = right;
58.1811 + while (left_set.find(nca) == left_set.end()) {
58.1812 + nca = _graph.target((*_matching)[nca]);
58.1813 + right_path.push_back(nca);
58.1814 + nca = _graph.target((*_pred)[nca]);
58.1815 + right_path.push_back(nca);
58.1816 + }
58.1817 + } else {
58.1818 + nca = left;
58.1819 + while (right_set.find(nca) == right_set.end()) {
58.1820 + nca = _graph.target((*_matching)[nca]);
58.1821 + left_path.push_back(nca);
58.1822 + nca = _graph.target((*_pred)[nca]);
58.1823 + left_path.push_back(nca);
58.1824 + }
58.1825 + }
58.1826 + }
58.1827 + }
58.1828 +
58.1829 + alternatePath(nca, tree);
58.1830 + Arc prev;
58.1831 +
58.1832 + prev = _graph.direct(edge, true);
58.1833 + for (int i = 0; left_path[i] != nca; i += 2) {
58.1834 + _matching->set(left_path[i], prev);
58.1835 + _status->set(left_path[i], MATCHED);
58.1836 + evenToMatched(left_path[i], tree);
58.1837 +
58.1838 + prev = _graph.oppositeArc((*_pred)[left_path[i + 1]]);
58.1839 + _status->set(left_path[i + 1], MATCHED);
58.1840 + oddToMatched(left_path[i + 1]);
58.1841 + }
58.1842 + _matching->set(nca, prev);
58.1843 +
58.1844 + for (int i = 0; right_path[i] != nca; i += 2) {
58.1845 + _status->set(right_path[i], MATCHED);
58.1846 + evenToMatched(right_path[i], tree);
58.1847 +
58.1848 + _matching->set(right_path[i + 1], (*_pred)[right_path[i + 1]]);
58.1849 + _status->set(right_path[i + 1], MATCHED);
58.1850 + oddToMatched(right_path[i + 1]);
58.1851 + }
58.1852 +
58.1853 + destroyTree(tree);
58.1854 + }
58.1855 +
58.1856 + void extractCycle(const Arc &arc) {
58.1857 + Node left = _graph.source(arc);
58.1858 + Node odd = _graph.target((*_matching)[left]);
58.1859 + Arc prev;
58.1860 + while (odd != left) {
58.1861 + Node even = _graph.target((*_matching)[odd]);
58.1862 + prev = (*_matching)[odd];
58.1863 + odd = _graph.target((*_matching)[even]);
58.1864 + _matching->set(even, _graph.oppositeArc(prev));
58.1865 + }
58.1866 + _matching->set(left, arc);
58.1867 +
58.1868 + Node right = _graph.target(arc);
58.1869 + int right_tree = _tree_set->find(right);
58.1870 + alternatePath(right, right_tree);
58.1871 + destroyTree(right_tree);
58.1872 + _matching->set(right, _graph.oppositeArc(arc));
58.1873 + }
58.1874 +
58.1875 + public:
58.1876 +
58.1877 + /// \brief Constructor
58.1878 + ///
58.1879 + /// Constructor.
58.1880 + MaxWeightedPerfectFractionalMatching(const Graph& graph,
58.1881 + const WeightMap& weight,
58.1882 + bool allow_loops = true)
58.1883 + : _graph(graph), _weight(weight), _matching(0),
58.1884 + _node_potential(0), _node_num(0), _allow_loops(allow_loops),
58.1885 + _status(0), _pred(0),
58.1886 + _tree_set_index(0), _tree_set(0),
58.1887 +
58.1888 + _delta2_index(0), _delta2(0),
58.1889 + _delta3_index(0), _delta3(0),
58.1890 +
58.1891 + _delta_sum() {}
58.1892 +
58.1893 + ~MaxWeightedPerfectFractionalMatching() {
58.1894 + destroyStructures();
58.1895 + }
58.1896 +
58.1897 + /// \name Execution Control
58.1898 + /// The simplest way to execute the algorithm is to use the
58.1899 + /// \ref run() member function.
58.1900 +
58.1901 + ///@{
58.1902 +
58.1903 + /// \brief Initialize the algorithm
58.1904 + ///
58.1905 + /// This function initializes the algorithm.
58.1906 + void init() {
58.1907 + createStructures();
58.1908 +
58.1909 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.1910 + (*_delta2_index)[n] = _delta2->PRE_HEAP;
58.1911 + }
58.1912 + for (EdgeIt e(_graph); e != INVALID; ++e) {
58.1913 + (*_delta3_index)[e] = _delta3->PRE_HEAP;
58.1914 + }
58.1915 +
58.1916 + _delta2->clear();
58.1917 + _delta3->clear();
58.1918 + _tree_set->clear();
58.1919 +
58.1920 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.1921 + Value max = - std::numeric_limits<Value>::max();
58.1922 + for (OutArcIt e(_graph, n); e != INVALID; ++e) {
58.1923 + if (_graph.target(e) == n && !_allow_loops) continue;
58.1924 + if ((dualScale * _weight[e]) / 2 > max) {
58.1925 + max = (dualScale * _weight[e]) / 2;
58.1926 + }
58.1927 + }
58.1928 + _node_potential->set(n, max);
58.1929 +
58.1930 + _tree_set->insert(n);
58.1931 +
58.1932 + _matching->set(n, INVALID);
58.1933 + _status->set(n, EVEN);
58.1934 + }
58.1935 +
58.1936 + for (EdgeIt e(_graph); e != INVALID; ++e) {
58.1937 + Node left = _graph.u(e);
58.1938 + Node right = _graph.v(e);
58.1939 + if (left == right && !_allow_loops) continue;
58.1940 + _delta3->push(e, ((*_node_potential)[left] +
58.1941 + (*_node_potential)[right] -
58.1942 + dualScale * _weight[e]) / 2);
58.1943 + }
58.1944 + }
58.1945 +
58.1946 + /// \brief Start the algorithm
58.1947 + ///
58.1948 + /// This function starts the algorithm.
58.1949 + ///
58.1950 + /// \pre \ref init() must be called before using this function.
58.1951 + bool start() {
58.1952 + enum OpType {
58.1953 + D2, D3
58.1954 + };
58.1955 +
58.1956 + int unmatched = _node_num;
58.1957 + while (unmatched > 0) {
58.1958 + Value d2 = !_delta2->empty() ?
58.1959 + _delta2->prio() : std::numeric_limits<Value>::max();
58.1960 +
58.1961 + Value d3 = !_delta3->empty() ?
58.1962 + _delta3->prio() : std::numeric_limits<Value>::max();
58.1963 +
58.1964 + _delta_sum = d3; OpType ot = D3;
58.1965 + if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
58.1966 +
58.1967 + if (_delta_sum == std::numeric_limits<Value>::max()) {
58.1968 + return false;
58.1969 + }
58.1970 +
58.1971 + switch (ot) {
58.1972 + case D2:
58.1973 + {
58.1974 + Node n = _delta2->top();
58.1975 + Arc a = (*_pred)[n];
58.1976 + if ((*_matching)[n] == INVALID) {
58.1977 + augmentOnArc(a);
58.1978 + --unmatched;
58.1979 + } else {
58.1980 + Node v = _graph.target((*_matching)[n]);
58.1981 + if ((*_matching)[n] !=
58.1982 + _graph.oppositeArc((*_matching)[v])) {
58.1983 + extractCycle(a);
58.1984 + --unmatched;
58.1985 + } else {
58.1986 + extendOnArc(a);
58.1987 + }
58.1988 + }
58.1989 + } break;
58.1990 + case D3:
58.1991 + {
58.1992 + Edge e = _delta3->top();
58.1993 +
58.1994 + Node left = _graph.u(e);
58.1995 + Node right = _graph.v(e);
58.1996 +
58.1997 + int left_tree = _tree_set->find(left);
58.1998 + int right_tree = _tree_set->find(right);
58.1999 +
58.2000 + if (left_tree == right_tree) {
58.2001 + cycleOnEdge(e, left_tree);
58.2002 + --unmatched;
58.2003 + } else {
58.2004 + augmentOnEdge(e);
58.2005 + unmatched -= 2;
58.2006 + }
58.2007 + } break;
58.2008 + }
58.2009 + }
58.2010 + return true;
58.2011 + }
58.2012 +
58.2013 + /// \brief Run the algorithm.
58.2014 + ///
58.2015 + /// This method runs the \c %MaxWeightedPerfectFractionalMatching
58.2016 + /// algorithm.
58.2017 + ///
58.2018 + /// \note mwfm.run() is just a shortcut of the following code.
58.2019 + /// \code
58.2020 + /// mwpfm.init();
58.2021 + /// mwpfm.start();
58.2022 + /// \endcode
58.2023 + bool run() {
58.2024 + init();
58.2025 + return start();
58.2026 + }
58.2027 +
58.2028 + /// @}
58.2029 +
58.2030 + /// \name Primal Solution
58.2031 + /// Functions to get the primal solution, i.e. the maximum weighted
58.2032 + /// matching.\n
58.2033 + /// Either \ref run() or \ref start() function should be called before
58.2034 + /// using them.
58.2035 +
58.2036 + /// @{
58.2037 +
58.2038 + /// \brief Return the weight of the matching.
58.2039 + ///
58.2040 + /// This function returns the weight of the found matching. This
58.2041 + /// value is scaled by \ref primalScale "primal scale".
58.2042 + ///
58.2043 + /// \pre Either run() or start() must be called before using this function.
58.2044 + Value matchingWeight() const {
58.2045 + Value sum = 0;
58.2046 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.2047 + if ((*_matching)[n] != INVALID) {
58.2048 + sum += _weight[(*_matching)[n]];
58.2049 + }
58.2050 + }
58.2051 + return sum * primalScale / 2;
58.2052 + }
58.2053 +
58.2054 + /// \brief Return the number of covered nodes in the matching.
58.2055 + ///
58.2056 + /// This function returns the number of covered nodes in the matching.
58.2057 + ///
58.2058 + /// \pre Either run() or start() must be called before using this function.
58.2059 + int matchingSize() const {
58.2060 + int num = 0;
58.2061 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.2062 + if ((*_matching)[n] != INVALID) {
58.2063 + ++num;
58.2064 + }
58.2065 + }
58.2066 + return num;
58.2067 + }
58.2068 +
58.2069 + /// \brief Return \c true if the given edge is in the matching.
58.2070 + ///
58.2071 + /// This function returns \c true if the given edge is in the
58.2072 + /// found matching. The result is scaled by \ref primalScale
58.2073 + /// "primal scale".
58.2074 + ///
58.2075 + /// \pre Either run() or start() must be called before using this function.
58.2076 + int matching(const Edge& edge) const {
58.2077 + return (edge == (*_matching)[_graph.u(edge)] ? 1 : 0)
58.2078 + + (edge == (*_matching)[_graph.v(edge)] ? 1 : 0);
58.2079 + }
58.2080 +
58.2081 + /// \brief Return the fractional matching arc (or edge) incident
58.2082 + /// to the given node.
58.2083 + ///
58.2084 + /// This function returns one of the fractional matching arc (or
58.2085 + /// edge) incident to the given node in the found matching or \c
58.2086 + /// INVALID if the node is not covered by the matching or if the
58.2087 + /// node is on an odd length cycle then it is the successor edge
58.2088 + /// on the cycle.
58.2089 + ///
58.2090 + /// \pre Either run() or start() must be called before using this function.
58.2091 + Arc matching(const Node& node) const {
58.2092 + return (*_matching)[node];
58.2093 + }
58.2094 +
58.2095 + /// \brief Return a const reference to the matching map.
58.2096 + ///
58.2097 + /// This function returns a const reference to a node map that stores
58.2098 + /// the matching arc (or edge) incident to each node.
58.2099 + const MatchingMap& matchingMap() const {
58.2100 + return *_matching;
58.2101 + }
58.2102 +
58.2103 + /// @}
58.2104 +
58.2105 + /// \name Dual Solution
58.2106 + /// Functions to get the dual solution.\n
58.2107 + /// Either \ref run() or \ref start() function should be called before
58.2108 + /// using them.
58.2109 +
58.2110 + /// @{
58.2111 +
58.2112 + /// \brief Return the value of the dual solution.
58.2113 + ///
58.2114 + /// This function returns the value of the dual solution.
58.2115 + /// It should be equal to the primal value scaled by \ref dualScale
58.2116 + /// "dual scale".
58.2117 + ///
58.2118 + /// \pre Either run() or start() must be called before using this function.
58.2119 + Value dualValue() const {
58.2120 + Value sum = 0;
58.2121 + for (NodeIt n(_graph); n != INVALID; ++n) {
58.2122 + sum += nodeValue(n);
58.2123 + }
58.2124 + return sum;
58.2125 + }
58.2126 +
58.2127 + /// \brief Return the dual value (potential) of the given node.
58.2128 + ///
58.2129 + /// This function returns the dual value (potential) of the given node.
58.2130 + ///
58.2131 + /// \pre Either run() or start() must be called before using this function.
58.2132 + Value nodeValue(const Node& n) const {
58.2133 + return (*_node_potential)[n];
58.2134 + }
58.2135 +
58.2136 + /// @}
58.2137 +
58.2138 + };
58.2139 +
58.2140 +} //END OF NAMESPACE LEMON
58.2141 +
58.2142 +#endif //LEMON_FRACTIONAL_MATCHING_H
59.1 --- a/lemon/full_graph.h Tue Dec 20 17:44:38 2011 +0100
59.2 +++ b/lemon/full_graph.h Tue Dec 20 18:15:14 2011 +0100
59.3 @@ -2,7 +2,7 @@
59.4 *
59.5 * This file is a part of LEMON, a generic C++ optimization library.
59.6 *
59.7 - * Copyright (C) 2003-2009
59.8 + * Copyright (C) 2003-2010
59.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
59.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
59.11 *
59.12 @@ -24,7 +24,7 @@
59.13
59.14 ///\ingroup graphs
59.15 ///\file
59.16 -///\brief FullGraph and FullDigraph classes.
59.17 +///\brief FullDigraph and FullGraph classes.
59.18
59.19 namespace lemon {
59.20
59.21 @@ -51,7 +51,7 @@
59.22 typedef True ArcNumTag;
59.23
59.24 Node operator()(int ix) const { return Node(ix); }
59.25 - int index(const Node& node) const { return node._id; }
59.26 + static int index(const Node& node) { return node._id; }
59.27
59.28 Arc arc(const Node& s, const Node& t) const {
59.29 return Arc(s._id * _node_num + t._id);
59.30 @@ -148,24 +148,28 @@
59.31
59.32 /// \ingroup graphs
59.33 ///
59.34 - /// \brief A full digraph class.
59.35 + /// \brief A directed full graph class.
59.36 ///
59.37 - /// This is a simple and fast directed full graph implementation.
59.38 - /// From each node go arcs to each node (including the source node),
59.39 - /// therefore the number of the arcs in the digraph is the square of
59.40 - /// the node number. This digraph type is completely static, so you
59.41 - /// can neither add nor delete either arcs or nodes, and it needs
59.42 - /// constant space in memory.
59.43 + /// FullDigraph is a simple and fast implmenetation of directed full
59.44 + /// (complete) graphs. It contains an arc from each node to each node
59.45 + /// (including a loop for each node), therefore the number of arcs
59.46 + /// is the square of the number of nodes.
59.47 + /// This class is completely static and it needs constant memory space.
59.48 + /// Thus you can neither add nor delete nodes or arcs, however
59.49 + /// the structure can be resized using resize().
59.50 ///
59.51 - /// This class fully conforms to the \ref concepts::Digraph
59.52 - /// "Digraph concept".
59.53 + /// This type fully conforms to the \ref concepts::Digraph "Digraph concept".
59.54 + /// Most of its member functions and nested classes are documented
59.55 + /// only in the concept class.
59.56 ///
59.57 - /// The \c FullDigraph and \c FullGraph classes are very similar,
59.58 + /// This class provides constant time counting for nodes and arcs.
59.59 + ///
59.60 + /// \note FullDigraph and FullGraph classes are very similar,
59.61 /// but there are two differences. While this class conforms only
59.62 - /// to the \ref concepts::Digraph "Digraph" concept, the \c FullGraph
59.63 - /// class conforms to the \ref concepts::Graph "Graph" concept,
59.64 - /// moreover \c FullGraph does not contain a loop arc for each
59.65 - /// node as \c FullDigraph does.
59.66 + /// to the \ref concepts::Digraph "Digraph" concept, FullGraph
59.67 + /// conforms to the \ref concepts::Graph "Graph" concept,
59.68 + /// moreover FullGraph does not contain a loop for each
59.69 + /// node as this class does.
59.70 ///
59.71 /// \sa FullGraph
59.72 class FullDigraph : public ExtendedFullDigraphBase {
59.73 @@ -173,7 +177,9 @@
59.74
59.75 public:
59.76
59.77 - /// \brief Constructor
59.78 + /// \brief Default constructor.
59.79 + ///
59.80 + /// Default constructor. The number of nodes and arcs will be zero.
59.81 FullDigraph() { construct(0); }
59.82
59.83 /// \brief Constructor
59.84 @@ -184,8 +190,8 @@
59.85
59.86 /// \brief Resizes the digraph
59.87 ///
59.88 - /// Resizes the digraph. The function will fully destroy and
59.89 - /// rebuild the digraph. This cause that the maps of the digraph will
59.90 + /// This function resizes the digraph. It fully destroys and
59.91 + /// rebuilds the structure, therefore the maps of the digraph will be
59.92 /// reallocated automatically and the previous values will be lost.
59.93 void resize(int n) {
59.94 Parent::notifier(Arc()).clear();
59.95 @@ -197,24 +203,26 @@
59.96
59.97 /// \brief Returns the node with the given index.
59.98 ///
59.99 - /// Returns the node with the given index. Since it is a static
59.100 - /// digraph its nodes can be indexed with integers from the range
59.101 - /// <tt>[0..nodeNum()-1]</tt>.
59.102 + /// Returns the node with the given index. Since this structure is
59.103 + /// completely static, the nodes can be indexed with integers from
59.104 + /// the range <tt>[0..nodeNum()-1]</tt>.
59.105 + /// The index of a node is the same as its ID.
59.106 /// \sa index()
59.107 Node operator()(int ix) const { return Parent::operator()(ix); }
59.108
59.109 /// \brief Returns the index of the given node.
59.110 ///
59.111 - /// Returns the index of the given node. Since it is a static
59.112 - /// digraph its nodes can be indexed with integers from the range
59.113 - /// <tt>[0..nodeNum()-1]</tt>.
59.114 - /// \sa operator()
59.115 - int index(const Node& node) const { return Parent::index(node); }
59.116 + /// Returns the index of the given node. Since this structure is
59.117 + /// completely static, the nodes can be indexed with integers from
59.118 + /// the range <tt>[0..nodeNum()-1]</tt>.
59.119 + /// The index of a node is the same as its ID.
59.120 + /// \sa operator()()
59.121 + static int index(const Node& node) { return Parent::index(node); }
59.122
59.123 /// \brief Returns the arc connecting the given nodes.
59.124 ///
59.125 /// Returns the arc connecting the given nodes.
59.126 - Arc arc(const Node& u, const Node& v) const {
59.127 + Arc arc(Node u, Node v) const {
59.128 return Parent::arc(u, v);
59.129 }
59.130
59.131 @@ -283,7 +291,7 @@
59.132 public:
59.133
59.134 Node operator()(int ix) const { return Node(ix); }
59.135 - int index(const Node& node) const { return node._id; }
59.136 + static int index(const Node& node) { return node._id; }
59.137
59.138 Edge edge(const Node& u, const Node& v) const {
59.139 if (u._id < v._id) {
59.140 @@ -520,21 +528,25 @@
59.141 ///
59.142 /// \brief An undirected full graph class.
59.143 ///
59.144 - /// This is a simple and fast undirected full graph
59.145 - /// implementation. From each node go edge to each other node,
59.146 - /// therefore the number of edges in the graph is \f$n(n-1)/2\f$.
59.147 - /// This graph type is completely static, so you can neither
59.148 - /// add nor delete either edges or nodes, and it needs constant
59.149 - /// space in memory.
59.150 + /// FullGraph is a simple and fast implmenetation of undirected full
59.151 + /// (complete) graphs. It contains an edge between every distinct pair
59.152 + /// of nodes, therefore the number of edges is <tt>n(n-1)/2</tt>.
59.153 + /// This class is completely static and it needs constant memory space.
59.154 + /// Thus you can neither add nor delete nodes or edges, however
59.155 + /// the structure can be resized using resize().
59.156 ///
59.157 - /// This class fully conforms to the \ref concepts::Graph "Graph concept".
59.158 + /// This type fully conforms to the \ref concepts::Graph "Graph concept".
59.159 + /// Most of its member functions and nested classes are documented
59.160 + /// only in the concept class.
59.161 ///
59.162 - /// The \c FullGraph and \c FullDigraph classes are very similar,
59.163 - /// but there are two differences. While the \c FullDigraph class
59.164 + /// This class provides constant time counting for nodes, edges and arcs.
59.165 + ///
59.166 + /// \note FullDigraph and FullGraph classes are very similar,
59.167 + /// but there are two differences. While FullDigraph
59.168 /// conforms only to the \ref concepts::Digraph "Digraph" concept,
59.169 /// this class conforms to the \ref concepts::Graph "Graph" concept,
59.170 - /// moreover \c FullGraph does not contain a loop arc for each
59.171 - /// node as \c FullDigraph does.
59.172 + /// moreover this class does not contain a loop for each
59.173 + /// node as FullDigraph does.
59.174 ///
59.175 /// \sa FullDigraph
59.176 class FullGraph : public ExtendedFullGraphBase {
59.177 @@ -542,7 +554,9 @@
59.178
59.179 public:
59.180
59.181 - /// \brief Constructor
59.182 + /// \brief Default constructor.
59.183 + ///
59.184 + /// Default constructor. The number of nodes and edges will be zero.
59.185 FullGraph() { construct(0); }
59.186
59.187 /// \brief Constructor
59.188 @@ -553,8 +567,8 @@
59.189
59.190 /// \brief Resizes the graph
59.191 ///
59.192 - /// Resizes the graph. The function will fully destroy and
59.193 - /// rebuild the graph. This cause that the maps of the graph will
59.194 + /// This function resizes the graph. It fully destroys and
59.195 + /// rebuilds the structure, therefore the maps of the graph will be
59.196 /// reallocated automatically and the previous values will be lost.
59.197 void resize(int n) {
59.198 Parent::notifier(Arc()).clear();
59.199 @@ -568,31 +582,33 @@
59.200
59.201 /// \brief Returns the node with the given index.
59.202 ///
59.203 - /// Returns the node with the given index. Since it is a static
59.204 - /// graph its nodes can be indexed with integers from the range
59.205 - /// <tt>[0..nodeNum()-1]</tt>.
59.206 + /// Returns the node with the given index. Since this structure is
59.207 + /// completely static, the nodes can be indexed with integers from
59.208 + /// the range <tt>[0..nodeNum()-1]</tt>.
59.209 + /// The index of a node is the same as its ID.
59.210 /// \sa index()
59.211 Node operator()(int ix) const { return Parent::operator()(ix); }
59.212
59.213 /// \brief Returns the index of the given node.
59.214 ///
59.215 - /// Returns the index of the given node. Since it is a static
59.216 - /// graph its nodes can be indexed with integers from the range
59.217 - /// <tt>[0..nodeNum()-1]</tt>.
59.218 - /// \sa operator()
59.219 - int index(const Node& node) const { return Parent::index(node); }
59.220 + /// Returns the index of the given node. Since this structure is
59.221 + /// completely static, the nodes can be indexed with integers from
59.222 + /// the range <tt>[0..nodeNum()-1]</tt>.
59.223 + /// The index of a node is the same as its ID.
59.224 + /// \sa operator()()
59.225 + static int index(const Node& node) { return Parent::index(node); }
59.226
59.227 /// \brief Returns the arc connecting the given nodes.
59.228 ///
59.229 /// Returns the arc connecting the given nodes.
59.230 - Arc arc(const Node& s, const Node& t) const {
59.231 + Arc arc(Node s, Node t) const {
59.232 return Parent::arc(s, t);
59.233 }
59.234
59.235 - /// \brief Returns the edge connects the given nodes.
59.236 + /// \brief Returns the edge connecting the given nodes.
59.237 ///
59.238 - /// Returns the edge connects the given nodes.
59.239 - Edge edge(const Node& u, const Node& v) const {
59.240 + /// Returns the edge connecting the given nodes.
59.241 + Edge edge(Node u, Node v) const {
59.242 return Parent::edge(u, v);
59.243 }
59.244
60.1 --- a/lemon/glpk.cc Tue Dec 20 17:44:38 2011 +0100
60.2 +++ b/lemon/glpk.cc Tue Dec 20 18:15:14 2011 +0100
60.3 @@ -2,7 +2,7 @@
60.4 *
60.5 * This file is a part of LEMON, a generic C++ optimization library.
60.6 *
60.7 - * Copyright (C) 2003-2009
60.8 + * Copyright (C) 2003-2010
60.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
60.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
60.11 *
60.12 @@ -59,6 +59,42 @@
60.13 return i;
60.14 }
60.15
60.16 + int GlpkBase::_addRow(Value lo, ExprIterator b,
60.17 + ExprIterator e, Value up) {
60.18 + int i = glp_add_rows(lp, 1);
60.19 +
60.20 + if (lo == -INF) {
60.21 + if (up == INF) {
60.22 + glp_set_row_bnds(lp, i, GLP_FR, lo, up);
60.23 + } else {
60.24 + glp_set_row_bnds(lp, i, GLP_UP, lo, up);
60.25 + }
60.26 + } else {
60.27 + if (up == INF) {
60.28 + glp_set_row_bnds(lp, i, GLP_LO, lo, up);
60.29 + } else if (lo != up) {
60.30 + glp_set_row_bnds(lp, i, GLP_DB, lo, up);
60.31 + } else {
60.32 + glp_set_row_bnds(lp, i, GLP_FX, lo, up);
60.33 + }
60.34 + }
60.35 +
60.36 + std::vector<int> indexes;
60.37 + std::vector<Value> values;
60.38 +
60.39 + indexes.push_back(0);
60.40 + values.push_back(0);
60.41 +
60.42 + for(ExprIterator it = b; it != e; ++it) {
60.43 + indexes.push_back(it->first);
60.44 + values.push_back(it->second);
60.45 + }
60.46 +
60.47 + glp_set_mat_row(lp, i, values.size() - 1,
60.48 + &indexes.front(), &values.front());
60.49 + return i;
60.50 + }
60.51 +
60.52 void GlpkBase::_eraseCol(int i) {
60.53 int ca[2];
60.54 ca[1] = i;
61.1 --- a/lemon/glpk.h Tue Dec 20 17:44:38 2011 +0100
61.2 +++ b/lemon/glpk.h Tue Dec 20 18:15:14 2011 +0100
61.3 @@ -2,7 +2,7 @@
61.4 *
61.5 * This file is a part of LEMON, a generic C++ optimization library.
61.6 *
61.7 - * Copyright (C) 2003-2008
61.8 + * Copyright (C) 2003-2010
61.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
61.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
61.11 *
61.12 @@ -30,7 +30,7 @@
61.13 namespace _solver_bits {
61.14 class VoidPtr {
61.15 private:
61.16 - void *_ptr;
61.17 + void *_ptr;
61.18 public:
61.19 VoidPtr() : _ptr(0) {}
61.20
61.21 @@ -38,8 +38,8 @@
61.22 VoidPtr(T* ptr) : _ptr(reinterpret_cast<void*>(ptr)) {}
61.23
61.24 template <typename T>
61.25 - VoidPtr& operator=(T* ptr) {
61.26 - _ptr = reinterpret_cast<void*>(ptr);
61.27 + VoidPtr& operator=(T* ptr) {
61.28 + _ptr = reinterpret_cast<void*>(ptr);
61.29 return *this;
61.30 }
61.31
61.32 @@ -65,6 +65,7 @@
61.33
61.34 virtual int _addCol();
61.35 virtual int _addRow();
61.36 + virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
61.37
61.38 virtual void _eraseCol(int i);
61.39 virtual void _eraseRow(int i);
61.40 @@ -123,13 +124,13 @@
61.41 freeEnv();
61.42 }
61.43 };
61.44 -
61.45 +
61.46 static FreeEnvHelper freeEnvHelper;
61.47
61.48 protected:
61.49 -
61.50 +
61.51 int _message_level;
61.52 -
61.53 +
61.54 public:
61.55
61.56 ///Pointer to the underlying GLPK data structure.
62.1 --- a/lemon/gomory_hu.h Tue Dec 20 17:44:38 2011 +0100
62.2 +++ b/lemon/gomory_hu.h Tue Dec 20 18:15:14 2011 +0100
62.3 @@ -1,8 +1,8 @@
62.4 -/* -*- C++ -*-
62.5 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
62.6 *
62.7 - * This file is a part of LEMON, a generic C++ optimization library
62.8 + * This file is a part of LEMON, a generic C++ optimization library.
62.9 *
62.10 - * Copyright (C) 2003-2008
62.11 + * Copyright (C) 2003-2010
62.12 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
62.13 * (Egervary Research Group on Combinatorial Optimization, EGRES).
62.14 *
62.15 @@ -27,7 +27,7 @@
62.16 #include <lemon/concepts/maps.h>
62.17
62.18 /// \ingroup min_cut
62.19 -/// \file
62.20 +/// \file
62.21 /// \brief Gomory-Hu cut tree in graphs.
62.22
62.23 namespace lemon {
62.24 @@ -38,13 +38,13 @@
62.25 ///
62.26 /// The Gomory-Hu tree is a tree on the node set of a given graph, but it
62.27 /// may contain edges which are not in the original graph. It has the
62.28 - /// property that the minimum capacity edge of the path between two nodes
62.29 + /// property that the minimum capacity edge of the path between two nodes
62.30 /// in this tree has the same weight as the minimum cut in the graph
62.31 /// between these nodes. Moreover the components obtained by removing
62.32 /// this edge from the tree determine the corresponding minimum cut.
62.33 /// Therefore once this tree is computed, the minimum cut between any pair
62.34 /// of nodes can easily be obtained.
62.35 - ///
62.36 + ///
62.37 /// The algorithm calculates \e n-1 distinct minimum cuts (currently with
62.38 /// the \ref Preflow algorithm), thus it has \f$O(n^3\sqrt{e})\f$ overall
62.39 /// time complexity. It calculates a rooted Gomory-Hu tree.
62.40 @@ -60,10 +60,10 @@
62.41 /// The default map type is \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
62.42 #ifdef DOXYGEN
62.43 template <typename GR,
62.44 - typename CAP>
62.45 + typename CAP>
62.46 #else
62.47 template <typename GR,
62.48 - typename CAP = typename GR::template EdgeMap<int> >
62.49 + typename CAP = typename GR::template EdgeMap<int> >
62.50 #endif
62.51 class GomoryHu {
62.52 public:
62.53 @@ -74,7 +74,7 @@
62.54 typedef CAP Capacity;
62.55 /// The value type of capacities
62.56 typedef typename Capacity::Value Value;
62.57 -
62.58 +
62.59 private:
62.60
62.61 TEMPLATE_GRAPH_TYPEDEFS(Graph);
62.62 @@ -89,28 +89,28 @@
62.63
62.64 void createStructures() {
62.65 if (!_pred) {
62.66 - _pred = new typename Graph::template NodeMap<Node>(_graph);
62.67 + _pred = new typename Graph::template NodeMap<Node>(_graph);
62.68 }
62.69 if (!_weight) {
62.70 - _weight = new typename Graph::template NodeMap<Value>(_graph);
62.71 + _weight = new typename Graph::template NodeMap<Value>(_graph);
62.72 }
62.73 if (!_order) {
62.74 - _order = new typename Graph::template NodeMap<int>(_graph);
62.75 + _order = new typename Graph::template NodeMap<int>(_graph);
62.76 }
62.77 }
62.78
62.79 void destroyStructures() {
62.80 if (_pred) {
62.81 - delete _pred;
62.82 + delete _pred;
62.83 }
62.84 if (_weight) {
62.85 - delete _weight;
62.86 + delete _weight;
62.87 }
62.88 if (_order) {
62.89 - delete _order;
62.90 + delete _order;
62.91 }
62.92 }
62.93 -
62.94 +
62.95 public:
62.96
62.97 /// \brief Constructor
62.98 @@ -118,9 +118,9 @@
62.99 /// Constructor.
62.100 /// \param graph The undirected graph the algorithm runs on.
62.101 /// \param capacity The edge capacity map.
62.102 - GomoryHu(const Graph& graph, const Capacity& capacity)
62.103 + GomoryHu(const Graph& graph, const Capacity& capacity)
62.104 : _graph(graph), _capacity(capacity),
62.105 - _pred(0), _weight(0), _order(0)
62.106 + _pred(0), _weight(0), _order(0)
62.107 {
62.108 checkConcept<concepts::ReadMap<Edge, Value>, Capacity>();
62.109 }
62.110 @@ -134,7 +134,7 @@
62.111 }
62.112
62.113 private:
62.114 -
62.115 +
62.116 // Initialize the internal data structures
62.117 void init() {
62.118 createStructures();
62.119 @@ -145,7 +145,7 @@
62.120 (*_order)[n] = -1;
62.121 }
62.122 (*_pred)[_root] = INVALID;
62.123 - (*_weight)[_root] = std::numeric_limits<Value>::max();
62.124 + (*_weight)[_root] = std::numeric_limits<Value>::max();
62.125 }
62.126
62.127
62.128 @@ -154,50 +154,50 @@
62.129 Preflow<Graph, Capacity> fa(_graph, _capacity, _root, INVALID);
62.130
62.131 for (NodeIt n(_graph); n != INVALID; ++n) {
62.132 - if (n == _root) continue;
62.133 + if (n == _root) continue;
62.134
62.135 - Node pn = (*_pred)[n];
62.136 - fa.source(n);
62.137 - fa.target(pn);
62.138 + Node pn = (*_pred)[n];
62.139 + fa.source(n);
62.140 + fa.target(pn);
62.141
62.142 - fa.runMinCut();
62.143 + fa.runMinCut();
62.144
62.145 - (*_weight)[n] = fa.flowValue();
62.146 + (*_weight)[n] = fa.flowValue();
62.147
62.148 - for (NodeIt nn(_graph); nn != INVALID; ++nn) {
62.149 - if (nn != n && fa.minCut(nn) && (*_pred)[nn] == pn) {
62.150 - (*_pred)[nn] = n;
62.151 - }
62.152 - }
62.153 - if ((*_pred)[pn] != INVALID && fa.minCut((*_pred)[pn])) {
62.154 - (*_pred)[n] = (*_pred)[pn];
62.155 - (*_pred)[pn] = n;
62.156 - (*_weight)[n] = (*_weight)[pn];
62.157 - (*_weight)[pn] = fa.flowValue();
62.158 - }
62.159 + for (NodeIt nn(_graph); nn != INVALID; ++nn) {
62.160 + if (nn != n && fa.minCut(nn) && (*_pred)[nn] == pn) {
62.161 + (*_pred)[nn] = n;
62.162 + }
62.163 + }
62.164 + if ((*_pred)[pn] != INVALID && fa.minCut((*_pred)[pn])) {
62.165 + (*_pred)[n] = (*_pred)[pn];
62.166 + (*_pred)[pn] = n;
62.167 + (*_weight)[n] = (*_weight)[pn];
62.168 + (*_weight)[pn] = fa.flowValue();
62.169 + }
62.170 }
62.171
62.172 (*_order)[_root] = 0;
62.173 int index = 1;
62.174
62.175 for (NodeIt n(_graph); n != INVALID; ++n) {
62.176 - std::vector<Node> st;
62.177 - Node nn = n;
62.178 - while ((*_order)[nn] == -1) {
62.179 - st.push_back(nn);
62.180 - nn = (*_pred)[nn];
62.181 - }
62.182 - while (!st.empty()) {
62.183 - (*_order)[st.back()] = index++;
62.184 - st.pop_back();
62.185 - }
62.186 + std::vector<Node> st;
62.187 + Node nn = n;
62.188 + while ((*_order)[nn] == -1) {
62.189 + st.push_back(nn);
62.190 + nn = (*_pred)[nn];
62.191 + }
62.192 + while (!st.empty()) {
62.193 + (*_order)[st.back()] = index++;
62.194 + st.pop_back();
62.195 + }
62.196 }
62.197 }
62.198
62.199 public:
62.200
62.201 ///\name Execution Control
62.202 -
62.203 +
62.204 ///@{
62.205
62.206 /// \brief Run the Gomory-Hu algorithm.
62.207 @@ -207,7 +207,7 @@
62.208 init();
62.209 start();
62.210 }
62.211 -
62.212 +
62.213 /// @}
62.214
62.215 ///\name Query Functions
62.216 @@ -232,7 +232,7 @@
62.217 /// \brief Return the weight of the predecessor edge in the
62.218 /// Gomory-Hu tree.
62.219 ///
62.220 - /// This function returns the weight of the predecessor edge of the
62.221 + /// This function returns the weight of the predecessor edge of the
62.222 /// given node in the Gomory-Hu tree.
62.223 /// If \c node is the root of the tree, the result is undefined.
62.224 ///
62.225 @@ -254,7 +254,7 @@
62.226 /// \brief Return the minimum cut value between two nodes
62.227 ///
62.228 /// This function returns the minimum cut value between the nodes
62.229 - /// \c s and \c t.
62.230 + /// \c s and \c t.
62.231 /// It finds the nearest common ancestor of the given nodes in the
62.232 /// Gomory-Hu tree and calculates the minimum weight edge on the
62.233 /// paths to the ancestor.
62.234 @@ -263,15 +263,15 @@
62.235 Value minCutValue(const Node& s, const Node& t) const {
62.236 Node sn = s, tn = t;
62.237 Value value = std::numeric_limits<Value>::max();
62.238 -
62.239 +
62.240 while (sn != tn) {
62.241 - if ((*_order)[sn] < (*_order)[tn]) {
62.242 - if ((*_weight)[tn] <= value) value = (*_weight)[tn];
62.243 - tn = (*_pred)[tn];
62.244 - } else {
62.245 - if ((*_weight)[sn] <= value) value = (*_weight)[sn];
62.246 - sn = (*_pred)[sn];
62.247 - }
62.248 + if ((*_order)[sn] < (*_order)[tn]) {
62.249 + if ((*_weight)[tn] <= value) value = (*_weight)[tn];
62.250 + tn = (*_pred)[tn];
62.251 + } else {
62.252 + if ((*_weight)[sn] <= value) value = (*_weight)[sn];
62.253 + sn = (*_pred)[sn];
62.254 + }
62.255 }
62.256 return value;
62.257 }
62.258 @@ -294,33 +294,31 @@
62.259 ///
62.260 /// \pre \ref run() must be called before using this function.
62.261 template <typename CutMap>
62.262 - Value minCutMap(const Node& s, ///<
62.263 + Value minCutMap(const Node& s,
62.264 const Node& t,
62.265 - ///<
62.266 CutMap& cutMap
62.267 - ///<
62.268 ) const {
62.269 Node sn = s, tn = t;
62.270 bool s_root=false;
62.271 Node rn = INVALID;
62.272 Value value = std::numeric_limits<Value>::max();
62.273 -
62.274 +
62.275 while (sn != tn) {
62.276 - if ((*_order)[sn] < (*_order)[tn]) {
62.277 - if ((*_weight)[tn] <= value) {
62.278 - rn = tn;
62.279 + if ((*_order)[sn] < (*_order)[tn]) {
62.280 + if ((*_weight)[tn] <= value) {
62.281 + rn = tn;
62.282 s_root = false;
62.283 - value = (*_weight)[tn];
62.284 - }
62.285 - tn = (*_pred)[tn];
62.286 - } else {
62.287 - if ((*_weight)[sn] <= value) {
62.288 - rn = sn;
62.289 + value = (*_weight)[tn];
62.290 + }
62.291 + tn = (*_pred)[tn];
62.292 + } else {
62.293 + if ((*_weight)[sn] <= value) {
62.294 + rn = sn;
62.295 s_root = true;
62.296 - value = (*_weight)[sn];
62.297 - }
62.298 - sn = (*_pred)[sn];
62.299 - }
62.300 + value = (*_weight)[sn];
62.301 + }
62.302 + sn = (*_pred)[sn];
62.303 + }
62.304 }
62.305
62.306 typename Graph::template NodeMap<bool> reached(_graph, false);
62.307 @@ -331,18 +329,18 @@
62.308
62.309 std::vector<Node> st;
62.310 for (NodeIt n(_graph); n != INVALID; ++n) {
62.311 - st.clear();
62.312 + st.clear();
62.313 Node nn = n;
62.314 - while (!reached[nn]) {
62.315 - st.push_back(nn);
62.316 - nn = (*_pred)[nn];
62.317 - }
62.318 - while (!st.empty()) {
62.319 - cutMap.set(st.back(), cutMap[nn]);
62.320 - st.pop_back();
62.321 - }
62.322 + while (!reached[nn]) {
62.323 + st.push_back(nn);
62.324 + nn = (*_pred)[nn];
62.325 + }
62.326 + while (!st.empty()) {
62.327 + cutMap.set(st.back(), cutMap[nn]);
62.328 + st.pop_back();
62.329 + }
62.330 }
62.331 -
62.332 +
62.333 return value;
62.334 }
62.335
62.336 @@ -351,7 +349,7 @@
62.337 friend class MinCutNodeIt;
62.338
62.339 /// Iterate on the nodes of a minimum cut
62.340 -
62.341 +
62.342 /// This iterator class lists the nodes of a minimum cut found by
62.343 /// GomoryHu. Before using it, you must allocate a GomoryHu class
62.344 /// and call its \ref GomoryHu::run() "run()" method.
62.345 @@ -359,10 +357,10 @@
62.346 /// This example counts the nodes in the minimum cut separating \c s from
62.347 /// \c t.
62.348 /// \code
62.349 - /// GomoruHu<Graph> gom(g, capacities);
62.350 + /// GomoryHu<Graph> gom(g, capacities);
62.351 /// gom.run();
62.352 /// int cnt=0;
62.353 - /// for(GomoruHu<Graph>::MinCutNodeIt n(gom,s,t); n!=INVALID; ++n) ++cnt;
62.354 + /// for(GomoryHu<Graph>::MinCutNodeIt n(gom,s,t); n!=INVALID; ++n) ++cnt;
62.355 /// \endcode
62.356 class MinCutNodeIt
62.357 {
62.358 @@ -394,7 +392,7 @@
62.359 /// MinCutNodeIt(gomory, t, s, false);
62.360 /// \endcode
62.361 /// does not necessarily give the same set of nodes.
62.362 - /// However it is ensured that
62.363 + /// However, it is ensured that
62.364 /// \code
62.365 /// MinCutNodeIt(gomory, s, t, true);
62.366 /// \endcode
62.367 @@ -444,11 +442,11 @@
62.368 return n;
62.369 }
62.370 };
62.371 -
62.372 +
62.373 friend class MinCutEdgeIt;
62.374 -
62.375 +
62.376 /// Iterate on the edges of a minimum cut
62.377 -
62.378 +
62.379 /// This iterator class lists the edges of a minimum cut found by
62.380 /// GomoryHu. Before using it, you must allocate a GomoryHu class
62.381 /// and call its \ref GomoryHu::run() "run()" method.
62.382 @@ -456,10 +454,10 @@
62.383 /// This example computes the value of the minimum cut separating \c s from
62.384 /// \c t.
62.385 /// \code
62.386 - /// GomoruHu<Graph> gom(g, capacities);
62.387 + /// GomoryHu<Graph> gom(g, capacities);
62.388 /// gom.run();
62.389 /// int value=0;
62.390 - /// for(GomoruHu<Graph>::MinCutEdgeIt e(gom,s,t); e!=INVALID; ++e)
62.391 + /// for(GomoryHu<Graph>::MinCutEdgeIt e(gom,s,t); e!=INVALID; ++e)
62.392 /// value+=capacities[e];
62.393 /// \endcode
62.394 /// The result will be the same as the value returned by
62.395 @@ -481,7 +479,7 @@
62.396 _arc_it=typename Graph::OutArcIt(_graph,_node_it);
62.397 }
62.398 }
62.399 -
62.400 +
62.401 public:
62.402 /// Constructor
62.403
62.404 @@ -550,7 +548,7 @@
62.405 return *this;
62.406 }
62.407 /// Postfix incrementation
62.408 -
62.409 +
62.410 /// Postfix incrementation.
62.411 ///
62.412 /// \warning This incrementation
63.1 --- a/lemon/graph_to_eps.h Tue Dec 20 17:44:38 2011 +0100
63.2 +++ b/lemon/graph_to_eps.h Tue Dec 20 18:15:14 2011 +0100
63.3 @@ -2,7 +2,7 @@
63.4 *
63.5 * This file is a part of LEMON, a generic C++ optimization library.
63.6 *
63.7 - * Copyright (C) 2003-2009
63.8 + * Copyright (C) 2003-2010
63.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
63.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
63.11 *
63.12 @@ -142,7 +142,7 @@
63.13 ///Constructor
63.14 ///\param gr Reference to the graph to be printed.
63.15 ///\param ost Reference to the output stream.
63.16 - ///By default it is <tt>std::cout</tt>.
63.17 + ///By default, it is <tt>std::cout</tt>.
63.18 ///\param pros If it is \c true, then the \c ostream referenced by \c os
63.19 ///will be explicitly deallocated by the destructor.
63.20 DefaultGraphToEpsTraits(const GR &gr, std::ostream& ost = std::cout,
63.21 @@ -512,7 +512,7 @@
63.22
63.23 ///Turn on/off pre-scaling
63.24
63.25 - ///By default graphToEps() rescales the whole image in order to avoid
63.26 + ///By default, graphToEps() rescales the whole image in order to avoid
63.27 ///very big or very small bounding boxes.
63.28 ///
63.29 ///This (p)rescaling can be turned off with this function.
63.30 @@ -1114,7 +1114,7 @@
63.31 ///Generates an EPS file from a graph.
63.32 ///\param g Reference to the graph to be printed.
63.33 ///\param os Reference to the output stream.
63.34 -///By default it is <tt>std::cout</tt>.
63.35 +///By default, it is <tt>std::cout</tt>.
63.36 ///
63.37 ///This function also has a lot of
63.38 ///\ref named-templ-func-param "named parameters",
63.39 @@ -1126,7 +1126,7 @@
63.40 /// .arcWidthScale(.4).run();
63.41 ///\endcode
63.42 ///
63.43 -///For more detailed examples see the \ref graph_to_eps_demo.cc demo file.
63.44 +///For more detailed examples, see the \ref graph_to_eps_demo.cc demo file.
63.45 ///
63.46 ///\warning Don't forget to put the \ref GraphToEps::run() "run()"
63.47 ///to the end of the parameter list.
64.1 --- a/lemon/grid_graph.h Tue Dec 20 17:44:38 2011 +0100
64.2 +++ b/lemon/grid_graph.h Tue Dec 20 18:15:14 2011 +0100
64.3 @@ -470,18 +470,22 @@
64.4 ///
64.5 /// \brief Grid graph class
64.6 ///
64.7 - /// This class implements a special graph type. The nodes of the
64.8 - /// graph can be indexed by two integer \c (i,j) value where \c i is
64.9 - /// in the \c [0..width()-1] range and j is in the \c
64.10 - /// [0..height()-1] range. Two nodes are connected in the graph if
64.11 - /// the indexes differ exactly on one position and exactly one is
64.12 - /// the difference. The nodes of the graph can be indexed by position
64.13 - /// with the \c operator()() function. The positions of the nodes can be
64.14 - /// get with \c pos(), \c col() and \c row() members. The outgoing
64.15 + /// GridGraph implements a special graph type. The nodes of the
64.16 + /// graph can be indexed by two integer values \c (i,j) where \c i is
64.17 + /// in the range <tt>[0..width()-1]</tt> and j is in the range
64.18 + /// <tt>[0..height()-1]</tt>. Two nodes are connected in the graph if
64.19 + /// the indices differ exactly on one position and the difference is
64.20 + /// also exactly one. The nodes of the graph can be obtained by position
64.21 + /// using the \c operator()() function and the indices of the nodes can
64.22 + /// be obtained using \c pos(), \c col() and \c row() members. The outgoing
64.23 /// arcs can be retrieved with the \c right(), \c up(), \c left()
64.24 /// and \c down() functions, where the bottom-left corner is the
64.25 /// origin.
64.26 ///
64.27 + /// This class is completely static and it needs constant memory space.
64.28 + /// Thus you can neither add nor delete nodes or edges, however
64.29 + /// the structure can be resized using resize().
64.30 + ///
64.31 /// \image html grid_graph.png
64.32 /// \image latex grid_graph.eps "Grid graph" width=\textwidth
64.33 ///
64.34 @@ -496,16 +500,21 @@
64.35 /// }
64.36 ///\endcode
64.37 ///
64.38 - /// This graph type fully conforms to the \ref concepts::Graph
64.39 - /// "Graph concept".
64.40 + /// This type fully conforms to the \ref concepts::Graph "Graph concept".
64.41 + /// Most of its member functions and nested classes are documented
64.42 + /// only in the concept class.
64.43 + ///
64.44 + /// This class provides constant time counting for nodes, edges and arcs.
64.45 class GridGraph : public ExtendedGridGraphBase {
64.46 typedef ExtendedGridGraphBase Parent;
64.47
64.48 public:
64.49
64.50 - /// \brief Map to get the indices of the nodes as dim2::Point<int>.
64.51 + /// \brief Map to get the indices of the nodes as \ref dim2::Point
64.52 + /// "dim2::Point<int>".
64.53 ///
64.54 - /// Map to get the indices of the nodes as dim2::Point<int>.
64.55 + /// Map to get the indices of the nodes as \ref dim2::Point
64.56 + /// "dim2::Point<int>".
64.57 class IndexMap {
64.58 public:
64.59 /// \brief The key type of the map
64.60 @@ -514,13 +523,9 @@
64.61 typedef dim2::Point<int> Value;
64.62
64.63 /// \brief Constructor
64.64 - ///
64.65 - /// Constructor
64.66 IndexMap(const GridGraph& graph) : _graph(graph) {}
64.67
64.68 /// \brief The subscript operator
64.69 - ///
64.70 - /// The subscript operator.
64.71 Value operator[](Key key) const {
64.72 return _graph.pos(key);
64.73 }
64.74 @@ -540,13 +545,9 @@
64.75 typedef int Value;
64.76
64.77 /// \brief Constructor
64.78 - ///
64.79 - /// Constructor
64.80 ColMap(const GridGraph& graph) : _graph(graph) {}
64.81
64.82 /// \brief The subscript operator
64.83 - ///
64.84 - /// The subscript operator.
64.85 Value operator[](Key key) const {
64.86 return _graph.col(key);
64.87 }
64.88 @@ -566,13 +567,9 @@
64.89 typedef int Value;
64.90
64.91 /// \brief Constructor
64.92 - ///
64.93 - /// Constructor
64.94 RowMap(const GridGraph& graph) : _graph(graph) {}
64.95
64.96 /// \brief The subscript operator
64.97 - ///
64.98 - /// The subscript operator.
64.99 Value operator[](Key key) const {
64.100 return _graph.row(key);
64.101 }
64.102 @@ -583,15 +580,14 @@
64.103
64.104 /// \brief Constructor
64.105 ///
64.106 - /// Construct a grid graph with given size.
64.107 + /// Construct a grid graph with the given size.
64.108 GridGraph(int width, int height) { construct(width, height); }
64.109
64.110 - /// \brief Resize the graph
64.111 + /// \brief Resizes the graph
64.112 ///
64.113 - /// Resize the graph. The function will fully destroy and rebuild
64.114 - /// the graph. This cause that the maps of the graph will
64.115 - /// reallocated automatically and the previous values will be
64.116 - /// lost.
64.117 + /// This function resizes the graph. It fully destroys and
64.118 + /// rebuilds the structure, therefore the maps of the graph will be
64.119 + /// reallocated automatically and the previous values will be lost.
64.120 void resize(int width, int height) {
64.121 Parent::notifier(Arc()).clear();
64.122 Parent::notifier(Edge()).clear();
64.123 @@ -609,42 +605,42 @@
64.124 return Parent::operator()(i, j);
64.125 }
64.126
64.127 - /// \brief Gives back the column index of the node.
64.128 + /// \brief The column index of the node.
64.129 ///
64.130 /// Gives back the column index of the node.
64.131 int col(Node n) const {
64.132 return Parent::col(n);
64.133 }
64.134
64.135 - /// \brief Gives back the row index of the node.
64.136 + /// \brief The row index of the node.
64.137 ///
64.138 /// Gives back the row index of the node.
64.139 int row(Node n) const {
64.140 return Parent::row(n);
64.141 }
64.142
64.143 - /// \brief Gives back the position of the node.
64.144 + /// \brief The position of the node.
64.145 ///
64.146 /// Gives back the position of the node, ie. the <tt>(col,row)</tt> pair.
64.147 dim2::Point<int> pos(Node n) const {
64.148 return Parent::pos(n);
64.149 }
64.150
64.151 - /// \brief Gives back the number of the columns.
64.152 + /// \brief The number of the columns.
64.153 ///
64.154 /// Gives back the number of the columns.
64.155 int width() const {
64.156 return Parent::width();
64.157 }
64.158
64.159 - /// \brief Gives back the number of the rows.
64.160 + /// \brief The number of the rows.
64.161 ///
64.162 /// Gives back the number of the rows.
64.163 int height() const {
64.164 return Parent::height();
64.165 }
64.166
64.167 - /// \brief Gives back the arc goes right from the node.
64.168 + /// \brief The arc goes right from the node.
64.169 ///
64.170 /// Gives back the arc goes right from the node. If there is not
64.171 /// outgoing arc then it gives back INVALID.
64.172 @@ -652,7 +648,7 @@
64.173 return Parent::right(n);
64.174 }
64.175
64.176 - /// \brief Gives back the arc goes left from the node.
64.177 + /// \brief The arc goes left from the node.
64.178 ///
64.179 /// Gives back the arc goes left from the node. If there is not
64.180 /// outgoing arc then it gives back INVALID.
64.181 @@ -660,7 +656,7 @@
64.182 return Parent::left(n);
64.183 }
64.184
64.185 - /// \brief Gives back the arc goes up from the node.
64.186 + /// \brief The arc goes up from the node.
64.187 ///
64.188 /// Gives back the arc goes up from the node. If there is not
64.189 /// outgoing arc then it gives back INVALID.
64.190 @@ -668,7 +664,7 @@
64.191 return Parent::up(n);
64.192 }
64.193
64.194 - /// \brief Gives back the arc goes down from the node.
64.195 + /// \brief The arc goes down from the node.
64.196 ///
64.197 /// Gives back the arc goes down from the node. If there is not
64.198 /// outgoing arc then it gives back INVALID.
65.1 --- a/lemon/hao_orlin.h Tue Dec 20 17:44:38 2011 +0100
65.2 +++ b/lemon/hao_orlin.h Tue Dec 20 18:15:14 2011 +0100
65.3 @@ -2,7 +2,7 @@
65.4 *
65.5 * This file is a part of LEMON, a generic C++ optimization library.
65.6 *
65.7 - * Copyright (C) 2003-2009
65.8 + * Copyright (C) 2003-2010
65.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
65.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
65.11 *
65.12 @@ -31,7 +31,7 @@
65.13 /// \ingroup min_cut
65.14 /// \brief Implementation of the Hao-Orlin algorithm.
65.15 ///
65.16 -/// Implementation of the Hao-Orlin algorithm for finding a minimum cut
65.17 +/// Implementation of the Hao-Orlin algorithm for finding a minimum cut
65.18 /// in a digraph.
65.19
65.20 namespace lemon {
65.21 @@ -41,7 +41,7 @@
65.22 /// \brief Hao-Orlin algorithm for finding a minimum cut in a digraph.
65.23 ///
65.24 /// This class implements the Hao-Orlin algorithm for finding a minimum
65.25 - /// value cut in a directed graph \f$D=(V,A)\f$.
65.26 + /// value cut in a directed graph \f$D=(V,A)\f$.
65.27 /// It takes a fixed node \f$ source \in V \f$ and
65.28 /// consists of two phases: in the first phase it determines a
65.29 /// minimum cut with \f$ source \f$ on the source-side (i.e. a set
65.30 @@ -58,7 +58,7 @@
65.31 ///
65.32 /// For an undirected graph you can run just the first phase of the
65.33 /// algorithm or you can use the algorithm of Nagamochi and Ibaraki,
65.34 - /// which solves the undirected problem in \f$ O(nm + n^2 \log n) \f$
65.35 + /// which solves the undirected problem in \f$ O(nm + n^2 \log n) \f$
65.36 /// time. It is implemented in the NagamochiIbaraki algorithm class.
65.37 ///
65.38 /// \tparam GR The type of the digraph the algorithm runs on.
65.39 @@ -76,7 +76,7 @@
65.40 #endif
65.41 class HaoOrlin {
65.42 public:
65.43 -
65.44 +
65.45 /// The digraph type of the algorithm
65.46 typedef GR Digraph;
65.47 /// The capacity map type of the algorithm
65.48 @@ -165,6 +165,23 @@
65.49 }
65.50 }
65.51
65.52 + /// \brief Set the tolerance used by the algorithm.
65.53 + ///
65.54 + /// This function sets the tolerance object used by the algorithm.
65.55 + /// \return <tt>(*this)</tt>
65.56 + HaoOrlin& tolerance(const Tolerance& tolerance) {
65.57 + _tolerance = tolerance;
65.58 + return *this;
65.59 + }
65.60 +
65.61 + /// \brief Returns a const reference to the tolerance.
65.62 + ///
65.63 + /// This function returns a const reference to the tolerance object
65.64 + /// used by the algorithm.
65.65 + const Tolerance& tolerance() const {
65.66 + return _tolerance;
65.67 + }
65.68 +
65.69 private:
65.70
65.71 void activate(const Node& i) {
65.72 @@ -847,7 +864,7 @@
65.73 /// \brief Initialize the internal data structures.
65.74 ///
65.75 /// This function initializes the internal data structures. It creates
65.76 - /// the maps and some bucket structures for the algorithm.
65.77 + /// the maps and some bucket structures for the algorithm.
65.78 /// The given node is used as the source node for the push-relabel
65.79 /// algorithm.
65.80 void init(const Node& source) {
65.81 @@ -927,7 +944,7 @@
65.82
65.83 /// \brief Run the algorithm.
65.84 ///
65.85 - /// This function runs the algorithm. It uses the given \c source node,
65.86 + /// This function runs the algorithm. It uses the given \c source node,
65.87 /// finds a proper \c target node and then calls the \ref init(),
65.88 /// \ref calculateOut() and \ref calculateIn().
65.89 void run(const Node& s) {
65.90 @@ -941,7 +958,7 @@
65.91 /// \name Query Functions
65.92 /// The result of the %HaoOrlin algorithm
65.93 /// can be obtained using these functions.\n
65.94 - /// \ref run(), \ref calculateOut() or \ref calculateIn()
65.95 + /// \ref run(), \ref calculateOut() or \ref calculateIn()
65.96 /// should be called before using them.
65.97
65.98 /// @{
65.99 @@ -950,7 +967,7 @@
65.100 ///
65.101 /// This function returns the value of the minimum cut.
65.102 ///
65.103 - /// \pre \ref run(), \ref calculateOut() or \ref calculateIn()
65.104 + /// \pre \ref run(), \ref calculateOut() or \ref calculateIn()
65.105 /// must be called before using this function.
65.106 Value minCutValue() const {
65.107 return _min_cut;
65.108 @@ -969,7 +986,7 @@
65.109 ///
65.110 /// \return The value of the minimum cut.
65.111 ///
65.112 - /// \pre \ref run(), \ref calculateOut() or \ref calculateIn()
65.113 + /// \pre \ref run(), \ref calculateOut() or \ref calculateIn()
65.114 /// must be called before using this function.
65.115 template <typename CutMap>
65.116 Value minCutMap(CutMap& cutMap) const {
66.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
66.2 +++ b/lemon/hartmann_orlin_mmc.h Tue Dec 20 18:15:14 2011 +0100
66.3 @@ -0,0 +1,650 @@
66.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
66.5 + *
66.6 + * This file is a part of LEMON, a generic C++ optimization library.
66.7 + *
66.8 + * Copyright (C) 2003-2010
66.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
66.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
66.11 + *
66.12 + * Permission to use, modify and distribute this software is granted
66.13 + * provided that this copyright notice appears in all copies. For
66.14 + * precise terms see the accompanying LICENSE file.
66.15 + *
66.16 + * This software is provided "AS IS" with no warranty of any kind,
66.17 + * express or implied, and with no claim as to its suitability for any
66.18 + * purpose.
66.19 + *
66.20 + */
66.21 +
66.22 +#ifndef LEMON_HARTMANN_ORLIN_MMC_H
66.23 +#define LEMON_HARTMANN_ORLIN_MMC_H
66.24 +
66.25 +/// \ingroup min_mean_cycle
66.26 +///
66.27 +/// \file
66.28 +/// \brief Hartmann-Orlin's algorithm for finding a minimum mean cycle.
66.29 +
66.30 +#include <vector>
66.31 +#include <limits>
66.32 +#include <lemon/core.h>
66.33 +#include <lemon/path.h>
66.34 +#include <lemon/tolerance.h>
66.35 +#include <lemon/connectivity.h>
66.36 +
66.37 +namespace lemon {
66.38 +
66.39 + /// \brief Default traits class of HartmannOrlinMmc class.
66.40 + ///
66.41 + /// Default traits class of HartmannOrlinMmc class.
66.42 + /// \tparam GR The type of the digraph.
66.43 + /// \tparam CM The type of the cost map.
66.44 + /// It must conform to the \ref concepts::Rea_data "Rea_data" concept.
66.45 +#ifdef DOXYGEN
66.46 + template <typename GR, typename CM>
66.47 +#else
66.48 + template <typename GR, typename CM,
66.49 + bool integer = std::numeric_limits<typename CM::Value>::is_integer>
66.50 +#endif
66.51 + struct HartmannOrlinMmcDefaultTraits
66.52 + {
66.53 + /// The type of the digraph
66.54 + typedef GR Digraph;
66.55 + /// The type of the cost map
66.56 + typedef CM CostMap;
66.57 + /// The type of the arc costs
66.58 + typedef typename CostMap::Value Cost;
66.59 +
66.60 + /// \brief The large cost type used for internal computations
66.61 + ///
66.62 + /// The large cost type used for internal computations.
66.63 + /// It is \c long \c long if the \c Cost type is integer,
66.64 + /// otherwise it is \c double.
66.65 + /// \c Cost must be convertible to \c LargeCost.
66.66 + typedef double LargeCost;
66.67 +
66.68 + /// The tolerance type used for internal computations
66.69 + typedef lemon::Tolerance<LargeCost> Tolerance;
66.70 +
66.71 + /// \brief The path type of the found cycles
66.72 + ///
66.73 + /// The path type of the found cycles.
66.74 + /// It must conform to the \ref lemon::concepts::Path "Path" concept
66.75 + /// and it must have an \c addFront() function.
66.76 + typedef lemon::Path<Digraph> Path;
66.77 + };
66.78 +
66.79 + // Default traits class for integer cost types
66.80 + template <typename GR, typename CM>
66.81 + struct HartmannOrlinMmcDefaultTraits<GR, CM, true>
66.82 + {
66.83 + typedef GR Digraph;
66.84 + typedef CM CostMap;
66.85 + typedef typename CostMap::Value Cost;
66.86 +#ifdef LEMON_HAVE_LONG_LONG
66.87 + typedef long long LargeCost;
66.88 +#else
66.89 + typedef long LargeCost;
66.90 +#endif
66.91 + typedef lemon::Tolerance<LargeCost> Tolerance;
66.92 + typedef lemon::Path<Digraph> Path;
66.93 + };
66.94 +
66.95 +
66.96 + /// \addtogroup min_mean_cycle
66.97 + /// @{
66.98 +
66.99 + /// \brief Implementation of the Hartmann-Orlin algorithm for finding
66.100 + /// a minimum mean cycle.
66.101 + ///
66.102 + /// This class implements the Hartmann-Orlin algorithm for finding
66.103 + /// a directed cycle of minimum mean cost in a digraph
66.104 + /// \ref amo93networkflows, \ref dasdan98minmeancycle.
66.105 + /// It is an improved version of \ref Karp "Karp"'s original algorithm,
66.106 + /// it applies an efficient early termination scheme.
66.107 + /// It runs in time O(ne) and uses space O(n<sup>2</sup>+e).
66.108 + ///
66.109 + /// \tparam GR The type of the digraph the algorithm runs on.
66.110 + /// \tparam CM The type of the cost map. The default
66.111 + /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
66.112 + /// \tparam TR The traits class that defines various types used by the
66.113 + /// algorithm. By default, it is \ref HartmannOrlinMmcDefaultTraits
66.114 + /// "HartmannOrlinMmcDefaultTraits<GR, CM>".
66.115 + /// In most cases, this parameter should not be set directly,
66.116 + /// consider to use the named template parameters instead.
66.117 +#ifdef DOXYGEN
66.118 + template <typename GR, typename CM, typename TR>
66.119 +#else
66.120 + template < typename GR,
66.121 + typename CM = typename GR::template ArcMap<int>,
66.122 + typename TR = HartmannOrlinMmcDefaultTraits<GR, CM> >
66.123 +#endif
66.124 + class HartmannOrlinMmc
66.125 + {
66.126 + public:
66.127 +
66.128 + /// The type of the digraph
66.129 + typedef typename TR::Digraph Digraph;
66.130 + /// The type of the cost map
66.131 + typedef typename TR::CostMap CostMap;
66.132 + /// The type of the arc costs
66.133 + typedef typename TR::Cost Cost;
66.134 +
66.135 + /// \brief The large cost type
66.136 + ///
66.137 + /// The large cost type used for internal computations.
66.138 + /// By default, it is \c long \c long if the \c Cost type is integer,
66.139 + /// otherwise it is \c double.
66.140 + typedef typename TR::LargeCost LargeCost;
66.141 +
66.142 + /// The tolerance type
66.143 + typedef typename TR::Tolerance Tolerance;
66.144 +
66.145 + /// \brief The path type of the found cycles
66.146 + ///
66.147 + /// The path type of the found cycles.
66.148 + /// Using the \ref HartmannOrlinMmcDefaultTraits "default traits class",
66.149 + /// it is \ref lemon::Path "Path<Digraph>".
66.150 + typedef typename TR::Path Path;
66.151 +
66.152 + /// The \ref HartmannOrlinMmcDefaultTraits "traits class" of the algorithm
66.153 + typedef TR Traits;
66.154 +
66.155 + private:
66.156 +
66.157 + TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
66.158 +
66.159 + // Data sturcture for path data
66.160 + struct PathData
66.161 + {
66.162 + LargeCost dist;
66.163 + Arc pred;
66.164 + PathData(LargeCost d, Arc p = INVALID) :
66.165 + dist(d), pred(p) {}
66.166 + };
66.167 +
66.168 + typedef typename Digraph::template NodeMap<std::vector<PathData> >
66.169 + PathDataNodeMap;
66.170 +
66.171 + private:
66.172 +
66.173 + // The digraph the algorithm runs on
66.174 + const Digraph &_gr;
66.175 + // The cost of the arcs
66.176 + const CostMap &_cost;
66.177 +
66.178 + // Data for storing the strongly connected components
66.179 + int _comp_num;
66.180 + typename Digraph::template NodeMap<int> _comp;
66.181 + std::vector<std::vector<Node> > _comp_nodes;
66.182 + std::vector<Node>* _nodes;
66.183 + typename Digraph::template NodeMap<std::vector<Arc> > _out_arcs;
66.184 +
66.185 + // Data for the found cycles
66.186 + bool _curr_found, _best_found;
66.187 + LargeCost _curr_cost, _best_cost;
66.188 + int _curr_size, _best_size;
66.189 + Node _curr_node, _best_node;
66.190 + int _curr_level, _best_level;
66.191 +
66.192 + Path *_cycle_path;
66.193 + bool _local_path;
66.194 +
66.195 + // Node map for storing path data
66.196 + PathDataNodeMap _data;
66.197 + // The processed nodes in the last round
66.198 + std::vector<Node> _process;
66.199 +
66.200 + Tolerance _tolerance;
66.201 +
66.202 + // Infinite constant
66.203 + const LargeCost INF;
66.204 +
66.205 + public:
66.206 +
66.207 + /// \name Named Template Parameters
66.208 + /// @{
66.209 +
66.210 + template <typename T>
66.211 + struct SetLargeCostTraits : public Traits {
66.212 + typedef T LargeCost;
66.213 + typedef lemon::Tolerance<T> Tolerance;
66.214 + };
66.215 +
66.216 + /// \brief \ref named-templ-param "Named parameter" for setting
66.217 + /// \c LargeCost type.
66.218 + ///
66.219 + /// \ref named-templ-param "Named parameter" for setting \c LargeCost
66.220 + /// type. It is used for internal computations in the algorithm.
66.221 + template <typename T>
66.222 + struct SetLargeCost
66.223 + : public HartmannOrlinMmc<GR, CM, SetLargeCostTraits<T> > {
66.224 + typedef HartmannOrlinMmc<GR, CM, SetLargeCostTraits<T> > Create;
66.225 + };
66.226 +
66.227 + template <typename T>
66.228 + struct SetPathTraits : public Traits {
66.229 + typedef T Path;
66.230 + };
66.231 +
66.232 + /// \brief \ref named-templ-param "Named parameter" for setting
66.233 + /// \c %Path type.
66.234 + ///
66.235 + /// \ref named-templ-param "Named parameter" for setting the \c %Path
66.236 + /// type of the found cycles.
66.237 + /// It must conform to the \ref lemon::concepts::Path "Path" concept
66.238 + /// and it must have an \c addFront() function.
66.239 + template <typename T>
66.240 + struct SetPath
66.241 + : public HartmannOrlinMmc<GR, CM, SetPathTraits<T> > {
66.242 + typedef HartmannOrlinMmc<GR, CM, SetPathTraits<T> > Create;
66.243 + };
66.244 +
66.245 + /// @}
66.246 +
66.247 + protected:
66.248 +
66.249 + HartmannOrlinMmc() {}
66.250 +
66.251 + public:
66.252 +
66.253 + /// \brief Constructor.
66.254 + ///
66.255 + /// The constructor of the class.
66.256 + ///
66.257 + /// \param digraph The digraph the algorithm runs on.
66.258 + /// \param cost The costs of the arcs.
66.259 + HartmannOrlinMmc( const Digraph &digraph,
66.260 + const CostMap &cost ) :
66.261 + _gr(digraph), _cost(cost), _comp(digraph), _out_arcs(digraph),
66.262 + _best_found(false), _best_cost(0), _best_size(1),
66.263 + _cycle_path(NULL), _local_path(false), _data(digraph),
66.264 + INF(std::numeric_limits<LargeCost>::has_infinity ?
66.265 + std::numeric_limits<LargeCost>::infinity() :
66.266 + std::numeric_limits<LargeCost>::max())
66.267 + {}
66.268 +
66.269 + /// Destructor.
66.270 + ~HartmannOrlinMmc() {
66.271 + if (_local_path) delete _cycle_path;
66.272 + }
66.273 +
66.274 + /// \brief Set the path structure for storing the found cycle.
66.275 + ///
66.276 + /// This function sets an external path structure for storing the
66.277 + /// found cycle.
66.278 + ///
66.279 + /// If you don't call this function before calling \ref run() or
66.280 + /// \ref findCycleMean(), it will allocate a local \ref Path "path"
66.281 + /// structure. The destuctor deallocates this automatically
66.282 + /// allocated object, of course.
66.283 + ///
66.284 + /// \note The algorithm calls only the \ref lemon::Path::addFront()
66.285 + /// "addFront()" function of the given path structure.
66.286 + ///
66.287 + /// \return <tt>(*this)</tt>
66.288 + HartmannOrlinMmc& cycle(Path &path) {
66.289 + if (_local_path) {
66.290 + delete _cycle_path;
66.291 + _local_path = false;
66.292 + }
66.293 + _cycle_path = &path;
66.294 + return *this;
66.295 + }
66.296 +
66.297 + /// \brief Set the tolerance used by the algorithm.
66.298 + ///
66.299 + /// This function sets the tolerance object used by the algorithm.
66.300 + ///
66.301 + /// \return <tt>(*this)</tt>
66.302 + HartmannOrlinMmc& tolerance(const Tolerance& tolerance) {
66.303 + _tolerance = tolerance;
66.304 + return *this;
66.305 + }
66.306 +
66.307 + /// \brief Return a const reference to the tolerance.
66.308 + ///
66.309 + /// This function returns a const reference to the tolerance object
66.310 + /// used by the algorithm.
66.311 + const Tolerance& tolerance() const {
66.312 + return _tolerance;
66.313 + }
66.314 +
66.315 + /// \name Execution control
66.316 + /// The simplest way to execute the algorithm is to call the \ref run()
66.317 + /// function.\n
66.318 + /// If you only need the minimum mean cost, you may call
66.319 + /// \ref findCycleMean().
66.320 +
66.321 + /// @{
66.322 +
66.323 + /// \brief Run the algorithm.
66.324 + ///
66.325 + /// This function runs the algorithm.
66.326 + /// It can be called more than once (e.g. if the underlying digraph
66.327 + /// and/or the arc costs have been modified).
66.328 + ///
66.329 + /// \return \c true if a directed cycle exists in the digraph.
66.330 + ///
66.331 + /// \note <tt>mmc.run()</tt> is just a shortcut of the following code.
66.332 + /// \code
66.333 + /// return mmc.findCycleMean() && mmc.findCycle();
66.334 + /// \endcode
66.335 + bool run() {
66.336 + return findCycleMean() && findCycle();
66.337 + }
66.338 +
66.339 + /// \brief Find the minimum cycle mean.
66.340 + ///
66.341 + /// This function finds the minimum mean cost of the directed
66.342 + /// cycles in the digraph.
66.343 + ///
66.344 + /// \return \c true if a directed cycle exists in the digraph.
66.345 + bool findCycleMean() {
66.346 + // Initialization and find strongly connected components
66.347 + init();
66.348 + findComponents();
66.349 +
66.350 + // Find the minimum cycle mean in the components
66.351 + for (int comp = 0; comp < _comp_num; ++comp) {
66.352 + if (!initComponent(comp)) continue;
66.353 + processRounds();
66.354 +
66.355 + // Update the best cycle (global minimum mean cycle)
66.356 + if ( _curr_found && (!_best_found ||
66.357 + _curr_cost * _best_size < _best_cost * _curr_size) ) {
66.358 + _best_found = true;
66.359 + _best_cost = _curr_cost;
66.360 + _best_size = _curr_size;
66.361 + _best_node = _curr_node;
66.362 + _best_level = _curr_level;
66.363 + }
66.364 + }
66.365 + return _best_found;
66.366 + }
66.367 +
66.368 + /// \brief Find a minimum mean directed cycle.
66.369 + ///
66.370 + /// This function finds a directed cycle of minimum mean cost
66.371 + /// in the digraph using the data computed by findCycleMean().
66.372 + ///
66.373 + /// \return \c true if a directed cycle exists in the digraph.
66.374 + ///
66.375 + /// \pre \ref findCycleMean() must be called before using this function.
66.376 + bool findCycle() {
66.377 + if (!_best_found) return false;
66.378 + IntNodeMap reached(_gr, -1);
66.379 + int r = _best_level + 1;
66.380 + Node u = _best_node;
66.381 + while (reached[u] < 0) {
66.382 + reached[u] = --r;
66.383 + u = _gr.source(_data[u][r].pred);
66.384 + }
66.385 + r = reached[u];
66.386 + Arc e = _data[u][r].pred;
66.387 + _cycle_path->addFront(e);
66.388 + _best_cost = _cost[e];
66.389 + _best_size = 1;
66.390 + Node v;
66.391 + while ((v = _gr.source(e)) != u) {
66.392 + e = _data[v][--r].pred;
66.393 + _cycle_path->addFront(e);
66.394 + _best_cost += _cost[e];
66.395 + ++_best_size;
66.396 + }
66.397 + return true;
66.398 + }
66.399 +
66.400 + /// @}
66.401 +
66.402 + /// \name Query Functions
66.403 + /// The results of the algorithm can be obtained using these
66.404 + /// functions.\n
66.405 + /// The algorithm should be executed before using them.
66.406 +
66.407 + /// @{
66.408 +
66.409 + /// \brief Return the total cost of the found cycle.
66.410 + ///
66.411 + /// This function returns the total cost of the found cycle.
66.412 + ///
66.413 + /// \pre \ref run() or \ref findCycleMean() must be called before
66.414 + /// using this function.
66.415 + Cost cycleCost() const {
66.416 + return static_cast<Cost>(_best_cost);
66.417 + }
66.418 +
66.419 + /// \brief Return the number of arcs on the found cycle.
66.420 + ///
66.421 + /// This function returns the number of arcs on the found cycle.
66.422 + ///
66.423 + /// \pre \ref run() or \ref findCycleMean() must be called before
66.424 + /// using this function.
66.425 + int cycleSize() const {
66.426 + return _best_size;
66.427 + }
66.428 +
66.429 + /// \brief Return the mean cost of the found cycle.
66.430 + ///
66.431 + /// This function returns the mean cost of the found cycle.
66.432 + ///
66.433 + /// \note <tt>alg.cycleMean()</tt> is just a shortcut of the
66.434 + /// following code.
66.435 + /// \code
66.436 + /// return static_cast<double>(alg.cycleCost()) / alg.cycleSize();
66.437 + /// \endcode
66.438 + ///
66.439 + /// \pre \ref run() or \ref findCycleMean() must be called before
66.440 + /// using this function.
66.441 + double cycleMean() const {
66.442 + return static_cast<double>(_best_cost) / _best_size;
66.443 + }
66.444 +
66.445 + /// \brief Return the found cycle.
66.446 + ///
66.447 + /// This function returns a const reference to the path structure
66.448 + /// storing the found cycle.
66.449 + ///
66.450 + /// \pre \ref run() or \ref findCycle() must be called before using
66.451 + /// this function.
66.452 + const Path& cycle() const {
66.453 + return *_cycle_path;
66.454 + }
66.455 +
66.456 + ///@}
66.457 +
66.458 + private:
66.459 +
66.460 + // Initialization
66.461 + void init() {
66.462 + if (!_cycle_path) {
66.463 + _local_path = true;
66.464 + _cycle_path = new Path;
66.465 + }
66.466 + _cycle_path->clear();
66.467 + _best_found = false;
66.468 + _best_cost = 0;
66.469 + _best_size = 1;
66.470 + _cycle_path->clear();
66.471 + for (NodeIt u(_gr); u != INVALID; ++u)
66.472 + _data[u].clear();
66.473 + }
66.474 +
66.475 + // Find strongly connected components and initialize _comp_nodes
66.476 + // and _out_arcs
66.477 + void findComponents() {
66.478 + _comp_num = stronglyConnectedComponents(_gr, _comp);
66.479 + _comp_nodes.resize(_comp_num);
66.480 + if (_comp_num == 1) {
66.481 + _comp_nodes[0].clear();
66.482 + for (NodeIt n(_gr); n != INVALID; ++n) {
66.483 + _comp_nodes[0].push_back(n);
66.484 + _out_arcs[n].clear();
66.485 + for (OutArcIt a(_gr, n); a != INVALID; ++a) {
66.486 + _out_arcs[n].push_back(a);
66.487 + }
66.488 + }
66.489 + } else {
66.490 + for (int i = 0; i < _comp_num; ++i)
66.491 + _comp_nodes[i].clear();
66.492 + for (NodeIt n(_gr); n != INVALID; ++n) {
66.493 + int k = _comp[n];
66.494 + _comp_nodes[k].push_back(n);
66.495 + _out_arcs[n].clear();
66.496 + for (OutArcIt a(_gr, n); a != INVALID; ++a) {
66.497 + if (_comp[_gr.target(a)] == k) _out_arcs[n].push_back(a);
66.498 + }
66.499 + }
66.500 + }
66.501 + }
66.502 +
66.503 + // Initialize path data for the current component
66.504 + bool initComponent(int comp) {
66.505 + _nodes = &(_comp_nodes[comp]);
66.506 + int n = _nodes->size();
66.507 + if (n < 1 || (n == 1 && _out_arcs[(*_nodes)[0]].size() == 0)) {
66.508 + return false;
66.509 + }
66.510 + for (int i = 0; i < n; ++i) {
66.511 + _data[(*_nodes)[i]].resize(n + 1, PathData(INF));
66.512 + }
66.513 + return true;
66.514 + }
66.515 +
66.516 + // Process all rounds of computing path data for the current component.
66.517 + // _data[v][k] is the cost of a shortest directed walk from the root
66.518 + // node to node v containing exactly k arcs.
66.519 + void processRounds() {
66.520 + Node start = (*_nodes)[0];
66.521 + _data[start][0] = PathData(0);
66.522 + _process.clear();
66.523 + _process.push_back(start);
66.524 +
66.525 + int k, n = _nodes->size();
66.526 + int next_check = 4;
66.527 + bool terminate = false;
66.528 + for (k = 1; k <= n && int(_process.size()) < n && !terminate; ++k) {
66.529 + processNextBuildRound(k);
66.530 + if (k == next_check || k == n) {
66.531 + terminate = checkTermination(k);
66.532 + next_check = next_check * 3 / 2;
66.533 + }
66.534 + }
66.535 + for ( ; k <= n && !terminate; ++k) {
66.536 + processNextFullRound(k);
66.537 + if (k == next_check || k == n) {
66.538 + terminate = checkTermination(k);
66.539 + next_check = next_check * 3 / 2;
66.540 + }
66.541 + }
66.542 + }
66.543 +
66.544 + // Process one round and rebuild _process
66.545 + void processNextBuildRound(int k) {
66.546 + std::vector<Node> next;
66.547 + Node u, v;
66.548 + Arc e;
66.549 + LargeCost d;
66.550 + for (int i = 0; i < int(_process.size()); ++i) {
66.551 + u = _process[i];
66.552 + for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
66.553 + e = _out_arcs[u][j];
66.554 + v = _gr.target(e);
66.555 + d = _data[u][k-1].dist + _cost[e];
66.556 + if (_tolerance.less(d, _data[v][k].dist)) {
66.557 + if (_data[v][k].dist == INF) next.push_back(v);
66.558 + _data[v][k] = PathData(d, e);
66.559 + }
66.560 + }
66.561 + }
66.562 + _process.swap(next);
66.563 + }
66.564 +
66.565 + // Process one round using _nodes instead of _process
66.566 + void processNextFullRound(int k) {
66.567 + Node u, v;
66.568 + Arc e;
66.569 + LargeCost d;
66.570 + for (int i = 0; i < int(_nodes->size()); ++i) {
66.571 + u = (*_nodes)[i];
66.572 + for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
66.573 + e = _out_arcs[u][j];
66.574 + v = _gr.target(e);
66.575 + d = _data[u][k-1].dist + _cost[e];
66.576 + if (_tolerance.less(d, _data[v][k].dist)) {
66.577 + _data[v][k] = PathData(d, e);
66.578 + }
66.579 + }
66.580 + }
66.581 + }
66.582 +
66.583 + // Check early termination
66.584 + bool checkTermination(int k) {
66.585 + typedef std::pair<int, int> Pair;
66.586 + typename GR::template NodeMap<Pair> level(_gr, Pair(-1, 0));
66.587 + typename GR::template NodeMap<LargeCost> pi(_gr);
66.588 + int n = _nodes->size();
66.589 + LargeCost cost;
66.590 + int size;
66.591 + Node u;
66.592 +
66.593 + // Search for cycles that are already found
66.594 + _curr_found = false;
66.595 + for (int i = 0; i < n; ++i) {
66.596 + u = (*_nodes)[i];
66.597 + if (_data[u][k].dist == INF) continue;
66.598 + for (int j = k; j >= 0; --j) {
66.599 + if (level[u].first == i && level[u].second > 0) {
66.600 + // A cycle is found
66.601 + cost = _data[u][level[u].second].dist - _data[u][j].dist;
66.602 + size = level[u].second - j;
66.603 + if (!_curr_found || cost * _curr_size < _curr_cost * size) {
66.604 + _curr_cost = cost;
66.605 + _curr_size = size;
66.606 + _curr_node = u;
66.607 + _curr_level = level[u].second;
66.608 + _curr_found = true;
66.609 + }
66.610 + }
66.611 + level[u] = Pair(i, j);
66.612 + if (j != 0) {
66.613 + u = _gr.source(_data[u][j].pred);
66.614 + }
66.615 + }
66.616 + }
66.617 +
66.618 + // If at least one cycle is found, check the optimality condition
66.619 + LargeCost d;
66.620 + if (_curr_found && k < n) {
66.621 + // Find node potentials
66.622 + for (int i = 0; i < n; ++i) {
66.623 + u = (*_nodes)[i];
66.624 + pi[u] = INF;
66.625 + for (int j = 0; j <= k; ++j) {
66.626 + if (_data[u][j].dist < INF) {
66.627 + d = _data[u][j].dist * _curr_size - j * _curr_cost;
66.628 + if (_tolerance.less(d, pi[u])) pi[u] = d;
66.629 + }
66.630 + }
66.631 + }
66.632 +
66.633 + // Check the optimality condition for all arcs
66.634 + bool done = true;
66.635 + for (ArcIt a(_gr); a != INVALID; ++a) {
66.636 + if (_tolerance.less(_cost[a] * _curr_size - _curr_cost,
66.637 + pi[_gr.target(a)] - pi[_gr.source(a)]) ) {
66.638 + done = false;
66.639 + break;
66.640 + }
66.641 + }
66.642 + return done;
66.643 + }
66.644 + return (k == n);
66.645 + }
66.646 +
66.647 + }; //class HartmannOrlinMmc
66.648 +
66.649 + ///@}
66.650 +
66.651 +} //namespace lemon
66.652 +
66.653 +#endif //LEMON_HARTMANN_ORLIN_MMC_H
67.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
67.2 +++ b/lemon/howard_mmc.h Tue Dec 20 18:15:14 2011 +0100
67.3 @@ -0,0 +1,605 @@
67.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
67.5 + *
67.6 + * This file is a part of LEMON, a generic C++ optimization library.
67.7 + *
67.8 + * Copyright (C) 2003-2010
67.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
67.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
67.11 + *
67.12 + * Permission to use, modify and distribute this software is granted
67.13 + * provided that this copyright notice appears in all copies. For
67.14 + * precise terms see the accompanying LICENSE file.
67.15 + *
67.16 + * This software is provided "AS IS" with no warranty of any kind,
67.17 + * express or implied, and with no claim as to its suitability for any
67.18 + * purpose.
67.19 + *
67.20 + */
67.21 +
67.22 +#ifndef LEMON_HOWARD_MMC_H
67.23 +#define LEMON_HOWARD_MMC_H
67.24 +
67.25 +/// \ingroup min_mean_cycle
67.26 +///
67.27 +/// \file
67.28 +/// \brief Howard's algorithm for finding a minimum mean cycle.
67.29 +
67.30 +#include <vector>
67.31 +#include <limits>
67.32 +#include <lemon/core.h>
67.33 +#include <lemon/path.h>
67.34 +#include <lemon/tolerance.h>
67.35 +#include <lemon/connectivity.h>
67.36 +
67.37 +namespace lemon {
67.38 +
67.39 + /// \brief Default traits class of HowardMmc class.
67.40 + ///
67.41 + /// Default traits class of HowardMmc class.
67.42 + /// \tparam GR The type of the digraph.
67.43 + /// \tparam CM The type of the cost map.
67.44 + /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
67.45 +#ifdef DOXYGEN
67.46 + template <typename GR, typename CM>
67.47 +#else
67.48 + template <typename GR, typename CM,
67.49 + bool integer = std::numeric_limits<typename CM::Value>::is_integer>
67.50 +#endif
67.51 + struct HowardMmcDefaultTraits
67.52 + {
67.53 + /// The type of the digraph
67.54 + typedef GR Digraph;
67.55 + /// The type of the cost map
67.56 + typedef CM CostMap;
67.57 + /// The type of the arc costs
67.58 + typedef typename CostMap::Value Cost;
67.59 +
67.60 + /// \brief The large cost type used for internal computations
67.61 + ///
67.62 + /// The large cost type used for internal computations.
67.63 + /// It is \c long \c long if the \c Cost type is integer,
67.64 + /// otherwise it is \c double.
67.65 + /// \c Cost must be convertible to \c LargeCost.
67.66 + typedef double LargeCost;
67.67 +
67.68 + /// The tolerance type used for internal computations
67.69 + typedef lemon::Tolerance<LargeCost> Tolerance;
67.70 +
67.71 + /// \brief The path type of the found cycles
67.72 + ///
67.73 + /// The path type of the found cycles.
67.74 + /// It must conform to the \ref lemon::concepts::Path "Path" concept
67.75 + /// and it must have an \c addBack() function.
67.76 + typedef lemon::Path<Digraph> Path;
67.77 + };
67.78 +
67.79 + // Default traits class for integer cost types
67.80 + template <typename GR, typename CM>
67.81 + struct HowardMmcDefaultTraits<GR, CM, true>
67.82 + {
67.83 + typedef GR Digraph;
67.84 + typedef CM CostMap;
67.85 + typedef typename CostMap::Value Cost;
67.86 +#ifdef LEMON_HAVE_LONG_LONG
67.87 + typedef long long LargeCost;
67.88 +#else
67.89 + typedef long LargeCost;
67.90 +#endif
67.91 + typedef lemon::Tolerance<LargeCost> Tolerance;
67.92 + typedef lemon::Path<Digraph> Path;
67.93 + };
67.94 +
67.95 +
67.96 + /// \addtogroup min_mean_cycle
67.97 + /// @{
67.98 +
67.99 + /// \brief Implementation of Howard's algorithm for finding a minimum
67.100 + /// mean cycle.
67.101 + ///
67.102 + /// This class implements Howard's policy iteration algorithm for finding
67.103 + /// a directed cycle of minimum mean cost in a digraph
67.104 + /// \ref amo93networkflows, \ref dasdan98minmeancycle.
67.105 + /// This class provides the most efficient algorithm for the
67.106 + /// minimum mean cycle problem, though the best known theoretical
67.107 + /// bound on its running time is exponential.
67.108 + ///
67.109 + /// \tparam GR The type of the digraph the algorithm runs on.
67.110 + /// \tparam CM The type of the cost map. The default
67.111 + /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
67.112 + /// \tparam TR The traits class that defines various types used by the
67.113 + /// algorithm. By default, it is \ref HowardMmcDefaultTraits
67.114 + /// "HowardMmcDefaultTraits<GR, CM>".
67.115 + /// In most cases, this parameter should not be set directly,
67.116 + /// consider to use the named template parameters instead.
67.117 +#ifdef DOXYGEN
67.118 + template <typename GR, typename CM, typename TR>
67.119 +#else
67.120 + template < typename GR,
67.121 + typename CM = typename GR::template ArcMap<int>,
67.122 + typename TR = HowardMmcDefaultTraits<GR, CM> >
67.123 +#endif
67.124 + class HowardMmc
67.125 + {
67.126 + public:
67.127 +
67.128 + /// The type of the digraph
67.129 + typedef typename TR::Digraph Digraph;
67.130 + /// The type of the cost map
67.131 + typedef typename TR::CostMap CostMap;
67.132 + /// The type of the arc costs
67.133 + typedef typename TR::Cost Cost;
67.134 +
67.135 + /// \brief The large cost type
67.136 + ///
67.137 + /// The large cost type used for internal computations.
67.138 + /// By default, it is \c long \c long if the \c Cost type is integer,
67.139 + /// otherwise it is \c double.
67.140 + typedef typename TR::LargeCost LargeCost;
67.141 +
67.142 + /// The tolerance type
67.143 + typedef typename TR::Tolerance Tolerance;
67.144 +
67.145 + /// \brief The path type of the found cycles
67.146 + ///
67.147 + /// The path type of the found cycles.
67.148 + /// Using the \ref HowardMmcDefaultTraits "default traits class",
67.149 + /// it is \ref lemon::Path "Path<Digraph>".
67.150 + typedef typename TR::Path Path;
67.151 +
67.152 + /// The \ref HowardMmcDefaultTraits "traits class" of the algorithm
67.153 + typedef TR Traits;
67.154 +
67.155 + private:
67.156 +
67.157 + TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
67.158 +
67.159 + // The digraph the algorithm runs on
67.160 + const Digraph &_gr;
67.161 + // The cost of the arcs
67.162 + const CostMap &_cost;
67.163 +
67.164 + // Data for the found cycles
67.165 + bool _curr_found, _best_found;
67.166 + LargeCost _curr_cost, _best_cost;
67.167 + int _curr_size, _best_size;
67.168 + Node _curr_node, _best_node;
67.169 +
67.170 + Path *_cycle_path;
67.171 + bool _local_path;
67.172 +
67.173 + // Internal data used by the algorithm
67.174 + typename Digraph::template NodeMap<Arc> _policy;
67.175 + typename Digraph::template NodeMap<bool> _reached;
67.176 + typename Digraph::template NodeMap<int> _level;
67.177 + typename Digraph::template NodeMap<LargeCost> _dist;
67.178 +
67.179 + // Data for storing the strongly connected components
67.180 + int _comp_num;
67.181 + typename Digraph::template NodeMap<int> _comp;
67.182 + std::vector<std::vector<Node> > _comp_nodes;
67.183 + std::vector<Node>* _nodes;
67.184 + typename Digraph::template NodeMap<std::vector<Arc> > _in_arcs;
67.185 +
67.186 + // Queue used for BFS search
67.187 + std::vector<Node> _queue;
67.188 + int _qfront, _qback;
67.189 +
67.190 + Tolerance _tolerance;
67.191 +
67.192 + // Infinite constant
67.193 + const LargeCost INF;
67.194 +
67.195 + public:
67.196 +
67.197 + /// \name Named Template Parameters
67.198 + /// @{
67.199 +
67.200 + template <typename T>
67.201 + struct SetLargeCostTraits : public Traits {
67.202 + typedef T LargeCost;
67.203 + typedef lemon::Tolerance<T> Tolerance;
67.204 + };
67.205 +
67.206 + /// \brief \ref named-templ-param "Named parameter" for setting
67.207 + /// \c LargeCost type.
67.208 + ///
67.209 + /// \ref named-templ-param "Named parameter" for setting \c LargeCost
67.210 + /// type. It is used for internal computations in the algorithm.
67.211 + template <typename T>
67.212 + struct SetLargeCost
67.213 + : public HowardMmc<GR, CM, SetLargeCostTraits<T> > {
67.214 + typedef HowardMmc<GR, CM, SetLargeCostTraits<T> > Create;
67.215 + };
67.216 +
67.217 + template <typename T>
67.218 + struct SetPathTraits : public Traits {
67.219 + typedef T Path;
67.220 + };
67.221 +
67.222 + /// \brief \ref named-templ-param "Named parameter" for setting
67.223 + /// \c %Path type.
67.224 + ///
67.225 + /// \ref named-templ-param "Named parameter" for setting the \c %Path
67.226 + /// type of the found cycles.
67.227 + /// It must conform to the \ref lemon::concepts::Path "Path" concept
67.228 + /// and it must have an \c addBack() function.
67.229 + template <typename T>
67.230 + struct SetPath
67.231 + : public HowardMmc<GR, CM, SetPathTraits<T> > {
67.232 + typedef HowardMmc<GR, CM, SetPathTraits<T> > Create;
67.233 + };
67.234 +
67.235 + /// @}
67.236 +
67.237 + protected:
67.238 +
67.239 + HowardMmc() {}
67.240 +
67.241 + public:
67.242 +
67.243 + /// \brief Constructor.
67.244 + ///
67.245 + /// The constructor of the class.
67.246 + ///
67.247 + /// \param digraph The digraph the algorithm runs on.
67.248 + /// \param cost The costs of the arcs.
67.249 + HowardMmc( const Digraph &digraph,
67.250 + const CostMap &cost ) :
67.251 + _gr(digraph), _cost(cost), _best_found(false),
67.252 + _best_cost(0), _best_size(1), _cycle_path(NULL), _local_path(false),
67.253 + _policy(digraph), _reached(digraph), _level(digraph), _dist(digraph),
67.254 + _comp(digraph), _in_arcs(digraph),
67.255 + INF(std::numeric_limits<LargeCost>::has_infinity ?
67.256 + std::numeric_limits<LargeCost>::infinity() :
67.257 + std::numeric_limits<LargeCost>::max())
67.258 + {}
67.259 +
67.260 + /// Destructor.
67.261 + ~HowardMmc() {
67.262 + if (_local_path) delete _cycle_path;
67.263 + }
67.264 +
67.265 + /// \brief Set the path structure for storing the found cycle.
67.266 + ///
67.267 + /// This function sets an external path structure for storing the
67.268 + /// found cycle.
67.269 + ///
67.270 + /// If you don't call this function before calling \ref run() or
67.271 + /// \ref findCycleMean(), it will allocate a local \ref Path "path"
67.272 + /// structure. The destuctor deallocates this automatically
67.273 + /// allocated object, of course.
67.274 + ///
67.275 + /// \note The algorithm calls only the \ref lemon::Path::addBack()
67.276 + /// "addBack()" function of the given path structure.
67.277 + ///
67.278 + /// \return <tt>(*this)</tt>
67.279 + HowardMmc& cycle(Path &path) {
67.280 + if (_local_path) {
67.281 + delete _cycle_path;
67.282 + _local_path = false;
67.283 + }
67.284 + _cycle_path = &path;
67.285 + return *this;
67.286 + }
67.287 +
67.288 + /// \brief Set the tolerance used by the algorithm.
67.289 + ///
67.290 + /// This function sets the tolerance object used by the algorithm.
67.291 + ///
67.292 + /// \return <tt>(*this)</tt>
67.293 + HowardMmc& tolerance(const Tolerance& tolerance) {
67.294 + _tolerance = tolerance;
67.295 + return *this;
67.296 + }
67.297 +
67.298 + /// \brief Return a const reference to the tolerance.
67.299 + ///
67.300 + /// This function returns a const reference to the tolerance object
67.301 + /// used by the algorithm.
67.302 + const Tolerance& tolerance() const {
67.303 + return _tolerance;
67.304 + }
67.305 +
67.306 + /// \name Execution control
67.307 + /// The simplest way to execute the algorithm is to call the \ref run()
67.308 + /// function.\n
67.309 + /// If you only need the minimum mean cost, you may call
67.310 + /// \ref findCycleMean().
67.311 +
67.312 + /// @{
67.313 +
67.314 + /// \brief Run the algorithm.
67.315 + ///
67.316 + /// This function runs the algorithm.
67.317 + /// It can be called more than once (e.g. if the underlying digraph
67.318 + /// and/or the arc costs have been modified).
67.319 + ///
67.320 + /// \return \c true if a directed cycle exists in the digraph.
67.321 + ///
67.322 + /// \note <tt>mmc.run()</tt> is just a shortcut of the following code.
67.323 + /// \code
67.324 + /// return mmc.findCycleMean() && mmc.findCycle();
67.325 + /// \endcode
67.326 + bool run() {
67.327 + return findCycleMean() && findCycle();
67.328 + }
67.329 +
67.330 + /// \brief Find the minimum cycle mean.
67.331 + ///
67.332 + /// This function finds the minimum mean cost of the directed
67.333 + /// cycles in the digraph.
67.334 + ///
67.335 + /// \return \c true if a directed cycle exists in the digraph.
67.336 + bool findCycleMean() {
67.337 + // Initialize and find strongly connected components
67.338 + init();
67.339 + findComponents();
67.340 +
67.341 + // Find the minimum cycle mean in the components
67.342 + for (int comp = 0; comp < _comp_num; ++comp) {
67.343 + // Find the minimum mean cycle in the current component
67.344 + if (!buildPolicyGraph(comp)) continue;
67.345 + while (true) {
67.346 + findPolicyCycle();
67.347 + if (!computeNodeDistances()) break;
67.348 + }
67.349 + // Update the best cycle (global minimum mean cycle)
67.350 + if ( _curr_found && (!_best_found ||
67.351 + _curr_cost * _best_size < _best_cost * _curr_size) ) {
67.352 + _best_found = true;
67.353 + _best_cost = _curr_cost;
67.354 + _best_size = _curr_size;
67.355 + _best_node = _curr_node;
67.356 + }
67.357 + }
67.358 + return _best_found;
67.359 + }
67.360 +
67.361 + /// \brief Find a minimum mean directed cycle.
67.362 + ///
67.363 + /// This function finds a directed cycle of minimum mean cost
67.364 + /// in the digraph using the data computed by findCycleMean().
67.365 + ///
67.366 + /// \return \c true if a directed cycle exists in the digraph.
67.367 + ///
67.368 + /// \pre \ref findCycleMean() must be called before using this function.
67.369 + bool findCycle() {
67.370 + if (!_best_found) return false;
67.371 + _cycle_path->addBack(_policy[_best_node]);
67.372 + for ( Node v = _best_node;
67.373 + (v = _gr.target(_policy[v])) != _best_node; ) {
67.374 + _cycle_path->addBack(_policy[v]);
67.375 + }
67.376 + return true;
67.377 + }
67.378 +
67.379 + /// @}
67.380 +
67.381 + /// \name Query Functions
67.382 + /// The results of the algorithm can be obtained using these
67.383 + /// functions.\n
67.384 + /// The algorithm should be executed before using them.
67.385 +
67.386 + /// @{
67.387 +
67.388 + /// \brief Return the total cost of the found cycle.
67.389 + ///
67.390 + /// This function returns the total cost of the found cycle.
67.391 + ///
67.392 + /// \pre \ref run() or \ref findCycleMean() must be called before
67.393 + /// using this function.
67.394 + Cost cycleCost() const {
67.395 + return static_cast<Cost>(_best_cost);
67.396 + }
67.397 +
67.398 + /// \brief Return the number of arcs on the found cycle.
67.399 + ///
67.400 + /// This function returns the number of arcs on the found cycle.
67.401 + ///
67.402 + /// \pre \ref run() or \ref findCycleMean() must be called before
67.403 + /// using this function.
67.404 + int cycleSize() const {
67.405 + return _best_size;
67.406 + }
67.407 +
67.408 + /// \brief Return the mean cost of the found cycle.
67.409 + ///
67.410 + /// This function returns the mean cost of the found cycle.
67.411 + ///
67.412 + /// \note <tt>alg.cycleMean()</tt> is just a shortcut of the
67.413 + /// following code.
67.414 + /// \code
67.415 + /// return static_cast<double>(alg.cycleCost()) / alg.cycleSize();
67.416 + /// \endcode
67.417 + ///
67.418 + /// \pre \ref run() or \ref findCycleMean() must be called before
67.419 + /// using this function.
67.420 + double cycleMean() const {
67.421 + return static_cast<double>(_best_cost) / _best_size;
67.422 + }
67.423 +
67.424 + /// \brief Return the found cycle.
67.425 + ///
67.426 + /// This function returns a const reference to the path structure
67.427 + /// storing the found cycle.
67.428 + ///
67.429 + /// \pre \ref run() or \ref findCycle() must be called before using
67.430 + /// this function.
67.431 + const Path& cycle() const {
67.432 + return *_cycle_path;
67.433 + }
67.434 +
67.435 + ///@}
67.436 +
67.437 + private:
67.438 +
67.439 + // Initialize
67.440 + void init() {
67.441 + if (!_cycle_path) {
67.442 + _local_path = true;
67.443 + _cycle_path = new Path;
67.444 + }
67.445 + _queue.resize(countNodes(_gr));
67.446 + _best_found = false;
67.447 + _best_cost = 0;
67.448 + _best_size = 1;
67.449 + _cycle_path->clear();
67.450 + }
67.451 +
67.452 + // Find strongly connected components and initialize _comp_nodes
67.453 + // and _in_arcs
67.454 + void findComponents() {
67.455 + _comp_num = stronglyConnectedComponents(_gr, _comp);
67.456 + _comp_nodes.resize(_comp_num);
67.457 + if (_comp_num == 1) {
67.458 + _comp_nodes[0].clear();
67.459 + for (NodeIt n(_gr); n != INVALID; ++n) {
67.460 + _comp_nodes[0].push_back(n);
67.461 + _in_arcs[n].clear();
67.462 + for (InArcIt a(_gr, n); a != INVALID; ++a) {
67.463 + _in_arcs[n].push_back(a);
67.464 + }
67.465 + }
67.466 + } else {
67.467 + for (int i = 0; i < _comp_num; ++i)
67.468 + _comp_nodes[i].clear();
67.469 + for (NodeIt n(_gr); n != INVALID; ++n) {
67.470 + int k = _comp[n];
67.471 + _comp_nodes[k].push_back(n);
67.472 + _in_arcs[n].clear();
67.473 + for (InArcIt a(_gr, n); a != INVALID; ++a) {
67.474 + if (_comp[_gr.source(a)] == k) _in_arcs[n].push_back(a);
67.475 + }
67.476 + }
67.477 + }
67.478 + }
67.479 +
67.480 + // Build the policy graph in the given strongly connected component
67.481 + // (the out-degree of every node is 1)
67.482 + bool buildPolicyGraph(int comp) {
67.483 + _nodes = &(_comp_nodes[comp]);
67.484 + if (_nodes->size() < 1 ||
67.485 + (_nodes->size() == 1 && _in_arcs[(*_nodes)[0]].size() == 0)) {
67.486 + return false;
67.487 + }
67.488 + for (int i = 0; i < int(_nodes->size()); ++i) {
67.489 + _dist[(*_nodes)[i]] = INF;
67.490 + }
67.491 + Node u, v;
67.492 + Arc e;
67.493 + for (int i = 0; i < int(_nodes->size()); ++i) {
67.494 + v = (*_nodes)[i];
67.495 + for (int j = 0; j < int(_in_arcs[v].size()); ++j) {
67.496 + e = _in_arcs[v][j];
67.497 + u = _gr.source(e);
67.498 + if (_cost[e] < _dist[u]) {
67.499 + _dist[u] = _cost[e];
67.500 + _policy[u] = e;
67.501 + }
67.502 + }
67.503 + }
67.504 + return true;
67.505 + }
67.506 +
67.507 + // Find the minimum mean cycle in the policy graph
67.508 + void findPolicyCycle() {
67.509 + for (int i = 0; i < int(_nodes->size()); ++i) {
67.510 + _level[(*_nodes)[i]] = -1;
67.511 + }
67.512 + LargeCost ccost;
67.513 + int csize;
67.514 + Node u, v;
67.515 + _curr_found = false;
67.516 + for (int i = 0; i < int(_nodes->size()); ++i) {
67.517 + u = (*_nodes)[i];
67.518 + if (_level[u] >= 0) continue;
67.519 + for (; _level[u] < 0; u = _gr.target(_policy[u])) {
67.520 + _level[u] = i;
67.521 + }
67.522 + if (_level[u] == i) {
67.523 + // A cycle is found
67.524 + ccost = _cost[_policy[u]];
67.525 + csize = 1;
67.526 + for (v = u; (v = _gr.target(_policy[v])) != u; ) {
67.527 + ccost += _cost[_policy[v]];
67.528 + ++csize;
67.529 + }
67.530 + if ( !_curr_found ||
67.531 + (ccost * _curr_size < _curr_cost * csize) ) {
67.532 + _curr_found = true;
67.533 + _curr_cost = ccost;
67.534 + _curr_size = csize;
67.535 + _curr_node = u;
67.536 + }
67.537 + }
67.538 + }
67.539 + }
67.540 +
67.541 + // Contract the policy graph and compute node distances
67.542 + bool computeNodeDistances() {
67.543 + // Find the component of the main cycle and compute node distances
67.544 + // using reverse BFS
67.545 + for (int i = 0; i < int(_nodes->size()); ++i) {
67.546 + _reached[(*_nodes)[i]] = false;
67.547 + }
67.548 + _qfront = _qback = 0;
67.549 + _queue[0] = _curr_node;
67.550 + _reached[_curr_node] = true;
67.551 + _dist[_curr_node] = 0;
67.552 + Node u, v;
67.553 + Arc e;
67.554 + while (_qfront <= _qback) {
67.555 + v = _queue[_qfront++];
67.556 + for (int j = 0; j < int(_in_arcs[v].size()); ++j) {
67.557 + e = _in_arcs[v][j];
67.558 + u = _gr.source(e);
67.559 + if (_policy[u] == e && !_reached[u]) {
67.560 + _reached[u] = true;
67.561 + _dist[u] = _dist[v] + _cost[e] * _curr_size - _curr_cost;
67.562 + _queue[++_qback] = u;
67.563 + }
67.564 + }
67.565 + }
67.566 +
67.567 + // Connect all other nodes to this component and compute node
67.568 + // distances using reverse BFS
67.569 + _qfront = 0;
67.570 + while (_qback < int(_nodes->size())-1) {
67.571 + v = _queue[_qfront++];
67.572 + for (int j = 0; j < int(_in_arcs[v].size()); ++j) {
67.573 + e = _in_arcs[v][j];
67.574 + u = _gr.source(e);
67.575 + if (!_reached[u]) {
67.576 + _reached[u] = true;
67.577 + _policy[u] = e;
67.578 + _dist[u] = _dist[v] + _cost[e] * _curr_size - _curr_cost;
67.579 + _queue[++_qback] = u;
67.580 + }
67.581 + }
67.582 + }
67.583 +
67.584 + // Improve node distances
67.585 + bool improved = false;
67.586 + for (int i = 0; i < int(_nodes->size()); ++i) {
67.587 + v = (*_nodes)[i];
67.588 + for (int j = 0; j < int(_in_arcs[v].size()); ++j) {
67.589 + e = _in_arcs[v][j];
67.590 + u = _gr.source(e);
67.591 + LargeCost delta = _dist[v] + _cost[e] * _curr_size - _curr_cost;
67.592 + if (_tolerance.less(delta, _dist[u])) {
67.593 + _dist[u] = delta;
67.594 + _policy[u] = e;
67.595 + improved = true;
67.596 + }
67.597 + }
67.598 + }
67.599 + return improved;
67.600 + }
67.601 +
67.602 + }; //class HowardMmc
67.603 +
67.604 + ///@}
67.605 +
67.606 +} //namespace lemon
67.607 +
67.608 +#endif //LEMON_HOWARD_MMC_H
68.1 --- a/lemon/hypercube_graph.h Tue Dec 20 17:44:38 2011 +0100
68.2 +++ b/lemon/hypercube_graph.h Tue Dec 20 18:15:14 2011 +0100
68.3 @@ -262,7 +262,7 @@
68.4 return arc._id >> _dim;
68.5 }
68.6
68.7 - int index(Node node) const {
68.8 + static int index(Node node) {
68.9 return node._id;
68.10 }
68.11
68.12 @@ -282,17 +282,23 @@
68.13 ///
68.14 /// \brief Hypercube graph class
68.15 ///
68.16 - /// This class implements a special graph type. The nodes of the graph
68.17 - /// are indiced with integers with at most \c dim binary digits.
68.18 + /// HypercubeGraph implements a special graph type. The nodes of the
68.19 + /// graph are indexed with integers having at most \c dim binary digits.
68.20 /// Two nodes are connected in the graph if and only if their indices
68.21 /// differ only on one position in the binary form.
68.22 + /// This class is completely static and it needs constant memory space.
68.23 + /// Thus you can neither add nor delete nodes or edges, however,
68.24 + /// the structure can be resized using resize().
68.25 + ///
68.26 + /// This type fully conforms to the \ref concepts::Graph "Graph concept".
68.27 + /// Most of its member functions and nested classes are documented
68.28 + /// only in the concept class.
68.29 + ///
68.30 + /// This class provides constant time counting for nodes, edges and arcs.
68.31 ///
68.32 /// \note The type of the indices is chosen to \c int for efficiency
68.33 /// reasons. Thus the maximum dimension of this implementation is 26
68.34 /// (assuming that the size of \c int is 32 bit).
68.35 - ///
68.36 - /// This graph type fully conforms to the \ref concepts::Graph
68.37 - /// "Graph concept".
68.38 class HypercubeGraph : public ExtendedHypercubeGraphBase {
68.39 typedef ExtendedHypercubeGraphBase Parent;
68.40
68.41 @@ -303,6 +309,21 @@
68.42 /// Constructs a hypercube graph with \c dim dimensions.
68.43 HypercubeGraph(int dim) { construct(dim); }
68.44
68.45 + /// \brief Resizes the graph
68.46 + ///
68.47 + /// This function resizes the graph. It fully destroys and
68.48 + /// rebuilds the structure, therefore the maps of the graph will be
68.49 + /// reallocated automatically and the previous values will be lost.
68.50 + void resize(int dim) {
68.51 + Parent::notifier(Arc()).clear();
68.52 + Parent::notifier(Edge()).clear();
68.53 + Parent::notifier(Node()).clear();
68.54 + construct(dim);
68.55 + Parent::notifier(Node()).build();
68.56 + Parent::notifier(Edge()).build();
68.57 + Parent::notifier(Arc()).build();
68.58 + }
68.59 +
68.60 /// \brief The number of dimensions.
68.61 ///
68.62 /// Gives back the number of dimensions.
68.63 @@ -320,7 +341,7 @@
68.64 /// \brief The dimension id of an edge.
68.65 ///
68.66 /// Gives back the dimension id of the given edge.
68.67 - /// It is in the [0..dim-1] range.
68.68 + /// It is in the range <tt>[0..dim-1]</tt>.
68.69 int dimension(Edge edge) const {
68.70 return Parent::dimension(edge);
68.71 }
68.72 @@ -328,7 +349,7 @@
68.73 /// \brief The dimension id of an arc.
68.74 ///
68.75 /// Gives back the dimension id of the given arc.
68.76 - /// It is in the [0..dim-1] range.
68.77 + /// It is in the range <tt>[0..dim-1]</tt>.
68.78 int dimension(Arc arc) const {
68.79 return Parent::dimension(arc);
68.80 }
68.81 @@ -337,7 +358,7 @@
68.82 ///
68.83 /// Gives back the index of the given node.
68.84 /// The lower bits of the integer describes the node.
68.85 - int index(Node node) const {
68.86 + static int index(Node node) {
68.87 return Parent::index(node);
68.88 }
68.89
69.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
69.2 +++ b/lemon/karp_mmc.h Tue Dec 20 18:15:14 2011 +0100
69.3 @@ -0,0 +1,590 @@
69.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
69.5 + *
69.6 + * This file is a part of LEMON, a generic C++ optimization library.
69.7 + *
69.8 + * Copyright (C) 2003-2010
69.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
69.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
69.11 + *
69.12 + * Permission to use, modify and distribute this software is granted
69.13 + * provided that this copyright notice appears in all copies. For
69.14 + * precise terms see the accompanying LICENSE file.
69.15 + *
69.16 + * This software is provided "AS IS" with no warranty of any kind,
69.17 + * express or implied, and with no claim as to its suitability for any
69.18 + * purpose.
69.19 + *
69.20 + */
69.21 +
69.22 +#ifndef LEMON_KARP_MMC_H
69.23 +#define LEMON_KARP_MMC_H
69.24 +
69.25 +/// \ingroup min_mean_cycle
69.26 +///
69.27 +/// \file
69.28 +/// \brief Karp's algorithm for finding a minimum mean cycle.
69.29 +
69.30 +#include <vector>
69.31 +#include <limits>
69.32 +#include <lemon/core.h>
69.33 +#include <lemon/path.h>
69.34 +#include <lemon/tolerance.h>
69.35 +#include <lemon/connectivity.h>
69.36 +
69.37 +namespace lemon {
69.38 +
69.39 + /// \brief Default traits class of KarpMmc class.
69.40 + ///
69.41 + /// Default traits class of KarpMmc class.
69.42 + /// \tparam GR The type of the digraph.
69.43 + /// \tparam CM The type of the cost map.
69.44 + /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
69.45 +#ifdef DOXYGEN
69.46 + template <typename GR, typename CM>
69.47 +#else
69.48 + template <typename GR, typename CM,
69.49 + bool integer = std::numeric_limits<typename CM::Value>::is_integer>
69.50 +#endif
69.51 + struct KarpMmcDefaultTraits
69.52 + {
69.53 + /// The type of the digraph
69.54 + typedef GR Digraph;
69.55 + /// The type of the cost map
69.56 + typedef CM CostMap;
69.57 + /// The type of the arc costs
69.58 + typedef typename CostMap::Value Cost;
69.59 +
69.60 + /// \brief The large cost type used for internal computations
69.61 + ///
69.62 + /// The large cost type used for internal computations.
69.63 + /// It is \c long \c long if the \c Cost type is integer,
69.64 + /// otherwise it is \c double.
69.65 + /// \c Cost must be convertible to \c LargeCost.
69.66 + typedef double LargeCost;
69.67 +
69.68 + /// The tolerance type used for internal computations
69.69 + typedef lemon::Tolerance<LargeCost> Tolerance;
69.70 +
69.71 + /// \brief The path type of the found cycles
69.72 + ///
69.73 + /// The path type of the found cycles.
69.74 + /// It must conform to the \ref lemon::concepts::Path "Path" concept
69.75 + /// and it must have an \c addFront() function.
69.76 + typedef lemon::Path<Digraph> Path;
69.77 + };
69.78 +
69.79 + // Default traits class for integer cost types
69.80 + template <typename GR, typename CM>
69.81 + struct KarpMmcDefaultTraits<GR, CM, true>
69.82 + {
69.83 + typedef GR Digraph;
69.84 + typedef CM CostMap;
69.85 + typedef typename CostMap::Value Cost;
69.86 +#ifdef LEMON_HAVE_LONG_LONG
69.87 + typedef long long LargeCost;
69.88 +#else
69.89 + typedef long LargeCost;
69.90 +#endif
69.91 + typedef lemon::Tolerance<LargeCost> Tolerance;
69.92 + typedef lemon::Path<Digraph> Path;
69.93 + };
69.94 +
69.95 +
69.96 + /// \addtogroup min_mean_cycle
69.97 + /// @{
69.98 +
69.99 + /// \brief Implementation of Karp's algorithm for finding a minimum
69.100 + /// mean cycle.
69.101 + ///
69.102 + /// This class implements Karp's algorithm for finding a directed
69.103 + /// cycle of minimum mean cost in a digraph
69.104 + /// \ref amo93networkflows, \ref dasdan98minmeancycle.
69.105 + /// It runs in time O(ne) and uses space O(n<sup>2</sup>+e).
69.106 + ///
69.107 + /// \tparam GR The type of the digraph the algorithm runs on.
69.108 + /// \tparam CM The type of the cost map. The default
69.109 + /// map type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
69.110 + /// \tparam TR The traits class that defines various types used by the
69.111 + /// algorithm. By default, it is \ref KarpMmcDefaultTraits
69.112 + /// "KarpMmcDefaultTraits<GR, CM>".
69.113 + /// In most cases, this parameter should not be set directly,
69.114 + /// consider to use the named template parameters instead.
69.115 +#ifdef DOXYGEN
69.116 + template <typename GR, typename CM, typename TR>
69.117 +#else
69.118 + template < typename GR,
69.119 + typename CM = typename GR::template ArcMap<int>,
69.120 + typename TR = KarpMmcDefaultTraits<GR, CM> >
69.121 +#endif
69.122 + class KarpMmc
69.123 + {
69.124 + public:
69.125 +
69.126 + /// The type of the digraph
69.127 + typedef typename TR::Digraph Digraph;
69.128 + /// The type of the cost map
69.129 + typedef typename TR::CostMap CostMap;
69.130 + /// The type of the arc costs
69.131 + typedef typename TR::Cost Cost;
69.132 +
69.133 + /// \brief The large cost type
69.134 + ///
69.135 + /// The large cost type used for internal computations.
69.136 + /// By default, it is \c long \c long if the \c Cost type is integer,
69.137 + /// otherwise it is \c double.
69.138 + typedef typename TR::LargeCost LargeCost;
69.139 +
69.140 + /// The tolerance type
69.141 + typedef typename TR::Tolerance Tolerance;
69.142 +
69.143 + /// \brief The path type of the found cycles
69.144 + ///
69.145 + /// The path type of the found cycles.
69.146 + /// Using the \ref KarpMmcDefaultTraits "default traits class",
69.147 + /// it is \ref lemon::Path "Path<Digraph>".
69.148 + typedef typename TR::Path Path;
69.149 +
69.150 + /// The \ref KarpMmcDefaultTraits "traits class" of the algorithm
69.151 + typedef TR Traits;
69.152 +
69.153 + private:
69.154 +
69.155 + TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
69.156 +
69.157 + // Data sturcture for path data
69.158 + struct PathData
69.159 + {
69.160 + LargeCost dist;
69.161 + Arc pred;
69.162 + PathData(LargeCost d, Arc p = INVALID) :
69.163 + dist(d), pred(p) {}
69.164 + };
69.165 +
69.166 + typedef typename Digraph::template NodeMap<std::vector<PathData> >
69.167 + PathDataNodeMap;
69.168 +
69.169 + private:
69.170 +
69.171 + // The digraph the algorithm runs on
69.172 + const Digraph &_gr;
69.173 + // The cost of the arcs
69.174 + const CostMap &_cost;
69.175 +
69.176 + // Data for storing the strongly connected components
69.177 + int _comp_num;
69.178 + typename Digraph::template NodeMap<int> _comp;
69.179 + std::vector<std::vector<Node> > _comp_nodes;
69.180 + std::vector<Node>* _nodes;
69.181 + typename Digraph::template NodeMap<std::vector<Arc> > _out_arcs;
69.182 +
69.183 + // Data for the found cycle
69.184 + LargeCost _cycle_cost;
69.185 + int _cycle_size;
69.186 + Node _cycle_node;
69.187 +
69.188 + Path *_cycle_path;
69.189 + bool _local_path;
69.190 +
69.191 + // Node map for storing path data
69.192 + PathDataNodeMap _data;
69.193 + // The processed nodes in the last round
69.194 + std::vector<Node> _process;
69.195 +
69.196 + Tolerance _tolerance;
69.197 +
69.198 + // Infinite constant
69.199 + const LargeCost INF;
69.200 +
69.201 + public:
69.202 +
69.203 + /// \name Named Template Parameters
69.204 + /// @{
69.205 +
69.206 + template <typename T>
69.207 + struct SetLargeCostTraits : public Traits {
69.208 + typedef T LargeCost;
69.209 + typedef lemon::Tolerance<T> Tolerance;
69.210 + };
69.211 +
69.212 + /// \brief \ref named-templ-param "Named parameter" for setting
69.213 + /// \c LargeCost type.
69.214 + ///
69.215 + /// \ref named-templ-param "Named parameter" for setting \c LargeCost
69.216 + /// type. It is used for internal computations in the algorithm.
69.217 + template <typename T>
69.218 + struct SetLargeCost
69.219 + : public KarpMmc<GR, CM, SetLargeCostTraits<T> > {
69.220 + typedef KarpMmc<GR, CM, SetLargeCostTraits<T> > Create;
69.221 + };
69.222 +
69.223 + template <typename T>
69.224 + struct SetPathTraits : public Traits {
69.225 + typedef T Path;
69.226 + };
69.227 +
69.228 + /// \brief \ref named-templ-param "Named parameter" for setting
69.229 + /// \c %Path type.
69.230 + ///
69.231 + /// \ref named-templ-param "Named parameter" for setting the \c %Path
69.232 + /// type of the found cycles.
69.233 + /// It must conform to the \ref lemon::concepts::Path "Path" concept
69.234 + /// and it must have an \c addFront() function.
69.235 + template <typename T>
69.236 + struct SetPath
69.237 + : public KarpMmc<GR, CM, SetPathTraits<T> > {
69.238 + typedef KarpMmc<GR, CM, SetPathTraits<T> > Create;
69.239 + };
69.240 +
69.241 + /// @}
69.242 +
69.243 + protected:
69.244 +
69.245 + KarpMmc() {}
69.246 +
69.247 + public:
69.248 +
69.249 + /// \brief Constructor.
69.250 + ///
69.251 + /// The constructor of the class.
69.252 + ///
69.253 + /// \param digraph The digraph the algorithm runs on.
69.254 + /// \param cost The costs of the arcs.
69.255 + KarpMmc( const Digraph &digraph,
69.256 + const CostMap &cost ) :
69.257 + _gr(digraph), _cost(cost), _comp(digraph), _out_arcs(digraph),
69.258 + _cycle_cost(0), _cycle_size(1), _cycle_node(INVALID),
69.259 + _cycle_path(NULL), _local_path(false), _data(digraph),
69.260 + INF(std::numeric_limits<LargeCost>::has_infinity ?
69.261 + std::numeric_limits<LargeCost>::infinity() :
69.262 + std::numeric_limits<LargeCost>::max())
69.263 + {}
69.264 +
69.265 + /// Destructor.
69.266 + ~KarpMmc() {
69.267 + if (_local_path) delete _cycle_path;
69.268 + }
69.269 +
69.270 + /// \brief Set the path structure for storing the found cycle.
69.271 + ///
69.272 + /// This function sets an external path structure for storing the
69.273 + /// found cycle.
69.274 + ///
69.275 + /// If you don't call this function before calling \ref run() or
69.276 + /// \ref findCycleMean(), it will allocate a local \ref Path "path"
69.277 + /// structure. The destuctor deallocates this automatically
69.278 + /// allocated object, of course.
69.279 + ///
69.280 + /// \note The algorithm calls only the \ref lemon::Path::addFront()
69.281 + /// "addFront()" function of the given path structure.
69.282 + ///
69.283 + /// \return <tt>(*this)</tt>
69.284 + KarpMmc& cycle(Path &path) {
69.285 + if (_local_path) {
69.286 + delete _cycle_path;
69.287 + _local_path = false;
69.288 + }
69.289 + _cycle_path = &path;
69.290 + return *this;
69.291 + }
69.292 +
69.293 + /// \brief Set the tolerance used by the algorithm.
69.294 + ///
69.295 + /// This function sets the tolerance object used by the algorithm.
69.296 + ///
69.297 + /// \return <tt>(*this)</tt>
69.298 + KarpMmc& tolerance(const Tolerance& tolerance) {
69.299 + _tolerance = tolerance;
69.300 + return *this;
69.301 + }
69.302 +
69.303 + /// \brief Return a const reference to the tolerance.
69.304 + ///
69.305 + /// This function returns a const reference to the tolerance object
69.306 + /// used by the algorithm.
69.307 + const Tolerance& tolerance() const {
69.308 + return _tolerance;
69.309 + }
69.310 +
69.311 + /// \name Execution control
69.312 + /// The simplest way to execute the algorithm is to call the \ref run()
69.313 + /// function.\n
69.314 + /// If you only need the minimum mean cost, you may call
69.315 + /// \ref findCycleMean().
69.316 +
69.317 + /// @{
69.318 +
69.319 + /// \brief Run the algorithm.
69.320 + ///
69.321 + /// This function runs the algorithm.
69.322 + /// It can be called more than once (e.g. if the underlying digraph
69.323 + /// and/or the arc costs have been modified).
69.324 + ///
69.325 + /// \return \c true if a directed cycle exists in the digraph.
69.326 + ///
69.327 + /// \note <tt>mmc.run()</tt> is just a shortcut of the following code.
69.328 + /// \code
69.329 + /// return mmc.findCycleMean() && mmc.findCycle();
69.330 + /// \endcode
69.331 + bool run() {
69.332 + return findCycleMean() && findCycle();
69.333 + }
69.334 +
69.335 + /// \brief Find the minimum cycle mean.
69.336 + ///
69.337 + /// This function finds the minimum mean cost of the directed
69.338 + /// cycles in the digraph.
69.339 + ///
69.340 + /// \return \c true if a directed cycle exists in the digraph.
69.341 + bool findCycleMean() {
69.342 + // Initialization and find strongly connected components
69.343 + init();
69.344 + findComponents();
69.345 +
69.346 + // Find the minimum cycle mean in the components
69.347 + for (int comp = 0; comp < _comp_num; ++comp) {
69.348 + if (!initComponent(comp)) continue;
69.349 + processRounds();
69.350 + updateMinMean();
69.351 + }
69.352 + return (_cycle_node != INVALID);
69.353 + }
69.354 +
69.355 + /// \brief Find a minimum mean directed cycle.
69.356 + ///
69.357 + /// This function finds a directed cycle of minimum mean cost
69.358 + /// in the digraph using the data computed by findCycleMean().
69.359 + ///
69.360 + /// \return \c true if a directed cycle exists in the digraph.
69.361 + ///
69.362 + /// \pre \ref findCycleMean() must be called before using this function.
69.363 + bool findCycle() {
69.364 + if (_cycle_node == INVALID) return false;
69.365 + IntNodeMap reached(_gr, -1);
69.366 + int r = _data[_cycle_node].size();
69.367 + Node u = _cycle_node;
69.368 + while (reached[u] < 0) {
69.369 + reached[u] = --r;
69.370 + u = _gr.source(_data[u][r].pred);
69.371 + }
69.372 + r = reached[u];
69.373 + Arc e = _data[u][r].pred;
69.374 + _cycle_path->addFront(e);
69.375 + _cycle_cost = _cost[e];
69.376 + _cycle_size = 1;
69.377 + Node v;
69.378 + while ((v = _gr.source(e)) != u) {
69.379 + e = _data[v][--r].pred;
69.380 + _cycle_path->addFront(e);
69.381 + _cycle_cost += _cost[e];
69.382 + ++_cycle_size;
69.383 + }
69.384 + return true;
69.385 + }
69.386 +
69.387 + /// @}
69.388 +
69.389 + /// \name Query Functions
69.390 + /// The results of the algorithm can be obtained using these
69.391 + /// functions.\n
69.392 + /// The algorithm should be executed before using them.
69.393 +
69.394 + /// @{
69.395 +
69.396 + /// \brief Return the total cost of the found cycle.
69.397 + ///
69.398 + /// This function returns the total cost of the found cycle.
69.399 + ///
69.400 + /// \pre \ref run() or \ref findCycleMean() must be called before
69.401 + /// using this function.
69.402 + Cost cycleCost() const {
69.403 + return static_cast<Cost>(_cycle_cost);
69.404 + }
69.405 +
69.406 + /// \brief Return the number of arcs on the found cycle.
69.407 + ///
69.408 + /// This function returns the number of arcs on the found cycle.
69.409 + ///
69.410 + /// \pre \ref run() or \ref findCycleMean() must be called before
69.411 + /// using this function.
69.412 + int cycleSize() const {
69.413 + return _cycle_size;
69.414 + }
69.415 +
69.416 + /// \brief Return the mean cost of the found cycle.
69.417 + ///
69.418 + /// This function returns the mean cost of the found cycle.
69.419 + ///
69.420 + /// \note <tt>alg.cycleMean()</tt> is just a shortcut of the
69.421 + /// following code.
69.422 + /// \code
69.423 + /// return static_cast<double>(alg.cycleCost()) / alg.cycleSize();
69.424 + /// \endcode
69.425 + ///
69.426 + /// \pre \ref run() or \ref findCycleMean() must be called before
69.427 + /// using this function.
69.428 + double cycleMean() const {
69.429 + return static_cast<double>(_cycle_cost) / _cycle_size;
69.430 + }
69.431 +
69.432 + /// \brief Return the found cycle.
69.433 + ///
69.434 + /// This function returns a const reference to the path structure
69.435 + /// storing the found cycle.
69.436 + ///
69.437 + /// \pre \ref run() or \ref findCycle() must be called before using
69.438 + /// this function.
69.439 + const Path& cycle() const {
69.440 + return *_cycle_path;
69.441 + }
69.442 +
69.443 + ///@}
69.444 +
69.445 + private:
69.446 +
69.447 + // Initialization
69.448 + void init() {
69.449 + if (!_cycle_path) {
69.450 + _local_path = true;
69.451 + _cycle_path = new Path;
69.452 + }
69.453 + _cycle_path->clear();
69.454 + _cycle_cost = 0;
69.455 + _cycle_size = 1;
69.456 + _cycle_node = INVALID;
69.457 + for (NodeIt u(_gr); u != INVALID; ++u)
69.458 + _data[u].clear();
69.459 + }
69.460 +
69.461 + // Find strongly connected components and initialize _comp_nodes
69.462 + // and _out_arcs
69.463 + void findComponents() {
69.464 + _comp_num = stronglyConnectedComponents(_gr, _comp);
69.465 + _comp_nodes.resize(_comp_num);
69.466 + if (_comp_num == 1) {
69.467 + _comp_nodes[0].clear();
69.468 + for (NodeIt n(_gr); n != INVALID; ++n) {
69.469 + _comp_nodes[0].push_back(n);
69.470 + _out_arcs[n].clear();
69.471 + for (OutArcIt a(_gr, n); a != INVALID; ++a) {
69.472 + _out_arcs[n].push_back(a);
69.473 + }
69.474 + }
69.475 + } else {
69.476 + for (int i = 0; i < _comp_num; ++i)
69.477 + _comp_nodes[i].clear();
69.478 + for (NodeIt n(_gr); n != INVALID; ++n) {
69.479 + int k = _comp[n];
69.480 + _comp_nodes[k].push_back(n);
69.481 + _out_arcs[n].clear();
69.482 + for (OutArcIt a(_gr, n); a != INVALID; ++a) {
69.483 + if (_comp[_gr.target(a)] == k) _out_arcs[n].push_back(a);
69.484 + }
69.485 + }
69.486 + }
69.487 + }
69.488 +
69.489 + // Initialize path data for the current component
69.490 + bool initComponent(int comp) {
69.491 + _nodes = &(_comp_nodes[comp]);
69.492 + int n = _nodes->size();
69.493 + if (n < 1 || (n == 1 && _out_arcs[(*_nodes)[0]].size() == 0)) {
69.494 + return false;
69.495 + }
69.496 + for (int i = 0; i < n; ++i) {
69.497 + _data[(*_nodes)[i]].resize(n + 1, PathData(INF));
69.498 + }
69.499 + return true;
69.500 + }
69.501 +
69.502 + // Process all rounds of computing path data for the current component.
69.503 + // _data[v][k] is the cost of a shortest directed walk from the root
69.504 + // node to node v containing exactly k arcs.
69.505 + void processRounds() {
69.506 + Node start = (*_nodes)[0];
69.507 + _data[start][0] = PathData(0);
69.508 + _process.clear();
69.509 + _process.push_back(start);
69.510 +
69.511 + int k, n = _nodes->size();
69.512 + for (k = 1; k <= n && int(_process.size()) < n; ++k) {
69.513 + processNextBuildRound(k);
69.514 + }
69.515 + for ( ; k <= n; ++k) {
69.516 + processNextFullRound(k);
69.517 + }
69.518 + }
69.519 +
69.520 + // Process one round and rebuild _process
69.521 + void processNextBuildRound(int k) {
69.522 + std::vector<Node> next;
69.523 + Node u, v;
69.524 + Arc e;
69.525 + LargeCost d;
69.526 + for (int i = 0; i < int(_process.size()); ++i) {
69.527 + u = _process[i];
69.528 + for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
69.529 + e = _out_arcs[u][j];
69.530 + v = _gr.target(e);
69.531 + d = _data[u][k-1].dist + _cost[e];
69.532 + if (_tolerance.less(d, _data[v][k].dist)) {
69.533 + if (_data[v][k].dist == INF) next.push_back(v);
69.534 + _data[v][k] = PathData(d, e);
69.535 + }
69.536 + }
69.537 + }
69.538 + _process.swap(next);
69.539 + }
69.540 +
69.541 + // Process one round using _nodes instead of _process
69.542 + void processNextFullRound(int k) {
69.543 + Node u, v;
69.544 + Arc e;
69.545 + LargeCost d;
69.546 + for (int i = 0; i < int(_nodes->size()); ++i) {
69.547 + u = (*_nodes)[i];
69.548 + for (int j = 0; j < int(_out_arcs[u].size()); ++j) {
69.549 + e = _out_arcs[u][j];
69.550 + v = _gr.target(e);
69.551 + d = _data[u][k-1].dist + _cost[e];
69.552 + if (_tolerance.less(d, _data[v][k].dist)) {
69.553 + _data[v][k] = PathData(d, e);
69.554 + }
69.555 + }
69.556 + }
69.557 + }
69.558 +
69.559 + // Update the minimum cycle mean
69.560 + void updateMinMean() {
69.561 + int n = _nodes->size();
69.562 + for (int i = 0; i < n; ++i) {
69.563 + Node u = (*_nodes)[i];
69.564 + if (_data[u][n].dist == INF) continue;
69.565 + LargeCost cost, max_cost = 0;
69.566 + int size, max_size = 1;
69.567 + bool found_curr = false;
69.568 + for (int k = 0; k < n; ++k) {
69.569 + if (_data[u][k].dist == INF) continue;
69.570 + cost = _data[u][n].dist - _data[u][k].dist;
69.571 + size = n - k;
69.572 + if (!found_curr || cost * max_size > max_cost * size) {
69.573 + found_curr = true;
69.574 + max_cost = cost;
69.575 + max_size = size;
69.576 + }
69.577 + }
69.578 + if ( found_curr && (_cycle_node == INVALID ||
69.579 + max_cost * _cycle_size < _cycle_cost * max_size) ) {
69.580 + _cycle_cost = max_cost;
69.581 + _cycle_size = max_size;
69.582 + _cycle_node = u;
69.583 + }
69.584 + }
69.585 + }
69.586 +
69.587 + }; //class KarpMmc
69.588 +
69.589 + ///@}
69.590 +
69.591 +} //namespace lemon
69.592 +
69.593 +#endif //LEMON_KARP_MMC_H
70.1 --- a/lemon/lgf_reader.h Tue Dec 20 17:44:38 2011 +0100
70.2 +++ b/lemon/lgf_reader.h Tue Dec 20 18:15:14 2011 +0100
70.3 @@ -427,7 +427,7 @@
70.4 /// run();
70.5 ///\endcode
70.6 ///
70.7 - /// By default the reader uses the first section in the file of the
70.8 + /// By default, the reader uses the first section in the file of the
70.9 /// proper type. If a section has an optional name, then it can be
70.10 /// selected for reading by giving an optional name parameter to the
70.11 /// \c nodes(), \c arcs() or \c attributes() functions.
70.12 @@ -562,7 +562,7 @@
70.13 template <typename TDGR>
70.14 friend DigraphReader<TDGR> digraphReader(TDGR& digraph, std::istream& is);
70.15 template <typename TDGR>
70.16 - friend DigraphReader<TDGR> digraphReader(TDGR& digraph,
70.17 + friend DigraphReader<TDGR> digraphReader(TDGR& digraph,
70.18 const std::string& fn);
70.19 template <typename TDGR>
70.20 friend DigraphReader<TDGR> digraphReader(TDGR& digraph, const char *fn);
70.21 @@ -1194,14 +1194,14 @@
70.22 /// @}
70.23
70.24 };
70.25 -
70.26 +
70.27 /// \ingroup lemon_io
70.28 ///
70.29 /// \brief Return a \ref DigraphReader class
70.30 ///
70.31 /// This function just returns a \ref DigraphReader class.
70.32 ///
70.33 - /// With this function a digraph can be read from an
70.34 + /// With this function a digraph can be read from an
70.35 /// \ref lgf-format "LGF" file or input stream with several maps and
70.36 /// attributes. For example, there is network flow problem on a
70.37 /// digraph, i.e. a digraph with a \e capacity map on the arcs and
70.38 @@ -1256,7 +1256,7 @@
70.39
70.40 template <typename GR>
70.41 class GraphReader;
70.42 -
70.43 +
70.44 template <typename TGR>
70.45 GraphReader<TGR> graphReader(TGR& graph, std::istream& is = std::cin);
70.46 template <typename TGR>
70.47 @@ -1393,7 +1393,7 @@
70.48 template <typename TGR>
70.49 friend GraphReader<TGR> graphReader(TGR& graph, std::istream& is);
70.50 template <typename TGR>
70.51 - friend GraphReader<TGR> graphReader(TGR& graph, const std::string& fn);
70.52 + friend GraphReader<TGR> graphReader(TGR& graph, const std::string& fn);
70.53 template <typename TGR>
70.54 friend GraphReader<TGR> graphReader(TGR& graph, const char *fn);
70.55
70.56 @@ -2077,9 +2077,9 @@
70.57 ///
70.58 /// \brief Return a \ref GraphReader class
70.59 ///
70.60 - /// This function just returns a \ref GraphReader class.
70.61 + /// This function just returns a \ref GraphReader class.
70.62 ///
70.63 - /// With this function a graph can be read from an
70.64 + /// With this function a graph can be read from an
70.65 /// \ref lgf-format "LGF" file or input stream with several maps and
70.66 /// attributes. For example, there is weighted matching problem on a
70.67 /// graph, i.e. a graph with a \e weight map on the edges. This
70.68 @@ -2235,7 +2235,7 @@
70.69 /// and the comment lines are filtered out, and the leading
70.70 /// whitespaces are trimmed from each processed string.
70.71 ///
70.72 - /// For example let's see a section, which contain several
70.73 + /// For example, let's see a section, which contain several
70.74 /// integers, which should be inserted into a vector.
70.75 ///\code
70.76 /// @numbers
71.1 --- a/lemon/lgf_writer.h Tue Dec 20 17:44:38 2011 +0100
71.2 +++ b/lemon/lgf_writer.h Tue Dec 20 18:15:14 2011 +0100
71.3 @@ -2,7 +2,7 @@
71.4 *
71.5 * This file is a part of LEMON, a generic C++ optimization library.
71.6 *
71.7 - * Copyright (C) 2003-2009
71.8 + * Copyright (C) 2003-2010
71.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
71.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
71.11 *
71.12 @@ -351,7 +351,7 @@
71.13 class DigraphWriter;
71.14
71.15 template <typename TDGR>
71.16 - DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
71.17 + DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
71.18 std::ostream& os = std::cout);
71.19 template <typename TDGR>
71.20 DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const std::string& fn);
71.21 @@ -504,7 +504,7 @@
71.22 private:
71.23
71.24 template <typename TDGR>
71.25 - friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
71.26 + friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
71.27 std::ostream& os);
71.28 template <typename TDGR>
71.29 friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
71.30 @@ -917,7 +917,7 @@
71.31 ///
71.32 /// \brief Return a \ref DigraphWriter class
71.33 ///
71.34 - /// This function just returns a \ref DigraphWriter class.
71.35 + /// This function just returns a \ref DigraphWriter class.
71.36 ///
71.37 /// With this function a digraph can be write to a file or output
71.38 /// stream in \ref lgf-format "LGF" format with several maps and
71.39 @@ -957,7 +957,7 @@
71.40 /// \relates DigraphWriter
71.41 /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
71.42 template <typename TDGR>
71.43 - DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
71.44 + DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
71.45 const std::string& fn) {
71.46 DigraphWriter<TDGR> tmp(digraph, fn);
71.47 return tmp;
71.48 @@ -1101,11 +1101,11 @@
71.49 template <typename TGR>
71.50 friend GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os);
71.51 template <typename TGR>
71.52 - friend GraphWriter<TGR> graphWriter(const TGR& graph,
71.53 + friend GraphWriter<TGR> graphWriter(const TGR& graph,
71.54 const std::string& fn);
71.55 template <typename TGR>
71.56 friend GraphWriter<TGR> graphWriter(const TGR& graph, const char *fn);
71.57 -
71.58 +
71.59 GraphWriter(GraphWriter& other)
71.60 : _os(other._os), local_os(other.local_os), _graph(other._graph),
71.61 _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
71.62 @@ -1556,7 +1556,7 @@
71.63 ///
71.64 /// \brief Return a \ref GraphWriter class
71.65 ///
71.66 - /// This function just returns a \ref GraphWriter class.
71.67 + /// This function just returns a \ref GraphWriter class.
71.68 ///
71.69 /// With this function a graph can be write to a file or output
71.70 /// stream in \ref lgf-format "LGF" format with several maps and
72.1 --- a/lemon/list_graph.h Tue Dec 20 17:44:38 2011 +0100
72.2 +++ b/lemon/list_graph.h Tue Dec 20 18:15:14 2011 +0100
72.3 @@ -2,7 +2,7 @@
72.4 *
72.5 * This file is a part of LEMON, a generic C++ optimization library.
72.6 *
72.7 - * Copyright (C) 2003-2009
72.8 + * Copyright (C) 2003-2010
72.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
72.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
72.11 *
72.12 @@ -21,7 +21,7 @@
72.13
72.14 ///\ingroup graphs
72.15 ///\file
72.16 -///\brief ListDigraph, ListGraph classes.
72.17 +///\brief ListDigraph and ListGraph classes.
72.18
72.19 #include <lemon/core.h>
72.20 #include <lemon/error.h>
72.21 @@ -32,6 +32,8 @@
72.22
72.23 namespace lemon {
72.24
72.25 + class ListDigraph;
72.26 +
72.27 class ListDigraphBase {
72.28
72.29 protected:
72.30 @@ -62,6 +64,7 @@
72.31
72.32 class Node {
72.33 friend class ListDigraphBase;
72.34 + friend class ListDigraph;
72.35 protected:
72.36
72.37 int id;
72.38 @@ -77,6 +80,7 @@
72.39
72.40 class Arc {
72.41 friend class ListDigraphBase;
72.42 + friend class ListDigraph;
72.43 protected:
72.44
72.45 int id;
72.46 @@ -116,20 +120,20 @@
72.47 void first(Arc& arc) const {
72.48 int n;
72.49 for(n = first_node;
72.50 - n!=-1 && nodes[n].first_in == -1;
72.51 + n != -1 && nodes[n].first_out == -1;
72.52 n = nodes[n].next) {}
72.53 - arc.id = (n == -1) ? -1 : nodes[n].first_in;
72.54 + arc.id = (n == -1) ? -1 : nodes[n].first_out;
72.55 }
72.56
72.57 void next(Arc& arc) const {
72.58 - if (arcs[arc.id].next_in != -1) {
72.59 - arc.id = arcs[arc.id].next_in;
72.60 + if (arcs[arc.id].next_out != -1) {
72.61 + arc.id = arcs[arc.id].next_out;
72.62 } else {
72.63 int n;
72.64 - for(n = nodes[arcs[arc.id].target].next;
72.65 - n!=-1 && nodes[n].first_in == -1;
72.66 + for(n = nodes[arcs[arc.id].source].next;
72.67 + n != -1 && nodes[n].first_out == -1;
72.68 n = nodes[n].next) {}
72.69 - arc.id = (n == -1) ? -1 : nodes[n].first_in;
72.70 + arc.id = (n == -1) ? -1 : nodes[n].first_out;
72.71 }
72.72 }
72.73
72.74 @@ -311,31 +315,27 @@
72.75
72.76 ///A general directed graph structure.
72.77
72.78 - ///\ref ListDigraph is a simple and fast <em>directed graph</em>
72.79 - ///implementation based on static linked lists that are stored in
72.80 + ///\ref ListDigraph is a versatile and fast directed graph
72.81 + ///implementation based on linked lists that are stored in
72.82 ///\c std::vector structures.
72.83 ///
72.84 - ///It conforms to the \ref concepts::Digraph "Digraph concept" and it
72.85 - ///also provides several useful additional functionalities.
72.86 - ///Most of the member functions and nested classes are documented
72.87 + ///This type fully conforms to the \ref concepts::Digraph "Digraph concept"
72.88 + ///and it also provides several useful additional functionalities.
72.89 + ///Most of its member functions and nested classes are documented
72.90 ///only in the concept class.
72.91 ///
72.92 + ///This class provides only linear time counting for nodes and arcs.
72.93 + ///
72.94 ///\sa concepts::Digraph
72.95 -
72.96 + ///\sa ListGraph
72.97 class ListDigraph : public ExtendedListDigraphBase {
72.98 typedef ExtendedListDigraphBase Parent;
72.99
72.100 private:
72.101 - ///ListDigraph is \e not copy constructible. Use copyDigraph() instead.
72.102 -
72.103 - ///ListDigraph is \e not copy constructible. Use copyDigraph() instead.
72.104 - ///
72.105 + /// Digraphs are \e not copy constructible. Use DigraphCopy instead.
72.106 ListDigraph(const ListDigraph &) :ExtendedListDigraphBase() {};
72.107 - ///\brief Assignment of ListDigraph to another one is \e not allowed.
72.108 - ///Use copyDigraph() instead.
72.109 -
72.110 - ///Assignment of ListDigraph to another one is \e not allowed.
72.111 - ///Use copyDigraph() instead.
72.112 + /// \brief Assignment of a digraph to another one is \e not allowed.
72.113 + /// Use DigraphCopy instead.
72.114 void operator=(const ListDigraph &) {}
72.115 public:
72.116
72.117 @@ -347,71 +347,72 @@
72.118
72.119 ///Add a new node to the digraph.
72.120
72.121 - ///Add a new node to the digraph.
72.122 + ///This function adds a new node to the digraph.
72.123 ///\return The new node.
72.124 Node addNode() { return Parent::addNode(); }
72.125
72.126 ///Add a new arc to the digraph.
72.127
72.128 - ///Add a new arc to the digraph with source node \c s
72.129 + ///This function adds a new arc to the digraph with source node \c s
72.130 ///and target node \c t.
72.131 ///\return The new arc.
72.132 - Arc addArc(const Node& s, const Node& t) {
72.133 + Arc addArc(Node s, Node t) {
72.134 return Parent::addArc(s, t);
72.135 }
72.136
72.137 ///\brief Erase a node from the digraph.
72.138 ///
72.139 - ///Erase a node from the digraph.
72.140 + ///This function erases the given node along with its outgoing and
72.141 + ///incoming arcs from the digraph.
72.142 ///
72.143 - void erase(const Node& n) { Parent::erase(n); }
72.144 + ///\note All iterators referencing the removed node or the connected
72.145 + ///arcs are invalidated, of course.
72.146 + void erase(Node n) { Parent::erase(n); }
72.147
72.148 ///\brief Erase an arc from the digraph.
72.149 ///
72.150 - ///Erase an arc from the digraph.
72.151 + ///This function erases the given arc from the digraph.
72.152 ///
72.153 - void erase(const Arc& a) { Parent::erase(a); }
72.154 + ///\note All iterators referencing the removed arc are invalidated,
72.155 + ///of course.
72.156 + void erase(Arc a) { Parent::erase(a); }
72.157
72.158 /// Node validity check
72.159
72.160 - /// This function gives back true if the given node is valid,
72.161 - /// ie. it is a real node of the graph.
72.162 + /// This function gives back \c true if the given node is valid,
72.163 + /// i.e. it is a real node of the digraph.
72.164 ///
72.165 - /// \warning A Node pointing to a removed item
72.166 - /// could become valid again later if new nodes are
72.167 - /// added to the graph.
72.168 + /// \warning A removed node could become valid again if new nodes are
72.169 + /// added to the digraph.
72.170 bool valid(Node n) const { return Parent::valid(n); }
72.171
72.172 /// Arc validity check
72.173
72.174 - /// This function gives back true if the given arc is valid,
72.175 - /// ie. it is a real arc of the graph.
72.176 + /// This function gives back \c true if the given arc is valid,
72.177 + /// i.e. it is a real arc of the digraph.
72.178 ///
72.179 - /// \warning An Arc pointing to a removed item
72.180 - /// could become valid again later if new nodes are
72.181 - /// added to the graph.
72.182 + /// \warning A removed arc could become valid again if new arcs are
72.183 + /// added to the digraph.
72.184 bool valid(Arc a) const { return Parent::valid(a); }
72.185
72.186 - /// Change the target of \c a to \c n
72.187 + /// Change the target node of an arc
72.188
72.189 - /// Change the target of \c a to \c n
72.190 + /// This function changes the target node of the given arc \c a to \c n.
72.191 ///
72.192 - ///\note The <tt>ArcIt</tt>s and <tt>OutArcIt</tt>s referencing
72.193 - ///the changed arc remain valid. However <tt>InArcIt</tt>s are
72.194 - ///invalidated.
72.195 + ///\note \c ArcIt and \c OutArcIt iterators referencing the changed
72.196 + ///arc remain valid, but \c InArcIt iterators are invalidated.
72.197 ///
72.198 ///\warning This functionality cannot be used together with the Snapshot
72.199 ///feature.
72.200 void changeTarget(Arc a, Node n) {
72.201 Parent::changeTarget(a,n);
72.202 }
72.203 - /// Change the source of \c a to \c n
72.204 + /// Change the source node of an arc
72.205
72.206 - /// Change the source of \c a to \c n
72.207 + /// This function changes the source node of the given arc \c a to \c n.
72.208 ///
72.209 - ///\note The <tt>InArcIt</tt>s referencing the changed arc remain
72.210 - ///valid. However the <tt>ArcIt</tt>s and <tt>OutArcIt</tt>s are
72.211 - ///invalidated.
72.212 + ///\note \c InArcIt iterators referencing the changed arc remain
72.213 + ///valid, but \c ArcIt and \c OutArcIt iterators are invalidated.
72.214 ///
72.215 ///\warning This functionality cannot be used together with the Snapshot
72.216 ///feature.
72.217 @@ -419,94 +420,76 @@
72.218 Parent::changeSource(a,n);
72.219 }
72.220
72.221 - /// Invert the direction of an arc.
72.222 + /// Reverse the direction of an arc.
72.223
72.224 - ///\note The <tt>ArcIt</tt>s referencing the changed arc remain
72.225 - ///valid. However <tt>OutArcIt</tt>s and <tt>InArcIt</tt>s are
72.226 - ///invalidated.
72.227 + /// This function reverses the direction of the given arc.
72.228 + ///\note \c ArcIt, \c OutArcIt and \c InArcIt iterators referencing
72.229 + ///the changed arc are invalidated.
72.230 ///
72.231 ///\warning This functionality cannot be used together with the Snapshot
72.232 ///feature.
72.233 - void reverseArc(Arc e) {
72.234 - Node t=target(e);
72.235 - changeTarget(e,source(e));
72.236 - changeSource(e,t);
72.237 + void reverseArc(Arc a) {
72.238 + Node t=target(a);
72.239 + changeTarget(a,source(a));
72.240 + changeSource(a,t);
72.241 }
72.242
72.243 - /// Reserve memory for nodes.
72.244 -
72.245 - /// Using this function it is possible to avoid the superfluous memory
72.246 - /// allocation: if you know that the digraph you want to build will
72.247 - /// be very large (e.g. it will contain millions of nodes and/or arcs)
72.248 - /// then it is worth reserving space for this amount before starting
72.249 - /// to build the digraph.
72.250 - /// \sa reserveArc
72.251 - void reserveNode(int n) { nodes.reserve(n); };
72.252 -
72.253 - /// Reserve memory for arcs.
72.254 -
72.255 - /// Using this function it is possible to avoid the superfluous memory
72.256 - /// allocation: if you know that the digraph you want to build will
72.257 - /// be very large (e.g. it will contain millions of nodes and/or arcs)
72.258 - /// then it is worth reserving space for this amount before starting
72.259 - /// to build the digraph.
72.260 - /// \sa reserveNode
72.261 - void reserveArc(int m) { arcs.reserve(m); };
72.262 -
72.263 ///Contract two nodes.
72.264
72.265 - ///This function contracts two nodes.
72.266 - ///Node \p b will be removed but instead of deleting
72.267 - ///incident arcs, they will be joined to \p a.
72.268 - ///The last parameter \p r controls whether to remove loops. \c true
72.269 - ///means that loops will be removed.
72.270 + ///This function contracts the given two nodes.
72.271 + ///Node \c v is removed, but instead of deleting its
72.272 + ///incident arcs, they are joined to node \c u.
72.273 + ///If the last parameter \c r is \c true (this is the default value),
72.274 + ///then the newly created loops are removed.
72.275 ///
72.276 - ///\note The <tt>ArcIt</tt>s referencing a moved arc remain
72.277 - ///valid. However <tt>InArcIt</tt>s and <tt>OutArcIt</tt>s
72.278 - ///may be invalidated.
72.279 + ///\note The moved arcs are joined to node \c u using changeSource()
72.280 + ///or changeTarget(), thus \c ArcIt and \c OutArcIt iterators are
72.281 + ///invalidated for the outgoing arcs of node \c v and \c InArcIt
72.282 + ///iterators are invalidated for the incomming arcs of \c v.
72.283 + ///Moreover all iterators referencing node \c v or the removed
72.284 + ///loops are also invalidated. Other iterators remain valid.
72.285 ///
72.286 ///\warning This functionality cannot be used together with the Snapshot
72.287 ///feature.
72.288 - void contract(Node a, Node b, bool r = true)
72.289 + void contract(Node u, Node v, bool r = true)
72.290 {
72.291 - for(OutArcIt e(*this,b);e!=INVALID;) {
72.292 + for(OutArcIt e(*this,v);e!=INVALID;) {
72.293 OutArcIt f=e;
72.294 ++f;
72.295 - if(r && target(e)==a) erase(e);
72.296 - else changeSource(e,a);
72.297 + if(r && target(e)==u) erase(e);
72.298 + else changeSource(e,u);
72.299 e=f;
72.300 }
72.301 - for(InArcIt e(*this,b);e!=INVALID;) {
72.302 + for(InArcIt e(*this,v);e!=INVALID;) {
72.303 InArcIt f=e;
72.304 ++f;
72.305 - if(r && source(e)==a) erase(e);
72.306 - else changeTarget(e,a);
72.307 + if(r && source(e)==u) erase(e);
72.308 + else changeTarget(e,u);
72.309 e=f;
72.310 }
72.311 - erase(b);
72.312 + erase(v);
72.313 }
72.314
72.315 ///Split a node.
72.316
72.317 - ///This function splits a node. First a new node is added to the digraph,
72.318 - ///then the source of each outgoing arc of \c n is moved to this new node.
72.319 - ///If \c connect is \c true (this is the default value), then a new arc
72.320 - ///from \c n to the newly created node is also added.
72.321 + ///This function splits the given node. First, a new node is added
72.322 + ///to the digraph, then the source of each outgoing arc of node \c n
72.323 + ///is moved to this new node.
72.324 + ///If the second parameter \c connect is \c true (this is the default
72.325 + ///value), then a new arc from node \c n to the newly created node
72.326 + ///is also added.
72.327 ///\return The newly created node.
72.328 ///
72.329 - ///\note The <tt>ArcIt</tt>s referencing a moved arc remain
72.330 - ///valid. However <tt>InArcIt</tt>s and <tt>OutArcIt</tt>s may
72.331 - ///be invalidated.
72.332 + ///\note All iterators remain valid.
72.333 ///
72.334 - ///\warning This functionality cannot be used in conjunction with the
72.335 + ///\warning This functionality cannot be used together with the
72.336 ///Snapshot feature.
72.337 Node split(Node n, bool connect = true) {
72.338 Node b = addNode();
72.339 - for(OutArcIt e(*this,n);e!=INVALID;) {
72.340 - OutArcIt f=e;
72.341 - ++f;
72.342 - changeSource(e,b);
72.343 - e=f;
72.344 + nodes[b.id].first_out=nodes[n.id].first_out;
72.345 + nodes[n.id].first_out=-1;
72.346 + for(int i=nodes[b.id].first_out; i!=-1; i=arcs[i].next_out) {
72.347 + arcs[i].source=b.id;
72.348 }
72.349 if (connect) addArc(n,b);
72.350 return b;
72.351 @@ -514,21 +497,53 @@
72.352
72.353 ///Split an arc.
72.354
72.355 - ///This function splits an arc. First a new node \c b is added to
72.356 - ///the digraph, then the original arc is re-targeted to \c
72.357 - ///b. Finally an arc from \c b to the original target is added.
72.358 + ///This function splits the given arc. First, a new node \c v is
72.359 + ///added to the digraph, then the target node of the original arc
72.360 + ///is set to \c v. Finally, an arc from \c v to the original target
72.361 + ///is added.
72.362 + ///\return The newly created node.
72.363 ///
72.364 - ///\return The newly created node.
72.365 + ///\note \c InArcIt iterators referencing the original arc are
72.366 + ///invalidated. Other iterators remain valid.
72.367 ///
72.368 ///\warning This functionality cannot be used together with the
72.369 ///Snapshot feature.
72.370 - Node split(Arc e) {
72.371 - Node b = addNode();
72.372 - addArc(b,target(e));
72.373 - changeTarget(e,b);
72.374 - return b;
72.375 + Node split(Arc a) {
72.376 + Node v = addNode();
72.377 + addArc(v,target(a));
72.378 + changeTarget(a,v);
72.379 + return v;
72.380 }
72.381
72.382 + ///Clear the digraph.
72.383 +
72.384 + ///This function erases all nodes and arcs from the digraph.
72.385 + ///
72.386 + ///\note All iterators of the digraph are invalidated, of course.
72.387 + void clear() {
72.388 + Parent::clear();
72.389 + }
72.390 +
72.391 + /// Reserve memory for nodes.
72.392 +
72.393 + /// Using this function, it is possible to avoid superfluous memory
72.394 + /// allocation: if you know that the digraph you want to build will
72.395 + /// be large (e.g. it will contain millions of nodes and/or arcs),
72.396 + /// then it is worth reserving space for this amount before starting
72.397 + /// to build the digraph.
72.398 + /// \sa reserveArc()
72.399 + void reserveNode(int n) { nodes.reserve(n); };
72.400 +
72.401 + /// Reserve memory for arcs.
72.402 +
72.403 + /// Using this function, it is possible to avoid superfluous memory
72.404 + /// allocation: if you know that the digraph you want to build will
72.405 + /// be large (e.g. it will contain millions of nodes and/or arcs),
72.406 + /// then it is worth reserving space for this amount before starting
72.407 + /// to build the digraph.
72.408 + /// \sa reserveNode()
72.409 + void reserveArc(int m) { arcs.reserve(m); };
72.410 +
72.411 /// \brief Class to make a snapshot of the digraph and restore
72.412 /// it later.
72.413 ///
72.414 @@ -537,9 +552,15 @@
72.415 /// The newly added nodes and arcs can be removed using the
72.416 /// restore() function.
72.417 ///
72.418 - /// \warning Arc and node deletions and other modifications (e.g.
72.419 - /// contracting, splitting, reversing arcs or nodes) cannot be
72.420 + /// \note After a state is restored, you cannot restore a later state,
72.421 + /// i.e. you cannot add the removed nodes and arcs again using
72.422 + /// another Snapshot instance.
72.423 + ///
72.424 + /// \warning Node and arc deletions and other modifications (e.g.
72.425 + /// reversing, contracting, splitting arcs or nodes) cannot be
72.426 /// restored. These events invalidate the snapshot.
72.427 + /// However, the arcs and nodes that were added to the digraph after
72.428 + /// making the current snapshot can be removed without invalidating it.
72.429 class Snapshot {
72.430 protected:
72.431
72.432 @@ -709,39 +730,40 @@
72.433 /// \brief Default constructor.
72.434 ///
72.435 /// Default constructor.
72.436 - /// To actually make a snapshot you must call save().
72.437 + /// You have to call save() to actually make a snapshot.
72.438 Snapshot()
72.439 : digraph(0), node_observer_proxy(*this),
72.440 arc_observer_proxy(*this) {}
72.441
72.442 /// \brief Constructor that immediately makes a snapshot.
72.443 ///
72.444 - /// This constructor immediately makes a snapshot of the digraph.
72.445 - /// \param _digraph The digraph we make a snapshot of.
72.446 - Snapshot(ListDigraph &_digraph)
72.447 + /// This constructor immediately makes a snapshot of the given digraph.
72.448 + Snapshot(ListDigraph &gr)
72.449 : node_observer_proxy(*this),
72.450 arc_observer_proxy(*this) {
72.451 - attach(_digraph);
72.452 + attach(gr);
72.453 }
72.454
72.455 /// \brief Make a snapshot.
72.456 ///
72.457 - /// Make a snapshot of the digraph.
72.458 - ///
72.459 - /// This function can be called more than once. In case of a repeated
72.460 + /// This function makes a snapshot of the given digraph.
72.461 + /// It can be called more than once. In case of a repeated
72.462 /// call, the previous snapshot gets lost.
72.463 - /// \param _digraph The digraph we make the snapshot of.
72.464 - void save(ListDigraph &_digraph) {
72.465 + void save(ListDigraph &gr) {
72.466 if (attached()) {
72.467 detach();
72.468 clear();
72.469 }
72.470 - attach(_digraph);
72.471 + attach(gr);
72.472 }
72.473
72.474 /// \brief Undo the changes until the last snapshot.
72.475 - //
72.476 - /// Undo the changes until the last snapshot created by save().
72.477 + ///
72.478 + /// This function undos the changes until the last snapshot
72.479 + /// created by save() or Snapshot(ListDigraph&).
72.480 + ///
72.481 + /// \warning This method invalidates the snapshot, i.e. repeated
72.482 + /// restoring is not supported unless you call save() again.
72.483 void restore() {
72.484 detach();
72.485 for(std::list<Arc>::iterator it = added_arcs.begin();
72.486 @@ -755,9 +777,9 @@
72.487 clear();
72.488 }
72.489
72.490 - /// \brief Gives back true when the snapshot is valid.
72.491 + /// \brief Returns \c true if the snapshot is valid.
72.492 ///
72.493 - /// Gives back true when the snapshot is valid.
72.494 + /// This function returns \c true if the snapshot is valid.
72.495 bool valid() const {
72.496 return attached();
72.497 }
72.498 @@ -795,10 +817,6 @@
72.499
72.500 typedef ListGraphBase Graph;
72.501
72.502 - class Node;
72.503 - class Arc;
72.504 - class Edge;
72.505 -
72.506 class Node {
72.507 friend class ListGraphBase;
72.508 protected:
72.509 @@ -848,8 +866,6 @@
72.510 bool operator<(const Arc& arc) const {return id < arc.id;}
72.511 };
72.512
72.513 -
72.514 -
72.515 ListGraphBase()
72.516 : nodes(), first_node(-1),
72.517 first_free_node(-1), arcs(), first_free_arc(-1) {}
72.518 @@ -1164,31 +1180,27 @@
72.519
72.520 ///A general undirected graph structure.
72.521
72.522 - ///\ref ListGraph is a simple and fast <em>undirected graph</em>
72.523 - ///implementation based on static linked lists that are stored in
72.524 + ///\ref ListGraph is a versatile and fast undirected graph
72.525 + ///implementation based on linked lists that are stored in
72.526 ///\c std::vector structures.
72.527 ///
72.528 - ///It conforms to the \ref concepts::Graph "Graph concept" and it
72.529 - ///also provides several useful additional functionalities.
72.530 - ///Most of the member functions and nested classes are documented
72.531 + ///This type fully conforms to the \ref concepts::Graph "Graph concept"
72.532 + ///and it also provides several useful additional functionalities.
72.533 + ///Most of its member functions and nested classes are documented
72.534 ///only in the concept class.
72.535 ///
72.536 + ///This class provides only linear time counting for nodes, edges and arcs.
72.537 + ///
72.538 ///\sa concepts::Graph
72.539 -
72.540 + ///\sa ListDigraph
72.541 class ListGraph : public ExtendedListGraphBase {
72.542 typedef ExtendedListGraphBase Parent;
72.543
72.544 private:
72.545 - ///ListGraph is \e not copy constructible. Use copyGraph() instead.
72.546 -
72.547 - ///ListGraph is \e not copy constructible. Use copyGraph() instead.
72.548 - ///
72.549 + /// Graphs are \e not copy constructible. Use GraphCopy instead.
72.550 ListGraph(const ListGraph &) :ExtendedListGraphBase() {};
72.551 - ///\brief Assignment of ListGraph to another one is \e not allowed.
72.552 - ///Use copyGraph() instead.
72.553 -
72.554 - ///Assignment of ListGraph to another one is \e not allowed.
72.555 - ///Use copyGraph() instead.
72.556 + /// \brief Assignment of a graph to another one is \e not allowed.
72.557 + /// Use GraphCopy instead.
72.558 void operator=(const ListGraph &) {}
72.559 public:
72.560 /// Constructor
72.561 @@ -1201,94 +1213,102 @@
72.562
72.563 /// \brief Add a new node to the graph.
72.564 ///
72.565 - /// Add a new node to the graph.
72.566 + /// This function adds a new node to the graph.
72.567 /// \return The new node.
72.568 Node addNode() { return Parent::addNode(); }
72.569
72.570 /// \brief Add a new edge to the graph.
72.571 ///
72.572 - /// Add a new edge to the graph with source node \c s
72.573 - /// and target node \c t.
72.574 + /// This function adds a new edge to the graph between nodes
72.575 + /// \c u and \c v with inherent orientation from node \c u to
72.576 + /// node \c v.
72.577 /// \return The new edge.
72.578 - Edge addEdge(const Node& s, const Node& t) {
72.579 - return Parent::addEdge(s, t);
72.580 + Edge addEdge(Node u, Node v) {
72.581 + return Parent::addEdge(u, v);
72.582 }
72.583
72.584 - /// \brief Erase a node from the graph.
72.585 + ///\brief Erase a node from the graph.
72.586 ///
72.587 - /// Erase a node from the graph.
72.588 + /// This function erases the given node along with its incident arcs
72.589 + /// from the graph.
72.590 ///
72.591 - void erase(const Node& n) { Parent::erase(n); }
72.592 + /// \note All iterators referencing the removed node or the incident
72.593 + /// edges are invalidated, of course.
72.594 + void erase(Node n) { Parent::erase(n); }
72.595
72.596 - /// \brief Erase an edge from the graph.
72.597 + ///\brief Erase an edge from the graph.
72.598 ///
72.599 - /// Erase an edge from the graph.
72.600 + /// This function erases the given edge from the graph.
72.601 ///
72.602 - void erase(const Edge& e) { Parent::erase(e); }
72.603 + /// \note All iterators referencing the removed edge are invalidated,
72.604 + /// of course.
72.605 + void erase(Edge e) { Parent::erase(e); }
72.606 /// Node validity check
72.607
72.608 - /// This function gives back true if the given node is valid,
72.609 - /// ie. it is a real node of the graph.
72.610 + /// This function gives back \c true if the given node is valid,
72.611 + /// i.e. it is a real node of the graph.
72.612 ///
72.613 - /// \warning A Node pointing to a removed item
72.614 - /// could become valid again later if new nodes are
72.615 + /// \warning A removed node could become valid again if new nodes are
72.616 /// added to the graph.
72.617 bool valid(Node n) const { return Parent::valid(n); }
72.618 + /// Edge validity check
72.619 +
72.620 + /// This function gives back \c true if the given edge is valid,
72.621 + /// i.e. it is a real edge of the graph.
72.622 + ///
72.623 + /// \warning A removed edge could become valid again if new edges are
72.624 + /// added to the graph.
72.625 + bool valid(Edge e) const { return Parent::valid(e); }
72.626 /// Arc validity check
72.627
72.628 - /// This function gives back true if the given arc is valid,
72.629 - /// ie. it is a real arc of the graph.
72.630 + /// This function gives back \c true if the given arc is valid,
72.631 + /// i.e. it is a real arc of the graph.
72.632 ///
72.633 - /// \warning An Arc pointing to a removed item
72.634 - /// could become valid again later if new edges are
72.635 + /// \warning A removed arc could become valid again if new edges are
72.636 /// added to the graph.
72.637 bool valid(Arc a) const { return Parent::valid(a); }
72.638 - /// Edge validity check
72.639
72.640 - /// This function gives back true if the given edge is valid,
72.641 - /// ie. it is a real arc of the graph.
72.642 + /// \brief Change the first node of an edge.
72.643 ///
72.644 - /// \warning A Edge pointing to a removed item
72.645 - /// could become valid again later if new edges are
72.646 - /// added to the graph.
72.647 - bool valid(Edge e) const { return Parent::valid(e); }
72.648 - /// \brief Change the end \c u of \c e to \c n
72.649 + /// This function changes the first node of the given edge \c e to \c n.
72.650 ///
72.651 - /// This function changes the end \c u of \c e to node \c n.
72.652 - ///
72.653 - ///\note The <tt>EdgeIt</tt>s and <tt>ArcIt</tt>s referencing the
72.654 - ///changed edge are invalidated and if the changed node is the
72.655 - ///base node of an iterator then this iterator is also
72.656 - ///invalidated.
72.657 + ///\note \c EdgeIt and \c ArcIt iterators referencing the
72.658 + ///changed edge are invalidated and all other iterators whose
72.659 + ///base node is the changed node are also invalidated.
72.660 ///
72.661 ///\warning This functionality cannot be used together with the
72.662 ///Snapshot feature.
72.663 void changeU(Edge e, Node n) {
72.664 Parent::changeU(e,n);
72.665 }
72.666 - /// \brief Change the end \c v of \c e to \c n
72.667 + /// \brief Change the second node of an edge.
72.668 ///
72.669 - /// This function changes the end \c v of \c e to \c n.
72.670 + /// This function changes the second node of the given edge \c e to \c n.
72.671 ///
72.672 - ///\note The <tt>EdgeIt</tt>s referencing the changed edge remain
72.673 - ///valid, however <tt>ArcIt</tt>s and if the changed node is the
72.674 - ///base node of an iterator then this iterator is invalidated.
72.675 + ///\note \c EdgeIt iterators referencing the changed edge remain
72.676 + ///valid, but \c ArcIt iterators referencing the changed edge and
72.677 + ///all other iterators whose base node is the changed node are also
72.678 + ///invalidated.
72.679 ///
72.680 ///\warning This functionality cannot be used together with the
72.681 ///Snapshot feature.
72.682 void changeV(Edge e, Node n) {
72.683 Parent::changeV(e,n);
72.684 }
72.685 +
72.686 /// \brief Contract two nodes.
72.687 ///
72.688 - /// This function contracts two nodes.
72.689 - /// Node \p b will be removed but instead of deleting
72.690 - /// its neighboring arcs, they will be joined to \p a.
72.691 - /// The last parameter \p r controls whether to remove loops. \c true
72.692 - /// means that loops will be removed.
72.693 + /// This function contracts the given two nodes.
72.694 + /// Node \c b is removed, but instead of deleting
72.695 + /// its incident edges, they are joined to node \c a.
72.696 + /// If the last parameter \c r is \c true (this is the default value),
72.697 + /// then the newly created loops are removed.
72.698 ///
72.699 - /// \note The <tt>ArcIt</tt>s referencing a moved arc remain
72.700 - /// valid.
72.701 + /// \note The moved edges are joined to node \c a using changeU()
72.702 + /// or changeV(), thus all edge and arc iterators whose base node is
72.703 + /// \c b are invalidated.
72.704 + /// Moreover all iterators referencing node \c b or the removed
72.705 + /// loops are also invalidated. Other iterators remain valid.
72.706 ///
72.707 ///\warning This functionality cannot be used together with the
72.708 ///Snapshot feature.
72.709 @@ -1307,6 +1327,34 @@
72.710 erase(b);
72.711 }
72.712
72.713 + ///Clear the graph.
72.714 +
72.715 + ///This function erases all nodes and arcs from the graph.
72.716 + ///
72.717 + ///\note All iterators of the graph are invalidated, of course.
72.718 + void clear() {
72.719 + Parent::clear();
72.720 + }
72.721 +
72.722 + /// Reserve memory for nodes.
72.723 +
72.724 + /// Using this function, it is possible to avoid superfluous memory
72.725 + /// allocation: if you know that the graph you want to build will
72.726 + /// be large (e.g. it will contain millions of nodes and/or edges),
72.727 + /// then it is worth reserving space for this amount before starting
72.728 + /// to build the graph.
72.729 + /// \sa reserveEdge()
72.730 + void reserveNode(int n) { nodes.reserve(n); };
72.731 +
72.732 + /// Reserve memory for edges.
72.733 +
72.734 + /// Using this function, it is possible to avoid superfluous memory
72.735 + /// allocation: if you know that the graph you want to build will
72.736 + /// be large (e.g. it will contain millions of nodes and/or edges),
72.737 + /// then it is worth reserving space for this amount before starting
72.738 + /// to build the graph.
72.739 + /// \sa reserveNode()
72.740 + void reserveEdge(int m) { arcs.reserve(2 * m); };
72.741
72.742 /// \brief Class to make a snapshot of the graph and restore
72.743 /// it later.
72.744 @@ -1316,9 +1364,15 @@
72.745 /// The newly added nodes and edges can be removed
72.746 /// using the restore() function.
72.747 ///
72.748 - /// \warning Edge and node deletions and other modifications
72.749 - /// (e.g. changing nodes of edges, contracting nodes) cannot be
72.750 - /// restored. These events invalidate the snapshot.
72.751 + /// \note After a state is restored, you cannot restore a later state,
72.752 + /// i.e. you cannot add the removed nodes and edges again using
72.753 + /// another Snapshot instance.
72.754 + ///
72.755 + /// \warning Node and edge deletions and other modifications
72.756 + /// (e.g. changing the end-nodes of edges or contracting nodes)
72.757 + /// cannot be restored. These events invalidate the snapshot.
72.758 + /// However, the edges and nodes that were added to the graph after
72.759 + /// making the current snapshot can be removed without invalidating it.
72.760 class Snapshot {
72.761 protected:
72.762
72.763 @@ -1488,39 +1542,40 @@
72.764 /// \brief Default constructor.
72.765 ///
72.766 /// Default constructor.
72.767 - /// To actually make a snapshot you must call save().
72.768 + /// You have to call save() to actually make a snapshot.
72.769 Snapshot()
72.770 : graph(0), node_observer_proxy(*this),
72.771 edge_observer_proxy(*this) {}
72.772
72.773 /// \brief Constructor that immediately makes a snapshot.
72.774 ///
72.775 - /// This constructor immediately makes a snapshot of the graph.
72.776 - /// \param _graph The graph we make a snapshot of.
72.777 - Snapshot(ListGraph &_graph)
72.778 + /// This constructor immediately makes a snapshot of the given graph.
72.779 + Snapshot(ListGraph &gr)
72.780 : node_observer_proxy(*this),
72.781 edge_observer_proxy(*this) {
72.782 - attach(_graph);
72.783 + attach(gr);
72.784 }
72.785
72.786 /// \brief Make a snapshot.
72.787 ///
72.788 - /// Make a snapshot of the graph.
72.789 - ///
72.790 - /// This function can be called more than once. In case of a repeated
72.791 + /// This function makes a snapshot of the given graph.
72.792 + /// It can be called more than once. In case of a repeated
72.793 /// call, the previous snapshot gets lost.
72.794 - /// \param _graph The graph we make the snapshot of.
72.795 - void save(ListGraph &_graph) {
72.796 + void save(ListGraph &gr) {
72.797 if (attached()) {
72.798 detach();
72.799 clear();
72.800 }
72.801 - attach(_graph);
72.802 + attach(gr);
72.803 }
72.804
72.805 /// \brief Undo the changes until the last snapshot.
72.806 - //
72.807 - /// Undo the changes until the last snapshot created by save().
72.808 + ///
72.809 + /// This function undos the changes until the last snapshot
72.810 + /// created by save() or Snapshot(ListGraph&).
72.811 + ///
72.812 + /// \warning This method invalidates the snapshot, i.e. repeated
72.813 + /// restoring is not supported unless you call save() again.
72.814 void restore() {
72.815 detach();
72.816 for(std::list<Edge>::iterator it = added_edges.begin();
72.817 @@ -1534,9 +1589,9 @@
72.818 clear();
72.819 }
72.820
72.821 - /// \brief Gives back true when the snapshot is valid.
72.822 + /// \brief Returns \c true if the snapshot is valid.
72.823 ///
72.824 - /// Gives back true when the snapshot is valid.
72.825 + /// This function returns \c true if the snapshot is valid.
72.826 bool valid() const {
72.827 return attached();
72.828 }
73.1 --- a/lemon/lp.h Tue Dec 20 17:44:38 2011 +0100
73.2 +++ b/lemon/lp.h Tue Dec 20 18:15:14 2011 +0100
73.3 @@ -2,7 +2,7 @@
73.4 *
73.5 * This file is a part of LEMON, a generic C++ optimization library.
73.6 *
73.7 - * Copyright (C) 2003-2008
73.8 + * Copyright (C) 2003-2010
73.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
73.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
73.11 *
73.12 @@ -84,7 +84,7 @@
73.13 typedef SoplexLp Lp;
73.14 #elif LEMON_HAVE_CLP
73.15 # define DEFAULT_LP CLP
73.16 - typedef ClpLp Lp;
73.17 + typedef ClpLp Lp;
73.18 #endif
73.19 #endif
73.20
74.1 --- a/lemon/lp_base.cc Tue Dec 20 17:44:38 2011 +0100
74.2 +++ b/lemon/lp_base.cc Tue Dec 20 18:15:14 2011 +0100
74.3 @@ -2,7 +2,7 @@
74.4 *
74.5 * This file is a part of LEMON, a generic C++ optimization library.
74.6 *
74.7 - * Copyright (C) 2003-2008
74.8 + * Copyright (C) 2003-2010
74.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
74.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
74.11 *
75.1 --- a/lemon/lp_base.h Tue Dec 20 17:44:38 2011 +0100
75.2 +++ b/lemon/lp_base.h Tue Dec 20 18:15:14 2011 +0100
75.3 @@ -2,7 +2,7 @@
75.4 *
75.5 * This file is a part of LEMON, a generic C++ optimization library.
75.6 *
75.7 - * Copyright (C) 2003-2008
75.8 + * Copyright (C) 2003-2010
75.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
75.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
75.11 *
75.12 @@ -82,7 +82,7 @@
75.13 /// Verbose output.
75.14 MESSAGE_VERBOSE
75.15 };
75.16 -
75.17 +
75.18
75.19 ///The floating point type used by the solver
75.20 typedef double Value;
75.21 @@ -114,14 +114,14 @@
75.22 typedef Value ExprValue;
75.23 typedef True LpCol;
75.24 /// Default constructor
75.25 -
75.26 +
75.27 /// \warning The default constructor sets the Col to an
75.28 /// undefined value.
75.29 Col() {}
75.30 /// Invalid constructor \& conversion.
75.31 -
75.32 +
75.33 /// This constructor initializes the Col to be invalid.
75.34 - /// \sa Invalid for more details.
75.35 + /// \sa Invalid for more details.
75.36 Col(const Invalid&) : _id(-1) {}
75.37 /// Equality operator
75.38
75.39 @@ -146,7 +146,7 @@
75.40
75.41 ///Iterator for iterate over the columns of an LP problem
75.42
75.43 - /// Its usage is quite simple, for example you can count the number
75.44 + /// Its usage is quite simple, for example, you can count the number
75.45 /// of columns in an LP \c lp:
75.46 ///\code
75.47 /// int count=0;
75.48 @@ -156,12 +156,12 @@
75.49 const LpBase *_solver;
75.50 public:
75.51 /// Default constructor
75.52 -
75.53 +
75.54 /// \warning The default constructor sets the iterator
75.55 /// to an undefined value.
75.56 ColIt() {}
75.57 /// Sets the iterator to the first Col
75.58 -
75.59 +
75.60 /// Sets the iterator to the first Col.
75.61 ///
75.62 ColIt(const LpBase &solver) : _solver(&solver)
75.63 @@ -169,12 +169,12 @@
75.64 _solver->cols.firstItem(_id);
75.65 }
75.66 /// Invalid constructor \& conversion
75.67 -
75.68 +
75.69 /// Initialize the iterator to be invalid.
75.70 /// \sa Invalid for more details.
75.71 ColIt(const Invalid&) : Col(INVALID) {}
75.72 /// Next column
75.73 -
75.74 +
75.75 /// Assign the iterator to the next column.
75.76 ///
75.77 ColIt &operator++()
75.78 @@ -209,14 +209,14 @@
75.79 typedef Value ExprValue;
75.80 typedef True LpRow;
75.81 /// Default constructor
75.82 -
75.83 +
75.84 /// \warning The default constructor sets the Row to an
75.85 /// undefined value.
75.86 Row() {}
75.87 /// Invalid constructor \& conversion.
75.88 -
75.89 +
75.90 /// This constructor initializes the Row to be invalid.
75.91 - /// \sa Invalid for more details.
75.92 + /// \sa Invalid for more details.
75.93 Row(const Invalid&) : _id(-1) {}
75.94 /// Equality operator
75.95
75.96 @@ -224,7 +224,7 @@
75.97 /// the same LP row or both are invalid.
75.98 bool operator==(Row r) const {return _id == r._id;}
75.99 /// Inequality operator
75.100 -
75.101 +
75.102 /// \sa operator==(Row r)
75.103 ///
75.104 bool operator!=(Row r) const {return _id != r._id;}
75.105 @@ -241,7 +241,7 @@
75.106
75.107 ///Iterator for iterate over the rows of an LP problem
75.108
75.109 - /// Its usage is quite simple, for example you can count the number
75.110 + /// Its usage is quite simple, for example, you can count the number
75.111 /// of rows in an LP \c lp:
75.112 ///\code
75.113 /// int count=0;
75.114 @@ -251,12 +251,12 @@
75.115 const LpBase *_solver;
75.116 public:
75.117 /// Default constructor
75.118 -
75.119 +
75.120 /// \warning The default constructor sets the iterator
75.121 /// to an undefined value.
75.122 RowIt() {}
75.123 /// Sets the iterator to the first Row
75.124 -
75.125 +
75.126 /// Sets the iterator to the first Row.
75.127 ///
75.128 RowIt(const LpBase &solver) : _solver(&solver)
75.129 @@ -264,12 +264,12 @@
75.130 _solver->rows.firstItem(_id);
75.131 }
75.132 /// Invalid constructor \& conversion
75.133 -
75.134 +
75.135 /// Initialize the iterator to be invalid.
75.136 /// \sa Invalid for more details.
75.137 RowIt(const Invalid&) : Row(INVALID) {}
75.138 /// Next row
75.139 -
75.140 +
75.141 /// Assign the iterator to the next row.
75.142 ///
75.143 RowIt &operator++()
75.144 @@ -347,7 +347,7 @@
75.145 public:
75.146 typedef True SolverExpr;
75.147 /// Default constructor
75.148 -
75.149 +
75.150 /// Construct an empty expression, the coefficients and
75.151 /// the constant component are initialized to zero.
75.152 Expr() : const_comp(0) {}
75.153 @@ -448,9 +448,9 @@
75.154 }
75.155
75.156 ///Iterator over the expression
75.157 -
75.158 - ///The iterator iterates over the terms of the expression.
75.159 - ///
75.160 +
75.161 + ///The iterator iterates over the terms of the expression.
75.162 + ///
75.163 ///\code
75.164 ///double s=0;
75.165 ///for(LpBase::Expr::CoeffIt i(e);i!=INVALID;++i)
75.166 @@ -464,7 +464,7 @@
75.167 public:
75.168
75.169 /// Sets the iterator to the first term
75.170 -
75.171 +
75.172 /// Sets the iterator to the first term of the expression.
75.173 ///
75.174 CoeffIt(Expr& e)
75.175 @@ -481,7 +481,7 @@
75.176 /// Returns the coefficient of the term
75.177 const Value& operator*() const { return _it->second; }
75.178 /// Next term
75.179 -
75.180 +
75.181 /// Assign the iterator to the next term.
75.182 ///
75.183 CoeffIt& operator++() { ++_it; return *this; }
75.184 @@ -493,9 +493,9 @@
75.185 };
75.186
75.187 /// Const iterator over the expression
75.188 -
75.189 - ///The iterator iterates over the terms of the expression.
75.190 - ///
75.191 +
75.192 + ///The iterator iterates over the terms of the expression.
75.193 + ///
75.194 ///\code
75.195 ///double s=0;
75.196 ///for(LpBase::Expr::ConstCoeffIt i(e);i!=INVALID;++i)
75.197 @@ -509,7 +509,7 @@
75.198 public:
75.199
75.200 /// Sets the iterator to the first term
75.201 -
75.202 +
75.203 /// Sets the iterator to the first term of the expression.
75.204 ///
75.205 ConstCoeffIt(const Expr& e)
75.206 @@ -524,7 +524,7 @@
75.207 const Value& operator*() const { return _it->second; }
75.208
75.209 /// Next term
75.210 -
75.211 +
75.212 /// Assign the iterator to the next term.
75.213 ///
75.214 ConstCoeffIt& operator++() { ++_it; return *this; }
75.215 @@ -673,7 +673,7 @@
75.216 public:
75.217 typedef True SolverExpr;
75.218 /// Default constructor
75.219 -
75.220 +
75.221 /// Construct an empty expression, the coefficients are
75.222 /// initialized to zero.
75.223 DualExpr() {}
75.224 @@ -708,7 +708,7 @@
75.225 }
75.226 }
75.227 /// \brief Removes the coefficients which's absolute value does
75.228 - /// not exceed \c epsilon.
75.229 + /// not exceed \c epsilon.
75.230 void simplify(Value epsilon = 0.0) {
75.231 std::map<int, Value>::iterator it=comps.begin();
75.232 while (it != comps.end()) {
75.233 @@ -757,9 +757,9 @@
75.234 }
75.235
75.236 ///Iterator over the expression
75.237 -
75.238 - ///The iterator iterates over the terms of the expression.
75.239 - ///
75.240 +
75.241 + ///The iterator iterates over the terms of the expression.
75.242 + ///
75.243 ///\code
75.244 ///double s=0;
75.245 ///for(LpBase::DualExpr::CoeffIt i(e);i!=INVALID;++i)
75.246 @@ -773,7 +773,7 @@
75.247 public:
75.248
75.249 /// Sets the iterator to the first term
75.250 -
75.251 +
75.252 /// Sets the iterator to the first term of the expression.
75.253 ///
75.254 CoeffIt(DualExpr& e)
75.255 @@ -791,7 +791,7 @@
75.256 const Value& operator*() const { return _it->second; }
75.257
75.258 /// Next term
75.259 -
75.260 +
75.261 /// Assign the iterator to the next term.
75.262 ///
75.263 CoeffIt& operator++() { ++_it; return *this; }
75.264 @@ -803,9 +803,9 @@
75.265 };
75.266
75.267 ///Iterator over the expression
75.268 -
75.269 - ///The iterator iterates over the terms of the expression.
75.270 - ///
75.271 +
75.272 + ///The iterator iterates over the terms of the expression.
75.273 + ///
75.274 ///\code
75.275 ///double s=0;
75.276 ///for(LpBase::DualExpr::ConstCoeffIt i(e);i!=INVALID;++i)
75.277 @@ -819,7 +819,7 @@
75.278 public:
75.279
75.280 /// Sets the iterator to the first term
75.281 -
75.282 +
75.283 /// Sets the iterator to the first term of the expression.
75.284 ///
75.285 ConstCoeffIt(const DualExpr& e)
75.286 @@ -834,7 +834,7 @@
75.287 const Value& operator*() const { return _it->second; }
75.288
75.289 /// Next term
75.290 -
75.291 +
75.292 /// Assign the iterator to the next term.
75.293 ///
75.294 ConstCoeffIt& operator++() { ++_it; return *this; }
75.295 @@ -943,6 +943,14 @@
75.296 virtual int _addCol() = 0;
75.297 virtual int _addRow() = 0;
75.298
75.299 + virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u) {
75.300 + int row = _addRow();
75.301 + _setRowCoeffs(row, b, e);
75.302 + _setRowLowerBound(row, l);
75.303 + _setRowUpperBound(row, u);
75.304 + return row;
75.305 + }
75.306 +
75.307 virtual void _eraseCol(int col) = 0;
75.308 virtual void _eraseRow(int row) = 0;
75.309
75.310 @@ -1207,8 +1215,10 @@
75.311 ///\param u is the upper bound (\ref INF means no bound)
75.312 ///\return The created row.
75.313 Row addRow(Value l,const Expr &e, Value u) {
75.314 - Row r=addRow();
75.315 - row(r,l,e,u);
75.316 + Row r;
75.317 + e.simplify();
75.318 + r._id = _addRowId(_addRow(l - *e, ExprIterator(e.comps.begin(), cols),
75.319 + ExprIterator(e.comps.end(), cols), u - *e));
75.320 return r;
75.321 }
75.322
75.323 @@ -1217,8 +1227,12 @@
75.324 ///\param c is a linear expression (see \ref Constr)
75.325 ///\return The created row.
75.326 Row addRow(const Constr &c) {
75.327 - Row r=addRow();
75.328 - row(r,c);
75.329 + Row r;
75.330 + c.expr().simplify();
75.331 + r._id = _addRowId(_addRow(c.lowerBounded()?c.lowerBound()-*c.expr():-INF,
75.332 + ExprIterator(c.expr().comps.begin(), cols),
75.333 + ExprIterator(c.expr().comps.end(), cols),
75.334 + c.upperBounded()?c.upperBound()-*c.expr():INF));
75.335 return r;
75.336 }
75.337 ///Erase a column (i.e a variable) from the LP
75.338 @@ -1803,10 +1817,10 @@
75.339 ///The basis status of variables
75.340 enum VarStatus {
75.341 /// The variable is in the basis
75.342 - BASIC,
75.343 + BASIC,
75.344 /// The variable is free, but not basic
75.345 FREE,
75.346 - /// The variable has active lower bound
75.347 + /// The variable has active lower bound
75.348 LOWER,
75.349 /// The variable has active upper bound
75.350 UPPER,
75.351 @@ -1885,7 +1899,7 @@
75.352 return res;
75.353 }
75.354 /// Returns a component of the primal ray
75.355 -
75.356 +
75.357 /// The primal ray is solution of the modified primal problem,
75.358 /// where we change each finite bound to 0, and we looking for a
75.359 /// negative objective value in case of minimization, and positive
75.360 @@ -1919,7 +1933,7 @@
75.361 }
75.362
75.363 /// Returns a component of the dual ray
75.364 -
75.365 +
75.366 /// The dual ray is solution of the modified primal problem, where
75.367 /// we change each finite bound to 0 (i.e. the objective function
75.368 /// coefficients in the primal problem), and we looking for a
75.369 @@ -2061,7 +2075,7 @@
75.370 return res;
75.371 }
75.372 ///The value of the objective function
75.373 -
75.374 +
75.375 ///\return
75.376 ///- \ref INF or -\ref INF means either infeasibility or unboundedness
75.377 /// of the problem, depending on whether we minimize or maximize.
76.1 --- a/lemon/lp_skeleton.cc Tue Dec 20 17:44:38 2011 +0100
76.2 +++ b/lemon/lp_skeleton.cc Tue Dec 20 18:15:14 2011 +0100
76.3 @@ -2,7 +2,7 @@
76.4 *
76.5 * This file is a part of LEMON, a generic C++ optimization library.
76.6 *
76.7 - * Copyright (C) 2003-2008
76.8 + * Copyright (C) 2003-2010
76.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
76.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
76.11 *
76.12 @@ -32,6 +32,11 @@
76.13 return ++row_num;
76.14 }
76.15
76.16 + int SkeletonSolverBase::_addRow(Value, ExprIterator, ExprIterator, Value)
76.17 + {
76.18 + return ++row_num;
76.19 + }
76.20 +
76.21 void SkeletonSolverBase::_eraseCol(int) {}
76.22 void SkeletonSolverBase::_eraseRow(int) {}
76.23
77.1 --- a/lemon/lp_skeleton.h Tue Dec 20 17:44:38 2011 +0100
77.2 +++ b/lemon/lp_skeleton.h Tue Dec 20 18:15:14 2011 +0100
77.3 @@ -2,7 +2,7 @@
77.4 *
77.5 * This file is a part of LEMON, a generic C++ optimization library.
77.6 *
77.7 - * Copyright (C) 2003-2008
77.8 + * Copyright (C) 2003-2010
77.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
77.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
77.11 *
77.12 @@ -23,13 +23,13 @@
77.13
77.14 ///\file
77.15 ///\brief Skeleton file to implement LP/MIP solver interfaces
77.16 -///
77.17 +///
77.18 ///The classes in this file do nothing, but they can serve as skeletons when
77.19 ///implementing an interface to new solvers.
77.20 namespace lemon {
77.21
77.22 ///A skeleton class to implement LP/MIP solver base interface
77.23 -
77.24 +
77.25 ///This class does nothing, but it can serve as a skeleton when
77.26 ///implementing an interface to new solvers.
77.27 class SkeletonSolverBase : public virtual LpBase {
77.28 @@ -45,6 +45,8 @@
77.29 /// \e
77.30 virtual int _addRow();
77.31 /// \e
77.32 + virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
77.33 + /// \e
77.34 virtual void _eraseCol(int i);
77.35 /// \e
77.36 virtual void _eraseRow(int i);
78.1 --- a/lemon/maps.h Tue Dec 20 17:44:38 2011 +0100
78.2 +++ b/lemon/maps.h Tue Dec 20 18:15:14 2011 +0100
78.3 @@ -2,7 +2,7 @@
78.4 *
78.5 * This file is a part of LEMON, a generic C++ optimization library.
78.6 *
78.7 - * Copyright (C) 2003-2009
78.8 + * Copyright (C) 2003-2010
78.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
78.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
78.11 *
78.12 @@ -22,6 +22,7 @@
78.13 #include <iterator>
78.14 #include <functional>
78.15 #include <vector>
78.16 +#include <map>
78.17
78.18 #include <lemon/core.h>
78.19
78.20 @@ -29,8 +30,6 @@
78.21 ///\ingroup maps
78.22 ///\brief Miscellaneous property maps
78.23
78.24 -#include <map>
78.25 -
78.26 namespace lemon {
78.27
78.28 /// \addtogroup maps
78.29 @@ -57,7 +56,7 @@
78.30 /// its type definitions, or if you have to provide a writable map,
78.31 /// but data written to it is not required (i.e. it will be sent to
78.32 /// <tt>/dev/null</tt>).
78.33 - /// It conforms the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
78.34 + /// It conforms to the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
78.35 ///
78.36 /// \sa ConstMap
78.37 template<typename K, typename V>
78.38 @@ -90,7 +89,7 @@
78.39 /// value to each key.
78.40 ///
78.41 /// In other aspects it is equivalent to \c NullMap.
78.42 - /// So it conforms the \ref concepts::ReadWriteMap "ReadWriteMap"
78.43 + /// So it conforms to the \ref concepts::ReadWriteMap "ReadWriteMap"
78.44 /// concept, but it absorbs the data written to it.
78.45 ///
78.46 /// The simplest way of using this map is through the constMap()
78.47 @@ -159,7 +158,7 @@
78.48 /// value to each key.
78.49 ///
78.50 /// In other aspects it is equivalent to \c NullMap.
78.51 - /// So it conforms the \ref concepts::ReadWriteMap "ReadWriteMap"
78.52 + /// So it conforms to the \ref concepts::ReadWriteMap "ReadWriteMap"
78.53 /// concept, but it absorbs the data written to it.
78.54 ///
78.55 /// The simplest way of using this map is through the constMap()
78.56 @@ -231,9 +230,9 @@
78.57 ///
78.58 /// This map is essentially a wrapper for \c std::vector. It assigns
78.59 /// values to integer keys from the range <tt>[0..size-1]</tt>.
78.60 - /// It can be used with some data structures, for example
78.61 - /// \c UnionFind, \c BinHeap, when the used items are small
78.62 - /// integers. This map conforms the \ref concepts::ReferenceMap
78.63 + /// It can be used together with some data structures, e.g.
78.64 + /// heap types and \c UnionFind, when the used items are small
78.65 + /// integers. This map conforms to the \ref concepts::ReferenceMap
78.66 /// "ReferenceMap" concept.
78.67 ///
78.68 /// The simplest way of using this map is through the rangeMap()
78.69 @@ -341,7 +340,7 @@
78.70 /// that you can specify a default value for the keys that are not
78.71 /// stored actually. This value can be different from the default
78.72 /// contructed value (i.e. \c %Value()).
78.73 - /// This type conforms the \ref concepts::ReferenceMap "ReferenceMap"
78.74 + /// This type conforms to the \ref concepts::ReferenceMap "ReferenceMap"
78.75 /// concept.
78.76 ///
78.77 /// This map is useful if a default value should be assigned to most of
78.78 @@ -349,9 +348,9 @@
78.79 /// keys (i.e. the map is "sparse").
78.80 /// The name of this type also refers to this important usage.
78.81 ///
78.82 - /// Apart form that this map can be used in many other cases since it
78.83 + /// Apart form that, this map can be used in many other cases since it
78.84 /// is based on \c std::map, which is a general associative container.
78.85 - /// However keep in mind that it is usually not as efficient as other
78.86 + /// However, keep in mind that it is usually not as efficient as other
78.87 /// maps.
78.88 ///
78.89 /// The simplest way of using this map is through the sparseMap()
78.90 @@ -707,7 +706,7 @@
78.91 /// "readable map" to another type using the default conversion.
78.92 /// The \c Key type of it is inherited from \c M and the \c Value
78.93 /// type is \c V.
78.94 - /// This type conforms the \ref concepts::ReadMap "ReadMap" concept.
78.95 + /// This type conforms to the \ref concepts::ReadMap "ReadMap" concept.
78.96 ///
78.97 /// The simplest way of using this map is through the convertMap()
78.98 /// function.
78.99 @@ -1786,22 +1785,22 @@
78.100 ///
78.101 /// The most important usage of it is storing certain nodes or arcs
78.102 /// that were marked \c true by an algorithm.
78.103 - /// For example it makes easier to store the nodes in the processing
78.104 + /// For example, it makes easier to store the nodes in the processing
78.105 /// order of Dfs algorithm, as the following examples show.
78.106 /// \code
78.107 /// std::vector<Node> v;
78.108 - /// dfs(g,s).processedMap(loggerBoolMap(std::back_inserter(v))).run();
78.109 + /// dfs(g).processedMap(loggerBoolMap(std::back_inserter(v))).run(s);
78.110 /// \endcode
78.111 /// \code
78.112 /// std::vector<Node> v(countNodes(g));
78.113 - /// dfs(g,s).processedMap(loggerBoolMap(v.begin())).run();
78.114 + /// dfs(g).processedMap(loggerBoolMap(v.begin())).run(s);
78.115 /// \endcode
78.116 ///
78.117 /// \note The container of the iterator must contain enough space
78.118 /// for the elements or the iterator should be an inserter iterator.
78.119 ///
78.120 /// \note LoggerBoolMap is just \ref concepts::WriteMap "writable", so
78.121 - /// it cannot be used when a readable map is needed, for example as
78.122 + /// it cannot be used when a readable map is needed, for example, as
78.123 /// \c ReachedMap for \c Bfs, \c Dfs and \c Dijkstra algorithms.
78.124 ///
78.125 /// \relates LoggerBoolMap
78.126 @@ -1818,7 +1817,7 @@
78.127 /// \brief Provides an immutable and unique id for each item in a graph.
78.128 ///
78.129 /// IdMap provides a unique and immutable id for each item of the
78.130 - /// same type (\c Node, \c Arc or \c Edge) in a graph. This id is
78.131 + /// same type (\c Node, \c Arc or \c Edge) in a graph. This id is
78.132 /// - \b unique: different items get different ids,
78.133 /// - \b immutable: the id of an item does not change (even if you
78.134 /// delete other nodes).
78.135 @@ -1826,7 +1825,7 @@
78.136 /// Using this map you get access (i.e. can read) the inner id values of
78.137 /// the items stored in the graph, which is returned by the \c id()
78.138 /// function of the graph. This map can be inverted with its member
78.139 - /// class \c InverseMap or with the \c operator() member.
78.140 + /// class \c InverseMap or with the \c operator()() member.
78.141 ///
78.142 /// \tparam GR The graph type.
78.143 /// \tparam K The key type of the map (\c GR::Node, \c GR::Arc or
78.144 @@ -1866,9 +1865,11 @@
78.145
78.146 public:
78.147
78.148 - /// \brief This class represents the inverse of its owner (IdMap).
78.149 + /// \brief The inverse map type of IdMap.
78.150 ///
78.151 - /// This class represents the inverse of its owner (IdMap).
78.152 + /// The inverse map type of IdMap. The subscript operator gives back
78.153 + /// an item by its id.
78.154 + /// This type conforms to the \ref concepts::ReadMap "ReadMap" concept.
78.155 /// \see inverse()
78.156 class InverseMap {
78.157 public:
78.158 @@ -1883,9 +1884,9 @@
78.159 /// Constructor for creating an id-to-item map.
78.160 explicit InverseMap(const IdMap& map) : _graph(map._graph) {}
78.161
78.162 - /// \brief Gives back the given item from its id.
78.163 + /// \brief Gives back an item by its id.
78.164 ///
78.165 - /// Gives back the given item from its id.
78.166 + /// Gives back an item by its id.
78.167 Item operator[](int id) const { return _graph->fromId(id, Item());}
78.168
78.169 private:
78.170 @@ -1898,14 +1899,31 @@
78.171 InverseMap inverse() const { return InverseMap(*_graph);}
78.172 };
78.173
78.174 + /// \brief Returns an \c IdMap class.
78.175 + ///
78.176 + /// This function just returns an \c IdMap class.
78.177 + /// \relates IdMap
78.178 + template <typename K, typename GR>
78.179 + inline IdMap<GR, K> idMap(const GR& graph) {
78.180 + return IdMap<GR, K>(graph);
78.181 + }
78.182
78.183 /// \brief General cross reference graph map type.
78.184
78.185 /// This class provides simple invertable graph maps.
78.186 /// It wraps a standard graph map (\c NodeMap, \c ArcMap or \c EdgeMap)
78.187 /// and if a key is set to a new value, then stores it in the inverse map.
78.188 - /// The values of the map can be accessed
78.189 - /// with stl compatible forward iterator.
78.190 + /// The graph items can be accessed by their values either using
78.191 + /// \c InverseMap or \c operator()(), and the values of the map can be
78.192 + /// accessed with an STL compatible forward iterator (\c ValueIt).
78.193 + ///
78.194 + /// This map is intended to be used when all associated values are
78.195 + /// different (the map is actually invertable) or there are only a few
78.196 + /// items with the same value.
78.197 + /// Otherwise consider to use \c IterableValueMap, which is more
78.198 + /// suitable and more efficient for such cases. It provides iterators
78.199 + /// to traverse the items with the same associated value, but
78.200 + /// it does not have \c InverseMap.
78.201 ///
78.202 /// This type is not reference map, so it cannot be modified with
78.203 /// the subscript operator.
78.204 @@ -1946,56 +1964,66 @@
78.205
78.206 /// \brief Forward iterator for values.
78.207 ///
78.208 - /// This iterator is an stl compatible forward
78.209 + /// This iterator is an STL compatible forward
78.210 /// iterator on the values of the map. The values can
78.211 /// be accessed in the <tt>[beginValue, endValue)</tt> range.
78.212 /// They are considered with multiplicity, so each value is
78.213 /// traversed for each item it is assigned to.
78.214 - class ValueIterator
78.215 + class ValueIt
78.216 : public std::iterator<std::forward_iterator_tag, Value> {
78.217 friend class CrossRefMap;
78.218 private:
78.219 - ValueIterator(typename Container::const_iterator _it)
78.220 + ValueIt(typename Container::const_iterator _it)
78.221 : it(_it) {}
78.222 public:
78.223
78.224 - ValueIterator() {}
78.225 -
78.226 - ValueIterator& operator++() { ++it; return *this; }
78.227 - ValueIterator operator++(int) {
78.228 - ValueIterator tmp(*this);
78.229 + /// Constructor
78.230 + ValueIt() {}
78.231 +
78.232 + /// \e
78.233 + ValueIt& operator++() { ++it; return *this; }
78.234 + /// \e
78.235 + ValueIt operator++(int) {
78.236 + ValueIt tmp(*this);
78.237 operator++();
78.238 return tmp;
78.239 }
78.240
78.241 + /// \e
78.242 const Value& operator*() const { return it->first; }
78.243 + /// \e
78.244 const Value* operator->() const { return &(it->first); }
78.245
78.246 - bool operator==(ValueIterator jt) const { return it == jt.it; }
78.247 - bool operator!=(ValueIterator jt) const { return it != jt.it; }
78.248 + /// \e
78.249 + bool operator==(ValueIt jt) const { return it == jt.it; }
78.250 + /// \e
78.251 + bool operator!=(ValueIt jt) const { return it != jt.it; }
78.252
78.253 private:
78.254 typename Container::const_iterator it;
78.255 };
78.256
78.257 + /// Alias for \c ValueIt
78.258 + typedef ValueIt ValueIterator;
78.259 +
78.260 /// \brief Returns an iterator to the first value.
78.261 ///
78.262 - /// Returns an stl compatible iterator to the
78.263 + /// Returns an STL compatible iterator to the
78.264 /// first value of the map. The values of the
78.265 /// map can be accessed in the <tt>[beginValue, endValue)</tt>
78.266 /// range.
78.267 - ValueIterator beginValue() const {
78.268 - return ValueIterator(_inv_map.begin());
78.269 + ValueIt beginValue() const {
78.270 + return ValueIt(_inv_map.begin());
78.271 }
78.272
78.273 /// \brief Returns an iterator after the last value.
78.274 ///
78.275 - /// Returns an stl compatible iterator after the
78.276 + /// Returns an STL compatible iterator after the
78.277 /// last value of the map. The values of the
78.278 /// map can be accessed in the <tt>[beginValue, endValue)</tt>
78.279 /// range.
78.280 - ValueIterator endValue() const {
78.281 - return ValueIterator(_inv_map.end());
78.282 + ValueIt endValue() const {
78.283 + return ValueIt(_inv_map.end());
78.284 }
78.285
78.286 /// \brief Sets the value associated with the given key.
78.287 @@ -2034,6 +2062,14 @@
78.288 return it != _inv_map.end() ? it->second : INVALID;
78.289 }
78.290
78.291 + /// \brief Returns the number of items with the given value.
78.292 + ///
78.293 + /// This function returns the number of items with the given value
78.294 + /// associated with it.
78.295 + int count(const Value &val) const {
78.296 + return _inv_map.count(val);
78.297 + }
78.298 +
78.299 protected:
78.300
78.301 /// \brief Erase the key from the map and the inverse map.
78.302 @@ -2083,10 +2119,12 @@
78.303
78.304 public:
78.305
78.306 - /// \brief The inverse map type.
78.307 + /// \brief The inverse map type of CrossRefMap.
78.308 ///
78.309 - /// The inverse of this map. The subscript operator of the map
78.310 - /// gives back the item that was last assigned to the value.
78.311 + /// The inverse map type of CrossRefMap. The subscript operator gives
78.312 + /// back an item by its value.
78.313 + /// This type conforms to the \ref concepts::ReadMap "ReadMap" concept.
78.314 + /// \see inverse()
78.315 class InverseMap {
78.316 public:
78.317 /// \brief Constructor
78.318 @@ -2113,20 +2151,20 @@
78.319 const CrossRefMap& _inverted;
78.320 };
78.321
78.322 - /// \brief It gives back the read-only inverse map.
78.323 + /// \brief Gives back the inverse of the map.
78.324 ///
78.325 - /// It gives back the read-only inverse map.
78.326 + /// Gives back the inverse of the CrossRefMap.
78.327 InverseMap inverse() const {
78.328 return InverseMap(*this);
78.329 }
78.330
78.331 };
78.332
78.333 - /// \brief Provides continuous and unique ID for the
78.334 + /// \brief Provides continuous and unique id for the
78.335 /// items of a graph.
78.336 ///
78.337 /// RangeIdMap provides a unique and continuous
78.338 - /// ID for each item of a given type (\c Node, \c Arc or
78.339 + /// id for each item of a given type (\c Node, \c Arc or
78.340 /// \c Edge) in a graph. This id is
78.341 /// - \b unique: different items get different ids,
78.342 /// - \b continuous: the range of the ids is the set of integers
78.343 @@ -2137,7 +2175,7 @@
78.344 /// Thus this id is not (necessarily) the same as what can get using
78.345 /// the \c id() function of the graph or \ref IdMap.
78.346 /// This map can be inverted with its member class \c InverseMap,
78.347 - /// or with the \c operator() member.
78.348 + /// or with the \c operator()() member.
78.349 ///
78.350 /// \tparam GR The graph type.
78.351 /// \tparam K The key type of the map (\c GR::Node, \c GR::Arc or
78.352 @@ -2265,16 +2303,16 @@
78.353 _inv_map[pi] = q;
78.354 }
78.355
78.356 - /// \brief Gives back the \e RangeId of the item
78.357 + /// \brief Gives back the \e range \e id of the item
78.358 ///
78.359 - /// Gives back the \e RangeId of the item.
78.360 + /// Gives back the \e range \e id of the item.
78.361 int operator[](const Item& item) const {
78.362 return Map::operator[](item);
78.363 }
78.364
78.365 - /// \brief Gives back the item belonging to a \e RangeId
78.366 - ///
78.367 - /// Gives back the item belonging to a \e RangeId.
78.368 + /// \brief Gives back the item belonging to a \e range \e id
78.369 + ///
78.370 + /// Gives back the item belonging to the given \e range \e id.
78.371 Item operator()(int id) const {
78.372 return _inv_map[id];
78.373 }
78.374 @@ -2288,7 +2326,9 @@
78.375
78.376 /// \brief The inverse map type of RangeIdMap.
78.377 ///
78.378 - /// The inverse map type of RangeIdMap.
78.379 + /// The inverse map type of RangeIdMap. The subscript operator gives
78.380 + /// back an item by its \e range \e id.
78.381 + /// This type conforms to the \ref concepts::ReadMap "ReadMap" concept.
78.382 class InverseMap {
78.383 public:
78.384 /// \brief Constructor
78.385 @@ -2306,7 +2346,7 @@
78.386 /// \brief Subscript operator.
78.387 ///
78.388 /// Subscript operator. It gives back the item
78.389 - /// that the descriptor currently belongs to.
78.390 + /// that the given \e range \e id currently belongs to.
78.391 Value operator[](const Key& key) const {
78.392 return _inverted(key);
78.393 }
78.394 @@ -2324,12 +2364,932 @@
78.395
78.396 /// \brief Gives back the inverse of the map.
78.397 ///
78.398 - /// Gives back the inverse of the map.
78.399 + /// Gives back the inverse of the RangeIdMap.
78.400 const InverseMap inverse() const {
78.401 return InverseMap(*this);
78.402 }
78.403 };
78.404
78.405 + /// \brief Returns a \c RangeIdMap class.
78.406 + ///
78.407 + /// This function just returns an \c RangeIdMap class.
78.408 + /// \relates RangeIdMap
78.409 + template <typename K, typename GR>
78.410 + inline RangeIdMap<GR, K> rangeIdMap(const GR& graph) {
78.411 + return RangeIdMap<GR, K>(graph);
78.412 + }
78.413 +
78.414 + /// \brief Dynamic iterable \c bool map.
78.415 + ///
78.416 + /// This class provides a special graph map type which can store a
78.417 + /// \c bool value for graph items (\c Node, \c Arc or \c Edge).
78.418 + /// For both \c true and \c false values it is possible to iterate on
78.419 + /// the keys mapped to the value.
78.420 + ///
78.421 + /// This type is a reference map, so it can be modified with the
78.422 + /// subscript operator.
78.423 + ///
78.424 + /// \tparam GR The graph type.
78.425 + /// \tparam K The key type of the map (\c GR::Node, \c GR::Arc or
78.426 + /// \c GR::Edge).
78.427 + ///
78.428 + /// \see IterableIntMap, IterableValueMap
78.429 + /// \see CrossRefMap
78.430 + template <typename GR, typename K>
78.431 + class IterableBoolMap
78.432 + : protected ItemSetTraits<GR, K>::template Map<int>::Type {
78.433 + private:
78.434 + typedef GR Graph;
78.435 +
78.436 + typedef typename ItemSetTraits<GR, K>::ItemIt KeyIt;
78.437 + typedef typename ItemSetTraits<GR, K>::template Map<int>::Type Parent;
78.438 +
78.439 + std::vector<K> _array;
78.440 + int _sep;
78.441 +
78.442 + public:
78.443 +
78.444 + /// Indicates that the map is reference map.
78.445 + typedef True ReferenceMapTag;
78.446 +
78.447 + /// The key type
78.448 + typedef K Key;
78.449 + /// The value type
78.450 + typedef bool Value;
78.451 + /// The const reference type.
78.452 + typedef const Value& ConstReference;
78.453 +
78.454 + private:
78.455 +
78.456 + int position(const Key& key) const {
78.457 + return Parent::operator[](key);
78.458 + }
78.459 +
78.460 + public:
78.461 +
78.462 + /// \brief Reference to the value of the map.
78.463 + ///
78.464 + /// This class is similar to the \c bool type. It can be converted to
78.465 + /// \c bool and it provides the same operators.
78.466 + class Reference {
78.467 + friend class IterableBoolMap;
78.468 + private:
78.469 + Reference(IterableBoolMap& map, const Key& key)
78.470 + : _key(key), _map(map) {}
78.471 + public:
78.472 +
78.473 + Reference& operator=(const Reference& value) {
78.474 + _map.set(_key, static_cast<bool>(value));
78.475 + return *this;
78.476 + }
78.477 +
78.478 + operator bool() const {
78.479 + return static_cast<const IterableBoolMap&>(_map)[_key];
78.480 + }
78.481 +
78.482 + Reference& operator=(bool value) {
78.483 + _map.set(_key, value);
78.484 + return *this;
78.485 + }
78.486 + Reference& operator&=(bool value) {
78.487 + _map.set(_key, _map[_key] & value);
78.488 + return *this;
78.489 + }
78.490 + Reference& operator|=(bool value) {
78.491 + _map.set(_key, _map[_key] | value);
78.492 + return *this;
78.493 + }
78.494 + Reference& operator^=(bool value) {
78.495 + _map.set(_key, _map[_key] ^ value);
78.496 + return *this;
78.497 + }
78.498 + private:
78.499 + Key _key;
78.500 + IterableBoolMap& _map;
78.501 + };
78.502 +
78.503 + /// \brief Constructor of the map with a default value.
78.504 + ///
78.505 + /// Constructor of the map with a default value.
78.506 + explicit IterableBoolMap(const Graph& graph, bool def = false)
78.507 + : Parent(graph) {
78.508 + typename Parent::Notifier* nf = Parent::notifier();
78.509 + Key it;
78.510 + for (nf->first(it); it != INVALID; nf->next(it)) {
78.511 + Parent::set(it, _array.size());
78.512 + _array.push_back(it);
78.513 + }
78.514 + _sep = (def ? _array.size() : 0);
78.515 + }
78.516 +
78.517 + /// \brief Const subscript operator of the map.
78.518 + ///
78.519 + /// Const subscript operator of the map.
78.520 + bool operator[](const Key& key) const {
78.521 + return position(key) < _sep;
78.522 + }
78.523 +
78.524 + /// \brief Subscript operator of the map.
78.525 + ///
78.526 + /// Subscript operator of the map.
78.527 + Reference operator[](const Key& key) {
78.528 + return Reference(*this, key);
78.529 + }
78.530 +
78.531 + /// \brief Set operation of the map.
78.532 + ///
78.533 + /// Set operation of the map.
78.534 + void set(const Key& key, bool value) {
78.535 + int pos = position(key);
78.536 + if (value) {
78.537 + if (pos < _sep) return;
78.538 + Key tmp = _array[_sep];
78.539 + _array[_sep] = key;
78.540 + Parent::set(key, _sep);
78.541 + _array[pos] = tmp;
78.542 + Parent::set(tmp, pos);
78.543 + ++_sep;
78.544 + } else {
78.545 + if (pos >= _sep) return;
78.546 + --_sep;
78.547 + Key tmp = _array[_sep];
78.548 + _array[_sep] = key;
78.549 + Parent::set(key, _sep);
78.550 + _array[pos] = tmp;
78.551 + Parent::set(tmp, pos);
78.552 + }
78.553 + }
78.554 +
78.555 + /// \brief Set all items.
78.556 + ///
78.557 + /// Set all items in the map.
78.558 + /// \note Constant time operation.
78.559 + void setAll(bool value) {
78.560 + _sep = (value ? _array.size() : 0);
78.561 + }
78.562 +
78.563 + /// \brief Returns the number of the keys mapped to \c true.
78.564 + ///
78.565 + /// Returns the number of the keys mapped to \c true.
78.566 + int trueNum() const {
78.567 + return _sep;
78.568 + }
78.569 +
78.570 + /// \brief Returns the number of the keys mapped to \c false.
78.571 + ///
78.572 + /// Returns the number of the keys mapped to \c false.
78.573 + int falseNum() const {
78.574 + return _array.size() - _sep;
78.575 + }
78.576 +
78.577 + /// \brief Iterator for the keys mapped to \c true.
78.578 + ///
78.579 + /// Iterator for the keys mapped to \c true. It works
78.580 + /// like a graph item iterator, it can be converted to
78.581 + /// the key type of the map, incremented with \c ++ operator, and
78.582 + /// if the iterator leaves the last valid key, it will be equal to
78.583 + /// \c INVALID.
78.584 + class TrueIt : public Key {
78.585 + public:
78.586 + typedef Key Parent;
78.587 +
78.588 + /// \brief Creates an iterator.
78.589 + ///
78.590 + /// Creates an iterator. It iterates on the
78.591 + /// keys mapped to \c true.
78.592 + /// \param map The IterableBoolMap.
78.593 + explicit TrueIt(const IterableBoolMap& map)
78.594 + : Parent(map._sep > 0 ? map._array[map._sep - 1] : INVALID),
78.595 + _map(&map) {}
78.596 +
78.597 + /// \brief Invalid constructor \& conversion.
78.598 + ///
78.599 + /// This constructor initializes the iterator to be invalid.
78.600 + /// \sa Invalid for more details.
78.601 + TrueIt(Invalid) : Parent(INVALID), _map(0) {}
78.602 +
78.603 + /// \brief Increment operator.
78.604 + ///
78.605 + /// Increment operator.
78.606 + TrueIt& operator++() {
78.607 + int pos = _map->position(*this);
78.608 + Parent::operator=(pos > 0 ? _map->_array[pos - 1] : INVALID);
78.609 + return *this;
78.610 + }
78.611 +
78.612 + private:
78.613 + const IterableBoolMap* _map;
78.614 + };
78.615 +
78.616 + /// \brief Iterator for the keys mapped to \c false.
78.617 + ///
78.618 + /// Iterator for the keys mapped to \c false. It works
78.619 + /// like a graph item iterator, it can be converted to
78.620 + /// the key type of the map, incremented with \c ++ operator, and
78.621 + /// if the iterator leaves the last valid key, it will be equal to
78.622 + /// \c INVALID.
78.623 + class FalseIt : public Key {
78.624 + public:
78.625 + typedef Key Parent;
78.626 +
78.627 + /// \brief Creates an iterator.
78.628 + ///
78.629 + /// Creates an iterator. It iterates on the
78.630 + /// keys mapped to \c false.
78.631 + /// \param map The IterableBoolMap.
78.632 + explicit FalseIt(const IterableBoolMap& map)
78.633 + : Parent(map._sep < int(map._array.size()) ?
78.634 + map._array.back() : INVALID), _map(&map) {}
78.635 +
78.636 + /// \brief Invalid constructor \& conversion.
78.637 + ///
78.638 + /// This constructor initializes the iterator to be invalid.
78.639 + /// \sa Invalid for more details.
78.640 + FalseIt(Invalid) : Parent(INVALID), _map(0) {}
78.641 +
78.642 + /// \brief Increment operator.
78.643 + ///
78.644 + /// Increment operator.
78.645 + FalseIt& operator++() {
78.646 + int pos = _map->position(*this);
78.647 + Parent::operator=(pos > _map->_sep ? _map->_array[pos - 1] : INVALID);
78.648 + return *this;
78.649 + }
78.650 +
78.651 + private:
78.652 + const IterableBoolMap* _map;
78.653 + };
78.654 +
78.655 + /// \brief Iterator for the keys mapped to a given value.
78.656 + ///
78.657 + /// Iterator for the keys mapped to a given value. It works
78.658 + /// like a graph item iterator, it can be converted to
78.659 + /// the key type of the map, incremented with \c ++ operator, and
78.660 + /// if the iterator leaves the last valid key, it will be equal to
78.661 + /// \c INVALID.
78.662 + class ItemIt : public Key {
78.663 + public:
78.664 + typedef Key Parent;
78.665 +
78.666 + /// \brief Creates an iterator with a value.
78.667 + ///
78.668 + /// Creates an iterator with a value. It iterates on the
78.669 + /// keys mapped to the given value.
78.670 + /// \param map The IterableBoolMap.
78.671 + /// \param value The value.
78.672 + ItemIt(const IterableBoolMap& map, bool value)
78.673 + : Parent(value ?
78.674 + (map._sep > 0 ?
78.675 + map._array[map._sep - 1] : INVALID) :
78.676 + (map._sep < int(map._array.size()) ?
78.677 + map._array.back() : INVALID)), _map(&map) {}
78.678 +
78.679 + /// \brief Invalid constructor \& conversion.
78.680 + ///
78.681 + /// This constructor initializes the iterator to be invalid.
78.682 + /// \sa Invalid for more details.
78.683 + ItemIt(Invalid) : Parent(INVALID), _map(0) {}
78.684 +
78.685 + /// \brief Increment operator.
78.686 + ///
78.687 + /// Increment operator.
78.688 + ItemIt& operator++() {
78.689 + int pos = _map->position(*this);
78.690 + int _sep = pos >= _map->_sep ? _map->_sep : 0;
78.691 + Parent::operator=(pos > _sep ? _map->_array[pos - 1] : INVALID);
78.692 + return *this;
78.693 + }
78.694 +
78.695 + private:
78.696 + const IterableBoolMap* _map;
78.697 + };
78.698 +
78.699 + protected:
78.700 +
78.701 + virtual void add(const Key& key) {
78.702 + Parent::add(key);
78.703 + Parent::set(key, _array.size());
78.704 + _array.push_back(key);
78.705 + }
78.706 +
78.707 + virtual void add(const std::vector<Key>& keys) {
78.708 + Parent::add(keys);
78.709 + for (int i = 0; i < int(keys.size()); ++i) {
78.710 + Parent::set(keys[i], _array.size());
78.711 + _array.push_back(keys[i]);
78.712 + }
78.713 + }
78.714 +
78.715 + virtual void erase(const Key& key) {
78.716 + int pos = position(key);
78.717 + if (pos < _sep) {
78.718 + --_sep;
78.719 + Parent::set(_array[_sep], pos);
78.720 + _array[pos] = _array[_sep];
78.721 + Parent::set(_array.back(), _sep);
78.722 + _array[_sep] = _array.back();
78.723 + _array.pop_back();
78.724 + } else {
78.725 + Parent::set(_array.back(), pos);
78.726 + _array[pos] = _array.back();
78.727 + _array.pop_back();
78.728 + }
78.729 + Parent::erase(key);
78.730 + }
78.731 +
78.732 + virtual void erase(const std::vector<Key>& keys) {
78.733 + for (int i = 0; i < int(keys.size()); ++i) {
78.734 + int pos = position(keys[i]);
78.735 + if (pos < _sep) {
78.736 + --_sep;
78.737 + Parent::set(_array[_sep], pos);
78.738 + _array[pos] = _array[_sep];
78.739 + Parent::set(_array.back(), _sep);
78.740 + _array[_sep] = _array.back();
78.741 + _array.pop_back();
78.742 + } else {
78.743 + Parent::set(_array.back(), pos);
78.744 + _array[pos] = _array.back();
78.745 + _array.pop_back();
78.746 + }
78.747 + }
78.748 + Parent::erase(keys);
78.749 + }
78.750 +
78.751 + virtual void build() {
78.752 + Parent::build();
78.753 + typename Parent::Notifier* nf = Parent::notifier();
78.754 + Key it;
78.755 + for (nf->first(it); it != INVALID; nf->next(it)) {
78.756 + Parent::set(it, _array.size());
78.757 + _array.push_back(it);
78.758 + }
78.759 + _sep = 0;
78.760 + }
78.761 +
78.762 + virtual void clear() {
78.763 + _array.clear();
78.764 + _sep = 0;
78.765 + Parent::clear();
78.766 + }
78.767 +
78.768 + };
78.769 +
78.770 +
78.771 + namespace _maps_bits {
78.772 + template <typename Item>
78.773 + struct IterableIntMapNode {
78.774 + IterableIntMapNode() : value(-1) {}
78.775 + IterableIntMapNode(int _value) : value(_value) {}
78.776 + Item prev, next;
78.777 + int value;
78.778 + };
78.779 + }
78.780 +
78.781 + /// \brief Dynamic iterable integer map.
78.782 + ///
78.783 + /// This class provides a special graph map type which can store an
78.784 + /// integer value for graph items (\c Node, \c Arc or \c Edge).
78.785 + /// For each non-negative value it is possible to iterate on the keys
78.786 + /// mapped to the value.
78.787 + ///
78.788 + /// This map is intended to be used with small integer values, for which
78.789 + /// it is efficient, and supports iteration only for non-negative values.
78.790 + /// If you need large values and/or iteration for negative integers,
78.791 + /// consider to use \ref IterableValueMap instead.
78.792 + ///
78.793 + /// This type is a reference map, so it can be modified with the
78.794 + /// subscript operator.
78.795 + ///
78.796 + /// \note The size of the data structure depends on the largest
78.797 + /// value in the map.
78.798 + ///
78.799 + /// \tparam GR The graph type.
78.800 + /// \tparam K The key type of the map (\c GR::Node, \c GR::Arc or
78.801 + /// \c GR::Edge).
78.802 + ///
78.803 + /// \see IterableBoolMap, IterableValueMap
78.804 + /// \see CrossRefMap
78.805 + template <typename GR, typename K>
78.806 + class IterableIntMap
78.807 + : protected ItemSetTraits<GR, K>::
78.808 + template Map<_maps_bits::IterableIntMapNode<K> >::Type {
78.809 + public:
78.810 + typedef typename ItemSetTraits<GR, K>::
78.811 + template Map<_maps_bits::IterableIntMapNode<K> >::Type Parent;
78.812 +
78.813 + /// The key type
78.814 + typedef K Key;
78.815 + /// The value type
78.816 + typedef int Value;
78.817 + /// The graph type
78.818 + typedef GR Graph;
78.819 +
78.820 + /// \brief Constructor of the map.
78.821 + ///
78.822 + /// Constructor of the map. It sets all values to -1.
78.823 + explicit IterableIntMap(const Graph& graph)
78.824 + : Parent(graph) {}
78.825 +
78.826 + /// \brief Constructor of the map with a given value.
78.827 + ///
78.828 + /// Constructor of the map with a given value.
78.829 + explicit IterableIntMap(const Graph& graph, int value)
78.830 + : Parent(graph, _maps_bits::IterableIntMapNode<K>(value)) {
78.831 + if (value >= 0) {
78.832 + for (typename Parent::ItemIt it(*this); it != INVALID; ++it) {
78.833 + lace(it);
78.834 + }
78.835 + }
78.836 + }
78.837 +
78.838 + private:
78.839 +
78.840 + void unlace(const Key& key) {
78.841 + typename Parent::Value& node = Parent::operator[](key);
78.842 + if (node.value < 0) return;
78.843 + if (node.prev != INVALID) {
78.844 + Parent::operator[](node.prev).next = node.next;
78.845 + } else {
78.846 + _first[node.value] = node.next;
78.847 + }
78.848 + if (node.next != INVALID) {
78.849 + Parent::operator[](node.next).prev = node.prev;
78.850 + }
78.851 + while (!_first.empty() && _first.back() == INVALID) {
78.852 + _first.pop_back();
78.853 + }
78.854 + }
78.855 +
78.856 + void lace(const Key& key) {
78.857 + typename Parent::Value& node = Parent::operator[](key);
78.858 + if (node.value < 0) return;
78.859 + if (node.value >= int(_first.size())) {
78.860 + _first.resize(node.value + 1, INVALID);
78.861 + }
78.862 + node.prev = INVALID;
78.863 + node.next = _first[node.value];
78.864 + if (node.next != INVALID) {
78.865 + Parent::operator[](node.next).prev = key;
78.866 + }
78.867 + _first[node.value] = key;
78.868 + }
78.869 +
78.870 + public:
78.871 +
78.872 + /// Indicates that the map is reference map.
78.873 + typedef True ReferenceMapTag;
78.874 +
78.875 + /// \brief Reference to the value of the map.
78.876 + ///
78.877 + /// This class is similar to the \c int type. It can
78.878 + /// be converted to \c int and it has the same operators.
78.879 + class Reference {
78.880 + friend class IterableIntMap;
78.881 + private:
78.882 + Reference(IterableIntMap& map, const Key& key)
78.883 + : _key(key), _map(map) {}
78.884 + public:
78.885 +
78.886 + Reference& operator=(const Reference& value) {
78.887 + _map.set(_key, static_cast<const int&>(value));
78.888 + return *this;
78.889 + }
78.890 +
78.891 + operator const int&() const {
78.892 + return static_cast<const IterableIntMap&>(_map)[_key];
78.893 + }
78.894 +
78.895 + Reference& operator=(int value) {
78.896 + _map.set(_key, value);
78.897 + return *this;
78.898 + }
78.899 + Reference& operator++() {
78.900 + _map.set(_key, _map[_key] + 1);
78.901 + return *this;
78.902 + }
78.903 + int operator++(int) {
78.904 + int value = _map[_key];
78.905 + _map.set(_key, value + 1);
78.906 + return value;
78.907 + }
78.908 + Reference& operator--() {
78.909 + _map.set(_key, _map[_key] - 1);
78.910 + return *this;
78.911 + }
78.912 + int operator--(int) {
78.913 + int value = _map[_key];
78.914 + _map.set(_key, value - 1);
78.915 + return value;
78.916 + }
78.917 + Reference& operator+=(int value) {
78.918 + _map.set(_key, _map[_key] + value);
78.919 + return *this;
78.920 + }
78.921 + Reference& operator-=(int value) {
78.922 + _map.set(_key, _map[_key] - value);
78.923 + return *this;
78.924 + }
78.925 + Reference& operator*=(int value) {
78.926 + _map.set(_key, _map[_key] * value);
78.927 + return *this;
78.928 + }
78.929 + Reference& operator/=(int value) {
78.930 + _map.set(_key, _map[_key] / value);
78.931 + return *this;
78.932 + }
78.933 + Reference& operator%=(int value) {
78.934 + _map.set(_key, _map[_key] % value);
78.935 + return *this;
78.936 + }
78.937 + Reference& operator&=(int value) {
78.938 + _map.set(_key, _map[_key] & value);
78.939 + return *this;
78.940 + }
78.941 + Reference& operator|=(int value) {
78.942 + _map.set(_key, _map[_key] | value);
78.943 + return *this;
78.944 + }
78.945 + Reference& operator^=(int value) {
78.946 + _map.set(_key, _map[_key] ^ value);
78.947 + return *this;
78.948 + }
78.949 + Reference& operator<<=(int value) {
78.950 + _map.set(_key, _map[_key] << value);
78.951 + return *this;
78.952 + }
78.953 + Reference& operator>>=(int value) {
78.954 + _map.set(_key, _map[_key] >> value);
78.955 + return *this;
78.956 + }
78.957 +
78.958 + private:
78.959 + Key _key;
78.960 + IterableIntMap& _map;
78.961 + };
78.962 +
78.963 + /// The const reference type.
78.964 + typedef const Value& ConstReference;
78.965 +
78.966 + /// \brief Gives back the maximal value plus one.
78.967 + ///
78.968 + /// Gives back the maximal value plus one.
78.969 + int size() const {
78.970 + return _first.size();
78.971 + }
78.972 +
78.973 + /// \brief Set operation of the map.
78.974 + ///
78.975 + /// Set operation of the map.
78.976 + void set(const Key& key, const Value& value) {
78.977 + unlace(key);
78.978 + Parent::operator[](key).value = value;
78.979 + lace(key);
78.980 + }
78.981 +
78.982 + /// \brief Const subscript operator of the map.
78.983 + ///
78.984 + /// Const subscript operator of the map.
78.985 + const Value& operator[](const Key& key) const {
78.986 + return Parent::operator[](key).value;
78.987 + }
78.988 +
78.989 + /// \brief Subscript operator of the map.
78.990 + ///
78.991 + /// Subscript operator of the map.
78.992 + Reference operator[](const Key& key) {
78.993 + return Reference(*this, key);
78.994 + }
78.995 +
78.996 + /// \brief Iterator for the keys with the same value.
78.997 + ///
78.998 + /// Iterator for the keys with the same value. It works
78.999 + /// like a graph item iterator, it can be converted to
78.1000 + /// the item type of the map, incremented with \c ++ operator, and
78.1001 + /// if the iterator leaves the last valid item, it will be equal to
78.1002 + /// \c INVALID.
78.1003 + class ItemIt : public Key {
78.1004 + public:
78.1005 + typedef Key Parent;
78.1006 +
78.1007 + /// \brief Invalid constructor \& conversion.
78.1008 + ///
78.1009 + /// This constructor initializes the iterator to be invalid.
78.1010 + /// \sa Invalid for more details.
78.1011 + ItemIt(Invalid) : Parent(INVALID), _map(0) {}
78.1012 +
78.1013 + /// \brief Creates an iterator with a value.
78.1014 + ///
78.1015 + /// Creates an iterator with a value. It iterates on the
78.1016 + /// keys mapped to the given value.
78.1017 + /// \param map The IterableIntMap.
78.1018 + /// \param value The value.
78.1019 + ItemIt(const IterableIntMap& map, int value) : _map(&map) {
78.1020 + if (value < 0 || value >= int(_map->_first.size())) {
78.1021 + Parent::operator=(INVALID);
78.1022 + } else {
78.1023 + Parent::operator=(_map->_first[value]);
78.1024 + }
78.1025 + }
78.1026 +
78.1027 + /// \brief Increment operator.
78.1028 + ///
78.1029 + /// Increment operator.
78.1030 + ItemIt& operator++() {
78.1031 + Parent::operator=(_map->IterableIntMap::Parent::
78.1032 + operator[](static_cast<Parent&>(*this)).next);
78.1033 + return *this;
78.1034 + }
78.1035 +
78.1036 + private:
78.1037 + const IterableIntMap* _map;
78.1038 + };
78.1039 +
78.1040 + protected:
78.1041 +
78.1042 + virtual void erase(const Key& key) {
78.1043 + unlace(key);
78.1044 + Parent::erase(key);
78.1045 + }
78.1046 +
78.1047 + virtual void erase(const std::vector<Key>& keys) {
78.1048 + for (int i = 0; i < int(keys.size()); ++i) {
78.1049 + unlace(keys[i]);
78.1050 + }
78.1051 + Parent::erase(keys);
78.1052 + }
78.1053 +
78.1054 + virtual void clear() {
78.1055 + _first.clear();
78.1056 + Parent::clear();
78.1057 + }
78.1058 +
78.1059 + private:
78.1060 + std::vector<Key> _first;
78.1061 + };
78.1062 +
78.1063 + namespace _maps_bits {
78.1064 + template <typename Item, typename Value>
78.1065 + struct IterableValueMapNode {
78.1066 + IterableValueMapNode(Value _value = Value()) : value(_value) {}
78.1067 + Item prev, next;
78.1068 + Value value;
78.1069 + };
78.1070 + }
78.1071 +
78.1072 + /// \brief Dynamic iterable map for comparable values.
78.1073 + ///
78.1074 + /// This class provides a special graph map type which can store a
78.1075 + /// comparable value for graph items (\c Node, \c Arc or \c Edge).
78.1076 + /// For each value it is possible to iterate on the keys mapped to
78.1077 + /// the value (\c ItemIt), and the values of the map can be accessed
78.1078 + /// with an STL compatible forward iterator (\c ValueIt).
78.1079 + /// The map stores a linked list for each value, which contains
78.1080 + /// the items mapped to the value, and the used values are stored
78.1081 + /// in balanced binary tree (\c std::map).
78.1082 + ///
78.1083 + /// \ref IterableBoolMap and \ref IterableIntMap are similar classes
78.1084 + /// specialized for \c bool and \c int values, respectively.
78.1085 + ///
78.1086 + /// This type is not reference map, so it cannot be modified with
78.1087 + /// the subscript operator.
78.1088 + ///
78.1089 + /// \tparam GR The graph type.
78.1090 + /// \tparam K The key type of the map (\c GR::Node, \c GR::Arc or
78.1091 + /// \c GR::Edge).
78.1092 + /// \tparam V The value type of the map. It can be any comparable
78.1093 + /// value type.
78.1094 + ///
78.1095 + /// \see IterableBoolMap, IterableIntMap
78.1096 + /// \see CrossRefMap
78.1097 + template <typename GR, typename K, typename V>
78.1098 + class IterableValueMap
78.1099 + : protected ItemSetTraits<GR, K>::
78.1100 + template Map<_maps_bits::IterableValueMapNode<K, V> >::Type {
78.1101 + public:
78.1102 + typedef typename ItemSetTraits<GR, K>::
78.1103 + template Map<_maps_bits::IterableValueMapNode<K, V> >::Type Parent;
78.1104 +
78.1105 + /// The key type
78.1106 + typedef K Key;
78.1107 + /// The value type
78.1108 + typedef V Value;
78.1109 + /// The graph type
78.1110 + typedef GR Graph;
78.1111 +
78.1112 + public:
78.1113 +
78.1114 + /// \brief Constructor of the map with a given value.
78.1115 + ///
78.1116 + /// Constructor of the map with a given value.
78.1117 + explicit IterableValueMap(const Graph& graph,
78.1118 + const Value& value = Value())
78.1119 + : Parent(graph, _maps_bits::IterableValueMapNode<K, V>(value)) {
78.1120 + for (typename Parent::ItemIt it(*this); it != INVALID; ++it) {
78.1121 + lace(it);
78.1122 + }
78.1123 + }
78.1124 +
78.1125 + protected:
78.1126 +
78.1127 + void unlace(const Key& key) {
78.1128 + typename Parent::Value& node = Parent::operator[](key);
78.1129 + if (node.prev != INVALID) {
78.1130 + Parent::operator[](node.prev).next = node.next;
78.1131 + } else {
78.1132 + if (node.next != INVALID) {
78.1133 + _first[node.value] = node.next;
78.1134 + } else {
78.1135 + _first.erase(node.value);
78.1136 + }
78.1137 + }
78.1138 + if (node.next != INVALID) {
78.1139 + Parent::operator[](node.next).prev = node.prev;
78.1140 + }
78.1141 + }
78.1142 +
78.1143 + void lace(const Key& key) {
78.1144 + typename Parent::Value& node = Parent::operator[](key);
78.1145 + typename std::map<Value, Key>::iterator it = _first.find(node.value);
78.1146 + if (it == _first.end()) {
78.1147 + node.prev = node.next = INVALID;
78.1148 + _first.insert(std::make_pair(node.value, key));
78.1149 + } else {
78.1150 + node.prev = INVALID;
78.1151 + node.next = it->second;
78.1152 + if (node.next != INVALID) {
78.1153 + Parent::operator[](node.next).prev = key;
78.1154 + }
78.1155 + it->second = key;
78.1156 + }
78.1157 + }
78.1158 +
78.1159 + public:
78.1160 +
78.1161 + /// \brief Forward iterator for values.
78.1162 + ///
78.1163 + /// This iterator is an STL compatible forward
78.1164 + /// iterator on the values of the map. The values can
78.1165 + /// be accessed in the <tt>[beginValue, endValue)</tt> range.
78.1166 + class ValueIt
78.1167 + : public std::iterator<std::forward_iterator_tag, Value> {
78.1168 + friend class IterableValueMap;
78.1169 + private:
78.1170 + ValueIt(typename std::map<Value, Key>::const_iterator _it)
78.1171 + : it(_it) {}
78.1172 + public:
78.1173 +
78.1174 + /// Constructor
78.1175 + ValueIt() {}
78.1176 +
78.1177 + /// \e
78.1178 + ValueIt& operator++() { ++it; return *this; }
78.1179 + /// \e
78.1180 + ValueIt operator++(int) {
78.1181 + ValueIt tmp(*this);
78.1182 + operator++();
78.1183 + return tmp;
78.1184 + }
78.1185 +
78.1186 + /// \e
78.1187 + const Value& operator*() const { return it->first; }
78.1188 + /// \e
78.1189 + const Value* operator->() const { return &(it->first); }
78.1190 +
78.1191 + /// \e
78.1192 + bool operator==(ValueIt jt) const { return it == jt.it; }
78.1193 + /// \e
78.1194 + bool operator!=(ValueIt jt) const { return it != jt.it; }
78.1195 +
78.1196 + private:
78.1197 + typename std::map<Value, Key>::const_iterator it;
78.1198 + };
78.1199 +
78.1200 + /// \brief Returns an iterator to the first value.
78.1201 + ///
78.1202 + /// Returns an STL compatible iterator to the
78.1203 + /// first value of the map. The values of the
78.1204 + /// map can be accessed in the <tt>[beginValue, endValue)</tt>
78.1205 + /// range.
78.1206 + ValueIt beginValue() const {
78.1207 + return ValueIt(_first.begin());
78.1208 + }
78.1209 +
78.1210 + /// \brief Returns an iterator after the last value.
78.1211 + ///
78.1212 + /// Returns an STL compatible iterator after the
78.1213 + /// last value of the map. The values of the
78.1214 + /// map can be accessed in the <tt>[beginValue, endValue)</tt>
78.1215 + /// range.
78.1216 + ValueIt endValue() const {
78.1217 + return ValueIt(_first.end());
78.1218 + }
78.1219 +
78.1220 + /// \brief Set operation of the map.
78.1221 + ///
78.1222 + /// Set operation of the map.
78.1223 + void set(const Key& key, const Value& value) {
78.1224 + unlace(key);
78.1225 + Parent::operator[](key).value = value;
78.1226 + lace(key);
78.1227 + }
78.1228 +
78.1229 + /// \brief Const subscript operator of the map.
78.1230 + ///
78.1231 + /// Const subscript operator of the map.
78.1232 + const Value& operator[](const Key& key) const {
78.1233 + return Parent::operator[](key).value;
78.1234 + }
78.1235 +
78.1236 + /// \brief Iterator for the keys with the same value.
78.1237 + ///
78.1238 + /// Iterator for the keys with the same value. It works
78.1239 + /// like a graph item iterator, it can be converted to
78.1240 + /// the item type of the map, incremented with \c ++ operator, and
78.1241 + /// if the iterator leaves the last valid item, it will be equal to
78.1242 + /// \c INVALID.
78.1243 + class ItemIt : public Key {
78.1244 + public:
78.1245 + typedef Key Parent;
78.1246 +
78.1247 + /// \brief Invalid constructor \& conversion.
78.1248 + ///
78.1249 + /// This constructor initializes the iterator to be invalid.
78.1250 + /// \sa Invalid for more details.
78.1251 + ItemIt(Invalid) : Parent(INVALID), _map(0) {}
78.1252 +
78.1253 + /// \brief Creates an iterator with a value.
78.1254 + ///
78.1255 + /// Creates an iterator with a value. It iterates on the
78.1256 + /// keys which have the given value.
78.1257 + /// \param map The IterableValueMap
78.1258 + /// \param value The value
78.1259 + ItemIt(const IterableValueMap& map, const Value& value) : _map(&map) {
78.1260 + typename std::map<Value, Key>::const_iterator it =
78.1261 + map._first.find(value);
78.1262 + if (it == map._first.end()) {
78.1263 + Parent::operator=(INVALID);
78.1264 + } else {
78.1265 + Parent::operator=(it->second);
78.1266 + }
78.1267 + }
78.1268 +
78.1269 + /// \brief Increment operator.
78.1270 + ///
78.1271 + /// Increment Operator.
78.1272 + ItemIt& operator++() {
78.1273 + Parent::operator=(_map->IterableValueMap::Parent::
78.1274 + operator[](static_cast<Parent&>(*this)).next);
78.1275 + return *this;
78.1276 + }
78.1277 +
78.1278 +
78.1279 + private:
78.1280 + const IterableValueMap* _map;
78.1281 + };
78.1282 +
78.1283 + protected:
78.1284 +
78.1285 + virtual void add(const Key& key) {
78.1286 + Parent::add(key);
78.1287 + lace(key);
78.1288 + }
78.1289 +
78.1290 + virtual void add(const std::vector<Key>& keys) {
78.1291 + Parent::add(keys);
78.1292 + for (int i = 0; i < int(keys.size()); ++i) {
78.1293 + lace(keys[i]);
78.1294 + }
78.1295 + }
78.1296 +
78.1297 + virtual void erase(const Key& key) {
78.1298 + unlace(key);
78.1299 + Parent::erase(key);
78.1300 + }
78.1301 +
78.1302 + virtual void erase(const std::vector<Key>& keys) {
78.1303 + for (int i = 0; i < int(keys.size()); ++i) {
78.1304 + unlace(keys[i]);
78.1305 + }
78.1306 + Parent::erase(keys);
78.1307 + }
78.1308 +
78.1309 + virtual void build() {
78.1310 + Parent::build();
78.1311 + for (typename Parent::ItemIt it(*this); it != INVALID; ++it) {
78.1312 + lace(it);
78.1313 + }
78.1314 + }
78.1315 +
78.1316 + virtual void clear() {
78.1317 + _first.clear();
78.1318 + Parent::clear();
78.1319 + }
78.1320 +
78.1321 + private:
78.1322 + std::map<Value, Key> _first;
78.1323 + };
78.1324 +
78.1325 /// \brief Map of the source nodes of arcs in a digraph.
78.1326 ///
78.1327 /// SourceMap provides access for the source node of each arc in a digraph,
78.1328 @@ -2340,9 +3300,9 @@
78.1329 class SourceMap {
78.1330 public:
78.1331
78.1332 - ///\e
78.1333 + /// The key type (the \c Arc type of the digraph).
78.1334 typedef typename GR::Arc Key;
78.1335 - ///\e
78.1336 + /// The value type (the \c Node type of the digraph).
78.1337 typedef typename GR::Node Value;
78.1338
78.1339 /// \brief Constructor
78.1340 @@ -2381,9 +3341,9 @@
78.1341 class TargetMap {
78.1342 public:
78.1343
78.1344 - ///\e
78.1345 + /// The key type (the \c Arc type of the digraph).
78.1346 typedef typename GR::Arc Key;
78.1347 - ///\e
78.1348 + /// The value type (the \c Node type of the digraph).
78.1349 typedef typename GR::Node Value;
78.1350
78.1351 /// \brief Constructor
78.1352 @@ -2423,8 +3383,10 @@
78.1353 class ForwardMap {
78.1354 public:
78.1355
78.1356 + /// The key type (the \c Edge type of the digraph).
78.1357 + typedef typename GR::Edge Key;
78.1358 + /// The value type (the \c Arc type of the digraph).
78.1359 typedef typename GR::Arc Value;
78.1360 - typedef typename GR::Edge Key;
78.1361
78.1362 /// \brief Constructor
78.1363 ///
78.1364 @@ -2463,8 +3425,10 @@
78.1365 class BackwardMap {
78.1366 public:
78.1367
78.1368 + /// The key type (the \c Edge type of the digraph).
78.1369 + typedef typename GR::Edge Key;
78.1370 + /// The value type (the \c Arc type of the digraph).
78.1371 typedef typename GR::Arc Value;
78.1372 - typedef typename GR::Edge Key;
78.1373
78.1374 /// \brief Constructor
78.1375 ///
78.1376 @@ -2499,10 +3463,10 @@
78.1377 /// in constant time. On the other hand, the values are updated automatically
78.1378 /// whenever the digraph changes.
78.1379 ///
78.1380 - /// \warning Besides \c addNode() and \c addArc(), a digraph structure
78.1381 + /// \warning Besides \c addNode() and \c addArc(), a digraph structure
78.1382 /// may provide alternative ways to modify the digraph.
78.1383 /// The correct behavior of InDegMap is not guarantied if these additional
78.1384 - /// features are used. For example the functions
78.1385 + /// features are used. For example, the functions
78.1386 /// \ref ListDigraph::changeSource() "changeSource()",
78.1387 /// \ref ListDigraph::changeTarget() "changeTarget()" and
78.1388 /// \ref ListDigraph::reverseArc() "reverseArc()"
78.1389 @@ -2515,7 +3479,7 @@
78.1390 ::ItemNotifier::ObserverBase {
78.1391
78.1392 public:
78.1393 -
78.1394 +
78.1395 /// The graph type of InDegMap
78.1396 typedef GR Graph;
78.1397 typedef GR Digraph;
78.1398 @@ -2629,10 +3593,10 @@
78.1399 /// in constant time. On the other hand, the values are updated automatically
78.1400 /// whenever the digraph changes.
78.1401 ///
78.1402 - /// \warning Besides \c addNode() and \c addArc(), a digraph structure
78.1403 + /// \warning Besides \c addNode() and \c addArc(), a digraph structure
78.1404 /// may provide alternative ways to modify the digraph.
78.1405 /// The correct behavior of OutDegMap is not guarantied if these additional
78.1406 - /// features are used. For example the functions
78.1407 + /// features are used. For example, the functions
78.1408 /// \ref ListDigraph::changeSource() "changeSource()",
78.1409 /// \ref ListDigraph::changeTarget() "changeTarget()" and
78.1410 /// \ref ListDigraph::reverseArc() "reverseArc()"
78.1411 @@ -2800,6 +3764,293 @@
78.1412 return PotentialDifferenceMap<GR, POT>(gr, potential);
78.1413 }
78.1414
78.1415 +
78.1416 + /// \brief Copy the values of a graph map to another map.
78.1417 + ///
78.1418 + /// This function copies the values of a graph map to another graph map.
78.1419 + /// \c To::Key must be equal or convertible to \c From::Key and
78.1420 + /// \c From::Value must be equal or convertible to \c To::Value.
78.1421 + ///
78.1422 + /// For example, an edge map of \c int value type can be copied to
78.1423 + /// an arc map of \c double value type in an undirected graph, but
78.1424 + /// an arc map cannot be copied to an edge map.
78.1425 + /// Note that even a \ref ConstMap can be copied to a standard graph map,
78.1426 + /// but \ref mapFill() can also be used for this purpose.
78.1427 + ///
78.1428 + /// \param gr The graph for which the maps are defined.
78.1429 + /// \param from The map from which the values have to be copied.
78.1430 + /// It must conform to the \ref concepts::ReadMap "ReadMap" concept.
78.1431 + /// \param to The map to which the values have to be copied.
78.1432 + /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
78.1433 + template <typename GR, typename From, typename To>
78.1434 + void mapCopy(const GR& gr, const From& from, To& to) {
78.1435 + typedef typename To::Key Item;
78.1436 + typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
78.1437 +
78.1438 + for (ItemIt it(gr); it != INVALID; ++it) {
78.1439 + to.set(it, from[it]);
78.1440 + }
78.1441 + }
78.1442 +
78.1443 + /// \brief Compare two graph maps.
78.1444 + ///
78.1445 + /// This function compares the values of two graph maps. It returns
78.1446 + /// \c true if the maps assign the same value for all items in the graph.
78.1447 + /// The \c Key type of the maps (\c Node, \c Arc or \c Edge) must be equal
78.1448 + /// and their \c Value types must be comparable using \c %operator==().
78.1449 + ///
78.1450 + /// \param gr The graph for which the maps are defined.
78.1451 + /// \param map1 The first map.
78.1452 + /// \param map2 The second map.
78.1453 + template <typename GR, typename Map1, typename Map2>
78.1454 + bool mapCompare(const GR& gr, const Map1& map1, const Map2& map2) {
78.1455 + typedef typename Map2::Key Item;
78.1456 + typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
78.1457 +
78.1458 + for (ItemIt it(gr); it != INVALID; ++it) {
78.1459 + if (!(map1[it] == map2[it])) return false;
78.1460 + }
78.1461 + return true;
78.1462 + }
78.1463 +
78.1464 + /// \brief Return an item having minimum value of a graph map.
78.1465 + ///
78.1466 + /// This function returns an item (\c Node, \c Arc or \c Edge) having
78.1467 + /// minimum value of the given graph map.
78.1468 + /// If the item set is empty, it returns \c INVALID.
78.1469 + ///
78.1470 + /// \param gr The graph for which the map is defined.
78.1471 + /// \param map The graph map.
78.1472 + template <typename GR, typename Map>
78.1473 + typename Map::Key mapMin(const GR& gr, const Map& map) {
78.1474 + return mapMin(gr, map, std::less<typename Map::Value>());
78.1475 + }
78.1476 +
78.1477 + /// \brief Return an item having minimum value of a graph map.
78.1478 + ///
78.1479 + /// This function returns an item (\c Node, \c Arc or \c Edge) having
78.1480 + /// minimum value of the given graph map.
78.1481 + /// If the item set is empty, it returns \c INVALID.
78.1482 + ///
78.1483 + /// \param gr The graph for which the map is defined.
78.1484 + /// \param map The graph map.
78.1485 + /// \param comp Comparison function object.
78.1486 + template <typename GR, typename Map, typename Comp>
78.1487 + typename Map::Key mapMin(const GR& gr, const Map& map, const Comp& comp) {
78.1488 + typedef typename Map::Key Item;
78.1489 + typedef typename Map::Value Value;
78.1490 + typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
78.1491 +
78.1492 + ItemIt min_item(gr);
78.1493 + if (min_item == INVALID) return INVALID;
78.1494 + Value min = map[min_item];
78.1495 + for (ItemIt it(gr); it != INVALID; ++it) {
78.1496 + if (comp(map[it], min)) {
78.1497 + min = map[it];
78.1498 + min_item = it;
78.1499 + }
78.1500 + }
78.1501 + return min_item;
78.1502 + }
78.1503 +
78.1504 + /// \brief Return an item having maximum value of a graph map.
78.1505 + ///
78.1506 + /// This function returns an item (\c Node, \c Arc or \c Edge) having
78.1507 + /// maximum value of the given graph map.
78.1508 + /// If the item set is empty, it returns \c INVALID.
78.1509 + ///
78.1510 + /// \param gr The graph for which the map is defined.
78.1511 + /// \param map The graph map.
78.1512 + template <typename GR, typename Map>
78.1513 + typename Map::Key mapMax(const GR& gr, const Map& map) {
78.1514 + return mapMax(gr, map, std::less<typename Map::Value>());
78.1515 + }
78.1516 +
78.1517 + /// \brief Return an item having maximum value of a graph map.
78.1518 + ///
78.1519 + /// This function returns an item (\c Node, \c Arc or \c Edge) having
78.1520 + /// maximum value of the given graph map.
78.1521 + /// If the item set is empty, it returns \c INVALID.
78.1522 + ///
78.1523 + /// \param gr The graph for which the map is defined.
78.1524 + /// \param map The graph map.
78.1525 + /// \param comp Comparison function object.
78.1526 + template <typename GR, typename Map, typename Comp>
78.1527 + typename Map::Key mapMax(const GR& gr, const Map& map, const Comp& comp) {
78.1528 + typedef typename Map::Key Item;
78.1529 + typedef typename Map::Value Value;
78.1530 + typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
78.1531 +
78.1532 + ItemIt max_item(gr);
78.1533 + if (max_item == INVALID) return INVALID;
78.1534 + Value max = map[max_item];
78.1535 + for (ItemIt it(gr); it != INVALID; ++it) {
78.1536 + if (comp(max, map[it])) {
78.1537 + max = map[it];
78.1538 + max_item = it;
78.1539 + }
78.1540 + }
78.1541 + return max_item;
78.1542 + }
78.1543 +
78.1544 + /// \brief Return the minimum value of a graph map.
78.1545 + ///
78.1546 + /// This function returns the minimum value of the given graph map.
78.1547 + /// The corresponding item set of the graph must not be empty.
78.1548 + ///
78.1549 + /// \param gr The graph for which the map is defined.
78.1550 + /// \param map The graph map.
78.1551 + template <typename GR, typename Map>
78.1552 + typename Map::Value mapMinValue(const GR& gr, const Map& map) {
78.1553 + return map[mapMin(gr, map, std::less<typename Map::Value>())];
78.1554 + }
78.1555 +
78.1556 + /// \brief Return the minimum value of a graph map.
78.1557 + ///
78.1558 + /// This function returns the minimum value of the given graph map.
78.1559 + /// The corresponding item set of the graph must not be empty.
78.1560 + ///
78.1561 + /// \param gr The graph for which the map is defined.
78.1562 + /// \param map The graph map.
78.1563 + /// \param comp Comparison function object.
78.1564 + template <typename GR, typename Map, typename Comp>
78.1565 + typename Map::Value
78.1566 + mapMinValue(const GR& gr, const Map& map, const Comp& comp) {
78.1567 + return map[mapMin(gr, map, comp)];
78.1568 + }
78.1569 +
78.1570 + /// \brief Return the maximum value of a graph map.
78.1571 + ///
78.1572 + /// This function returns the maximum value of the given graph map.
78.1573 + /// The corresponding item set of the graph must not be empty.
78.1574 + ///
78.1575 + /// \param gr The graph for which the map is defined.
78.1576 + /// \param map The graph map.
78.1577 + template <typename GR, typename Map>
78.1578 + typename Map::Value mapMaxValue(const GR& gr, const Map& map) {
78.1579 + return map[mapMax(gr, map, std::less<typename Map::Value>())];
78.1580 + }
78.1581 +
78.1582 + /// \brief Return the maximum value of a graph map.
78.1583 + ///
78.1584 + /// This function returns the maximum value of the given graph map.
78.1585 + /// The corresponding item set of the graph must not be empty.
78.1586 + ///
78.1587 + /// \param gr The graph for which the map is defined.
78.1588 + /// \param map The graph map.
78.1589 + /// \param comp Comparison function object.
78.1590 + template <typename GR, typename Map, typename Comp>
78.1591 + typename Map::Value
78.1592 + mapMaxValue(const GR& gr, const Map& map, const Comp& comp) {
78.1593 + return map[mapMax(gr, map, comp)];
78.1594 + }
78.1595 +
78.1596 + /// \brief Return an item having a specified value in a graph map.
78.1597 + ///
78.1598 + /// This function returns an item (\c Node, \c Arc or \c Edge) having
78.1599 + /// the specified assigned value in the given graph map.
78.1600 + /// If no such item exists, it returns \c INVALID.
78.1601 + ///
78.1602 + /// \param gr The graph for which the map is defined.
78.1603 + /// \param map The graph map.
78.1604 + /// \param val The value that have to be found.
78.1605 + template <typename GR, typename Map>
78.1606 + typename Map::Key
78.1607 + mapFind(const GR& gr, const Map& map, const typename Map::Value& val) {
78.1608 + typedef typename Map::Key Item;
78.1609 + typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
78.1610 +
78.1611 + for (ItemIt it(gr); it != INVALID; ++it) {
78.1612 + if (map[it] == val) return it;
78.1613 + }
78.1614 + return INVALID;
78.1615 + }
78.1616 +
78.1617 + /// \brief Return an item having value for which a certain predicate is
78.1618 + /// true in a graph map.
78.1619 + ///
78.1620 + /// This function returns an item (\c Node, \c Arc or \c Edge) having
78.1621 + /// such assigned value for which the specified predicate is true
78.1622 + /// in the given graph map.
78.1623 + /// If no such item exists, it returns \c INVALID.
78.1624 + ///
78.1625 + /// \param gr The graph for which the map is defined.
78.1626 + /// \param map The graph map.
78.1627 + /// \param pred The predicate function object.
78.1628 + template <typename GR, typename Map, typename Pred>
78.1629 + typename Map::Key
78.1630 + mapFindIf(const GR& gr, const Map& map, const Pred& pred) {
78.1631 + typedef typename Map::Key Item;
78.1632 + typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
78.1633 +
78.1634 + for (ItemIt it(gr); it != INVALID; ++it) {
78.1635 + if (pred(map[it])) return it;
78.1636 + }
78.1637 + return INVALID;
78.1638 + }
78.1639 +
78.1640 + /// \brief Return the number of items having a specified value in a
78.1641 + /// graph map.
78.1642 + ///
78.1643 + /// This function returns the number of items (\c Node, \c Arc or \c Edge)
78.1644 + /// having the specified assigned value in the given graph map.
78.1645 + ///
78.1646 + /// \param gr The graph for which the map is defined.
78.1647 + /// \param map The graph map.
78.1648 + /// \param val The value that have to be counted.
78.1649 + template <typename GR, typename Map>
78.1650 + int mapCount(const GR& gr, const Map& map, const typename Map::Value& val) {
78.1651 + typedef typename Map::Key Item;
78.1652 + typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
78.1653 +
78.1654 + int cnt = 0;
78.1655 + for (ItemIt it(gr); it != INVALID; ++it) {
78.1656 + if (map[it] == val) ++cnt;
78.1657 + }
78.1658 + return cnt;
78.1659 + }
78.1660 +
78.1661 + /// \brief Return the number of items having values for which a certain
78.1662 + /// predicate is true in a graph map.
78.1663 + ///
78.1664 + /// This function returns the number of items (\c Node, \c Arc or \c Edge)
78.1665 + /// having such assigned values for which the specified predicate is true
78.1666 + /// in the given graph map.
78.1667 + ///
78.1668 + /// \param gr The graph for which the map is defined.
78.1669 + /// \param map The graph map.
78.1670 + /// \param pred The predicate function object.
78.1671 + template <typename GR, typename Map, typename Pred>
78.1672 + int mapCountIf(const GR& gr, const Map& map, const Pred& pred) {
78.1673 + typedef typename Map::Key Item;
78.1674 + typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
78.1675 +
78.1676 + int cnt = 0;
78.1677 + for (ItemIt it(gr); it != INVALID; ++it) {
78.1678 + if (pred(map[it])) ++cnt;
78.1679 + }
78.1680 + return cnt;
78.1681 + }
78.1682 +
78.1683 + /// \brief Fill a graph map with a certain value.
78.1684 + ///
78.1685 + /// This function sets the specified value for all items (\c Node,
78.1686 + /// \c Arc or \c Edge) in the given graph map.
78.1687 + ///
78.1688 + /// \param gr The graph for which the map is defined.
78.1689 + /// \param map The graph map. It must conform to the
78.1690 + /// \ref concepts::WriteMap "WriteMap" concept.
78.1691 + /// \param val The value.
78.1692 + template <typename GR, typename Map>
78.1693 + void mapFill(const GR& gr, Map& map, const typename Map::Value& val) {
78.1694 + typedef typename Map::Key Item;
78.1695 + typedef typename ItemSetTraits<GR, Item>::ItemIt ItemIt;
78.1696 +
78.1697 + for (ItemIt it(gr); it != INVALID; ++it) {
78.1698 + map.set(it, val);
78.1699 + }
78.1700 + }
78.1701 +
78.1702 /// @}
78.1703 }
78.1704
79.1 --- a/lemon/matching.h Tue Dec 20 17:44:38 2011 +0100
79.2 +++ b/lemon/matching.h Tue Dec 20 18:15:14 2011 +0100
79.3 @@ -2,7 +2,7 @@
79.4 *
79.5 * This file is a part of LEMON, a generic C++ optimization library.
79.6 *
79.7 - * Copyright (C) 2003-2009
79.8 + * Copyright (C) 2003-2010
79.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
79.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
79.11 *
79.12 @@ -16,8 +16,8 @@
79.13 *
79.14 */
79.15
79.16 -#ifndef LEMON_MAX_MATCHING_H
79.17 -#define LEMON_MAX_MATCHING_H
79.18 +#ifndef LEMON_MATCHING_H
79.19 +#define LEMON_MATCHING_H
79.20
79.21 #include <vector>
79.22 #include <queue>
79.23 @@ -28,6 +28,7 @@
79.24 #include <lemon/unionfind.h>
79.25 #include <lemon/bin_heap.h>
79.26 #include <lemon/maps.h>
79.27 +#include <lemon/fractional_matching.h>
79.28
79.29 ///\ingroup matching
79.30 ///\file
79.31 @@ -41,7 +42,7 @@
79.32 ///
79.33 /// This class implements Edmonds' alternating forest matching algorithm
79.34 /// for finding a maximum cardinality matching in a general undirected graph.
79.35 - /// It can be started from an arbitrary initial matching
79.36 + /// It can be started from an arbitrary initial matching
79.37 /// (the default is the empty one).
79.38 ///
79.39 /// The dual solution of the problem is a map of the nodes to
79.40 @@ -69,11 +70,11 @@
79.41
79.42 ///\brief Status constants for Gallai-Edmonds decomposition.
79.43 ///
79.44 - ///These constants are used for indicating the Gallai-Edmonds
79.45 + ///These constants are used for indicating the Gallai-Edmonds
79.46 ///decomposition of a graph. The nodes with status \c EVEN (or \c D)
79.47 ///induce a subgraph with factor-critical components, the nodes with
79.48 ///status \c ODD (or \c A) form the canonical barrier, and the nodes
79.49 - ///with status \c MATCHED (or \c C) induce a subgraph having a
79.50 + ///with status \c MATCHED (or \c C) induce a subgraph having a
79.51 ///perfect matching.
79.52 enum Status {
79.53 EVEN = 1, ///< = 1. (\c D is an alias for \c EVEN.)
79.54 @@ -512,7 +513,7 @@
79.55 }
79.56 }
79.57
79.58 - /// \brief Start Edmonds' algorithm with a heuristic improvement
79.59 + /// \brief Start Edmonds' algorithm with a heuristic improvement
79.60 /// for dense graphs
79.61 ///
79.62 /// This function runs Edmonds' algorithm with a heuristic of postponing
79.63 @@ -534,8 +535,8 @@
79.64
79.65 /// \brief Run Edmonds' algorithm
79.66 ///
79.67 - /// This function runs Edmonds' algorithm. An additional heuristic of
79.68 - /// postponing shrinks is used for relatively dense graphs
79.69 + /// This function runs Edmonds' algorithm. An additional heuristic of
79.70 + /// postponing shrinks is used for relatively dense graphs
79.71 /// (for which <tt>m>=2*n</tt> holds).
79.72 void run() {
79.73 if (countEdges(_graph) < 2 * countNodes(_graph)) {
79.74 @@ -556,7 +557,7 @@
79.75
79.76 /// \brief Return the size (cardinality) of the matching.
79.77 ///
79.78 - /// This function returns the size (cardinality) of the current matching.
79.79 + /// This function returns the size (cardinality) of the current matching.
79.80 /// After run() it returns the size of the maximum matching in the graph.
79.81 int matchingSize() const {
79.82 int size = 0;
79.83 @@ -570,7 +571,7 @@
79.84
79.85 /// \brief Return \c true if the given edge is in the matching.
79.86 ///
79.87 - /// This function returns \c true if the given edge is in the current
79.88 + /// This function returns \c true if the given edge is in the current
79.89 /// matching.
79.90 bool matching(const Edge& edge) const {
79.91 return edge == (*_matching)[_graph.u(edge)];
79.92 @@ -579,7 +580,7 @@
79.93 /// \brief Return the matching arc (or edge) incident to the given node.
79.94 ///
79.95 /// This function returns the matching arc (or edge) incident to the
79.96 - /// given node in the current matching or \c INVALID if the node is
79.97 + /// given node in the current matching or \c INVALID if the node is
79.98 /// not covered by the matching.
79.99 Arc matching(const Node& n) const {
79.100 return (*_matching)[n];
79.101 @@ -595,7 +596,7 @@
79.102
79.103 /// \brief Return the mate of the given node.
79.104 ///
79.105 - /// This function returns the mate of the given node in the current
79.106 + /// This function returns the mate of the given node in the current
79.107 /// matching or \c INVALID if the node is not covered by the matching.
79.108 Node mate(const Node& n) const {
79.109 return (*_matching)[n] != INVALID ?
79.110 @@ -605,7 +606,7 @@
79.111 /// @}
79.112
79.113 /// \name Dual Solution
79.114 - /// Functions to get the dual solution, i.e. the Gallai-Edmonds
79.115 + /// Functions to get the dual solution, i.e. the Gallai-Edmonds
79.116 /// decomposition.
79.117
79.118 /// @{
79.119 @@ -648,8 +649,8 @@
79.120 /// on extensive use of priority queues and provides
79.121 /// \f$O(nm\log n)\f$ time complexity.
79.122 ///
79.123 - /// The maximum weighted matching problem is to find a subset of the
79.124 - /// edges in an undirected graph with maximum overall weight for which
79.125 + /// The maximum weighted matching problem is to find a subset of the
79.126 + /// edges in an undirected graph with maximum overall weight for which
79.127 /// each node has at most one incident edge.
79.128 /// It can be formulated with the following linear program.
79.129 /// \f[ \sum_{e \in \delta(u)}x_e \le 1 \quad \forall u\in V\f]
79.130 @@ -673,16 +674,16 @@
79.131 /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
79.132 \frac{\vert B \vert - 1}{2}z_B\f] */
79.133 ///
79.134 - /// The algorithm can be executed with the run() function.
79.135 + /// The algorithm can be executed with the run() function.
79.136 /// After it the matching (the primal solution) and the dual solution
79.137 - /// can be obtained using the query functions and the
79.138 - /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class,
79.139 - /// which is able to iterate on the nodes of a blossom.
79.140 + /// can be obtained using the query functions and the
79.141 + /// \ref MaxWeightedMatching::BlossomIt "BlossomIt" nested class,
79.142 + /// which is able to iterate on the nodes of a blossom.
79.143 /// If the value type is integer, then the dual solution is multiplied
79.144 /// by \ref MaxWeightedMatching::dualScale "4".
79.145 ///
79.146 /// \tparam GR The undirected graph type the algorithm runs on.
79.147 - /// \tparam WM The type edge weight map. The default type is
79.148 + /// \tparam WM The type edge weight map. The default type is
79.149 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
79.150 #ifdef DOXYGEN
79.151 template <typename GR, typename WM>
79.152 @@ -745,7 +746,7 @@
79.153 typedef RangeMap<int> IntIntMap;
79.154
79.155 enum Status {
79.156 - EVEN = -1, MATCHED = 0, ODD = 1, UNMATCHED = -2
79.157 + EVEN = -1, MATCHED = 0, ODD = 1
79.158 };
79.159
79.160 typedef HeapUnionFind<Value, IntNodeMap> BlossomSet;
79.161 @@ -797,6 +798,10 @@
79.162 BinHeap<Value, IntIntMap> *_delta4;
79.163
79.164 Value _delta_sum;
79.165 + int _unmatched;
79.166 +
79.167 + typedef MaxWeightedFractionalMatching<Graph, WeightMap> FractionalMatching;
79.168 + FractionalMatching *_fractional;
79.169
79.170 void createStructures() {
79.171 _node_num = countNodes(_graph);
79.172 @@ -863,9 +868,6 @@
79.173 }
79.174
79.175 void destroyStructures() {
79.176 - _node_num = countNodes(_graph);
79.177 - _blossom_num = _node_num * 3 / 2;
79.178 -
79.179 if (_matching) {
79.180 delete _matching;
79.181 }
79.182 @@ -941,10 +943,6 @@
79.183 if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
79.184 _delta3->push(e, rw / 2);
79.185 }
79.186 - } else if ((*_blossom_data)[vb].status == UNMATCHED) {
79.187 - if (_delta3->state(e) != _delta3->IN_HEAP) {
79.188 - _delta3->push(e, rw);
79.189 - }
79.190 } else {
79.191 typename std::map<int, Arc>::iterator it =
79.192 (*_node_data)[vi].heap_index.find(tree);
79.193 @@ -968,202 +966,6 @@
79.194 _delta2->push(vb, _blossom_set->classPrio(vb) -
79.195 (*_blossom_data)[vb].offset);
79.196 } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
79.197 - (*_blossom_data)[vb].offset){
79.198 - _delta2->decrease(vb, _blossom_set->classPrio(vb) -
79.199 - (*_blossom_data)[vb].offset);
79.200 - }
79.201 - }
79.202 - }
79.203 - }
79.204 - }
79.205 - }
79.206 - (*_blossom_data)[blossom].offset = 0;
79.207 - }
79.208 -
79.209 - void matchedToOdd(int blossom) {
79.210 - if (_delta2->state(blossom) == _delta2->IN_HEAP) {
79.211 - _delta2->erase(blossom);
79.212 - }
79.213 - (*_blossom_data)[blossom].offset += _delta_sum;
79.214 - if (!_blossom_set->trivial(blossom)) {
79.215 - _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
79.216 - (*_blossom_data)[blossom].offset);
79.217 - }
79.218 - }
79.219 -
79.220 - void evenToMatched(int blossom, int tree) {
79.221 - if (!_blossom_set->trivial(blossom)) {
79.222 - (*_blossom_data)[blossom].pot += 2 * _delta_sum;
79.223 - }
79.224 -
79.225 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
79.226 - n != INVALID; ++n) {
79.227 - int ni = (*_node_index)[n];
79.228 - (*_node_data)[ni].pot -= _delta_sum;
79.229 -
79.230 - _delta1->erase(n);
79.231 -
79.232 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
79.233 - Node v = _graph.source(e);
79.234 - int vb = _blossom_set->find(v);
79.235 - int vi = (*_node_index)[v];
79.236 -
79.237 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
79.238 - dualScale * _weight[e];
79.239 -
79.240 - if (vb == blossom) {
79.241 - if (_delta3->state(e) == _delta3->IN_HEAP) {
79.242 - _delta3->erase(e);
79.243 - }
79.244 - } else if ((*_blossom_data)[vb].status == EVEN) {
79.245 -
79.246 - if (_delta3->state(e) == _delta3->IN_HEAP) {
79.247 - _delta3->erase(e);
79.248 - }
79.249 -
79.250 - int vt = _tree_set->find(vb);
79.251 -
79.252 - if (vt != tree) {
79.253 -
79.254 - Arc r = _graph.oppositeArc(e);
79.255 -
79.256 - typename std::map<int, Arc>::iterator it =
79.257 - (*_node_data)[ni].heap_index.find(vt);
79.258 -
79.259 - if (it != (*_node_data)[ni].heap_index.end()) {
79.260 - if ((*_node_data)[ni].heap[it->second] > rw) {
79.261 - (*_node_data)[ni].heap.replace(it->second, r);
79.262 - (*_node_data)[ni].heap.decrease(r, rw);
79.263 - it->second = r;
79.264 - }
79.265 - } else {
79.266 - (*_node_data)[ni].heap.push(r, rw);
79.267 - (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
79.268 - }
79.269 -
79.270 - if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
79.271 - _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
79.272 -
79.273 - if (_delta2->state(blossom) != _delta2->IN_HEAP) {
79.274 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
79.275 - (*_blossom_data)[blossom].offset);
79.276 - } else if ((*_delta2)[blossom] >
79.277 - _blossom_set->classPrio(blossom) -
79.278 - (*_blossom_data)[blossom].offset){
79.279 - _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
79.280 - (*_blossom_data)[blossom].offset);
79.281 - }
79.282 - }
79.283 - }
79.284 -
79.285 - } else if ((*_blossom_data)[vb].status == UNMATCHED) {
79.286 - if (_delta3->state(e) == _delta3->IN_HEAP) {
79.287 - _delta3->erase(e);
79.288 - }
79.289 - } else {
79.290 -
79.291 - typename std::map<int, Arc>::iterator it =
79.292 - (*_node_data)[vi].heap_index.find(tree);
79.293 -
79.294 - if (it != (*_node_data)[vi].heap_index.end()) {
79.295 - (*_node_data)[vi].heap.erase(it->second);
79.296 - (*_node_data)[vi].heap_index.erase(it);
79.297 - if ((*_node_data)[vi].heap.empty()) {
79.298 - _blossom_set->increase(v, std::numeric_limits<Value>::max());
79.299 - } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
79.300 - _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
79.301 - }
79.302 -
79.303 - if ((*_blossom_data)[vb].status == MATCHED) {
79.304 - if (_blossom_set->classPrio(vb) ==
79.305 - std::numeric_limits<Value>::max()) {
79.306 - _delta2->erase(vb);
79.307 - } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
79.308 - (*_blossom_data)[vb].offset) {
79.309 - _delta2->increase(vb, _blossom_set->classPrio(vb) -
79.310 - (*_blossom_data)[vb].offset);
79.311 - }
79.312 - }
79.313 - }
79.314 - }
79.315 - }
79.316 - }
79.317 - }
79.318 -
79.319 - void oddToMatched(int blossom) {
79.320 - (*_blossom_data)[blossom].offset -= _delta_sum;
79.321 -
79.322 - if (_blossom_set->classPrio(blossom) !=
79.323 - std::numeric_limits<Value>::max()) {
79.324 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
79.325 - (*_blossom_data)[blossom].offset);
79.326 - }
79.327 -
79.328 - if (!_blossom_set->trivial(blossom)) {
79.329 - _delta4->erase(blossom);
79.330 - }
79.331 - }
79.332 -
79.333 - void oddToEven(int blossom, int tree) {
79.334 - if (!_blossom_set->trivial(blossom)) {
79.335 - _delta4->erase(blossom);
79.336 - (*_blossom_data)[blossom].pot -=
79.337 - 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
79.338 - }
79.339 -
79.340 - for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
79.341 - n != INVALID; ++n) {
79.342 - int ni = (*_node_index)[n];
79.343 -
79.344 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
79.345 -
79.346 - (*_node_data)[ni].heap.clear();
79.347 - (*_node_data)[ni].heap_index.clear();
79.348 - (*_node_data)[ni].pot +=
79.349 - 2 * _delta_sum - (*_blossom_data)[blossom].offset;
79.350 -
79.351 - _delta1->push(n, (*_node_data)[ni].pot);
79.352 -
79.353 - for (InArcIt e(_graph, n); e != INVALID; ++e) {
79.354 - Node v = _graph.source(e);
79.355 - int vb = _blossom_set->find(v);
79.356 - int vi = (*_node_index)[v];
79.357 -
79.358 - Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
79.359 - dualScale * _weight[e];
79.360 -
79.361 - if ((*_blossom_data)[vb].status == EVEN) {
79.362 - if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
79.363 - _delta3->push(e, rw / 2);
79.364 - }
79.365 - } else if ((*_blossom_data)[vb].status == UNMATCHED) {
79.366 - if (_delta3->state(e) != _delta3->IN_HEAP) {
79.367 - _delta3->push(e, rw);
79.368 - }
79.369 - } else {
79.370 -
79.371 - typename std::map<int, Arc>::iterator it =
79.372 - (*_node_data)[vi].heap_index.find(tree);
79.373 -
79.374 - if (it != (*_node_data)[vi].heap_index.end()) {
79.375 - if ((*_node_data)[vi].heap[it->second] > rw) {
79.376 - (*_node_data)[vi].heap.replace(it->second, e);
79.377 - (*_node_data)[vi].heap.decrease(e, rw);
79.378 - it->second = e;
79.379 - }
79.380 - } else {
79.381 - (*_node_data)[vi].heap.push(e, rw);
79.382 - (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
79.383 - }
79.384 -
79.385 - if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
79.386 - _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
79.387 -
79.388 - if ((*_blossom_data)[vb].status == MATCHED) {
79.389 - if (_delta2->state(vb) != _delta2->IN_HEAP) {
79.390 - _delta2->push(vb, _blossom_set->classPrio(vb) -
79.391 - (*_blossom_data)[vb].offset);
79.392 - } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
79.393 (*_blossom_data)[vb].offset) {
79.394 _delta2->decrease(vb, _blossom_set->classPrio(vb) -
79.395 (*_blossom_data)[vb].offset);
79.396 @@ -1176,43 +978,145 @@
79.397 (*_blossom_data)[blossom].offset = 0;
79.398 }
79.399
79.400 -
79.401 - void matchedToUnmatched(int blossom) {
79.402 + void matchedToOdd(int blossom) {
79.403 if (_delta2->state(blossom) == _delta2->IN_HEAP) {
79.404 _delta2->erase(blossom);
79.405 }
79.406 + (*_blossom_data)[blossom].offset += _delta_sum;
79.407 + if (!_blossom_set->trivial(blossom)) {
79.408 + _delta4->push(blossom, (*_blossom_data)[blossom].pot / 2 +
79.409 + (*_blossom_data)[blossom].offset);
79.410 + }
79.411 + }
79.412 +
79.413 + void evenToMatched(int blossom, int tree) {
79.414 + if (!_blossom_set->trivial(blossom)) {
79.415 + (*_blossom_data)[blossom].pot += 2 * _delta_sum;
79.416 + }
79.417
79.418 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
79.419 n != INVALID; ++n) {
79.420 int ni = (*_node_index)[n];
79.421 -
79.422 - _blossom_set->increase(n, std::numeric_limits<Value>::max());
79.423 -
79.424 - (*_node_data)[ni].heap.clear();
79.425 - (*_node_data)[ni].heap_index.clear();
79.426 -
79.427 - for (OutArcIt e(_graph, n); e != INVALID; ++e) {
79.428 - Node v = _graph.target(e);
79.429 + (*_node_data)[ni].pot -= _delta_sum;
79.430 +
79.431 + _delta1->erase(n);
79.432 +
79.433 + for (InArcIt e(_graph, n); e != INVALID; ++e) {
79.434 + Node v = _graph.source(e);
79.435 int vb = _blossom_set->find(v);
79.436 int vi = (*_node_index)[v];
79.437
79.438 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
79.439 dualScale * _weight[e];
79.440
79.441 - if ((*_blossom_data)[vb].status == EVEN) {
79.442 - if (_delta3->state(e) != _delta3->IN_HEAP) {
79.443 - _delta3->push(e, rw);
79.444 + if (vb == blossom) {
79.445 + if (_delta3->state(e) == _delta3->IN_HEAP) {
79.446 + _delta3->erase(e);
79.447 + }
79.448 + } else if ((*_blossom_data)[vb].status == EVEN) {
79.449 +
79.450 + if (_delta3->state(e) == _delta3->IN_HEAP) {
79.451 + _delta3->erase(e);
79.452 + }
79.453 +
79.454 + int vt = _tree_set->find(vb);
79.455 +
79.456 + if (vt != tree) {
79.457 +
79.458 + Arc r = _graph.oppositeArc(e);
79.459 +
79.460 + typename std::map<int, Arc>::iterator it =
79.461 + (*_node_data)[ni].heap_index.find(vt);
79.462 +
79.463 + if (it != (*_node_data)[ni].heap_index.end()) {
79.464 + if ((*_node_data)[ni].heap[it->second] > rw) {
79.465 + (*_node_data)[ni].heap.replace(it->second, r);
79.466 + (*_node_data)[ni].heap.decrease(r, rw);
79.467 + it->second = r;
79.468 + }
79.469 + } else {
79.470 + (*_node_data)[ni].heap.push(r, rw);
79.471 + (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
79.472 + }
79.473 +
79.474 + if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
79.475 + _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
79.476 +
79.477 + if (_delta2->state(blossom) != _delta2->IN_HEAP) {
79.478 + _delta2->push(blossom, _blossom_set->classPrio(blossom) -
79.479 + (*_blossom_data)[blossom].offset);
79.480 + } else if ((*_delta2)[blossom] >
79.481 + _blossom_set->classPrio(blossom) -
79.482 + (*_blossom_data)[blossom].offset){
79.483 + _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
79.484 + (*_blossom_data)[blossom].offset);
79.485 + }
79.486 + }
79.487 + }
79.488 + } else {
79.489 +
79.490 + typename std::map<int, Arc>::iterator it =
79.491 + (*_node_data)[vi].heap_index.find(tree);
79.492 +
79.493 + if (it != (*_node_data)[vi].heap_index.end()) {
79.494 + (*_node_data)[vi].heap.erase(it->second);
79.495 + (*_node_data)[vi].heap_index.erase(it);
79.496 + if ((*_node_data)[vi].heap.empty()) {
79.497 + _blossom_set->increase(v, std::numeric_limits<Value>::max());
79.498 + } else if ((*_blossom_set)[v] < (*_node_data)[vi].heap.prio()) {
79.499 + _blossom_set->increase(v, (*_node_data)[vi].heap.prio());
79.500 + }
79.501 +
79.502 + if ((*_blossom_data)[vb].status == MATCHED) {
79.503 + if (_blossom_set->classPrio(vb) ==
79.504 + std::numeric_limits<Value>::max()) {
79.505 + _delta2->erase(vb);
79.506 + } else if ((*_delta2)[vb] < _blossom_set->classPrio(vb) -
79.507 + (*_blossom_data)[vb].offset) {
79.508 + _delta2->increase(vb, _blossom_set->classPrio(vb) -
79.509 + (*_blossom_data)[vb].offset);
79.510 + }
79.511 + }
79.512 }
79.513 }
79.514 }
79.515 }
79.516 }
79.517
79.518 - void unmatchedToMatched(int blossom) {
79.519 + void oddToMatched(int blossom) {
79.520 + (*_blossom_data)[blossom].offset -= _delta_sum;
79.521 +
79.522 + if (_blossom_set->classPrio(blossom) !=
79.523 + std::numeric_limits<Value>::max()) {
79.524 + _delta2->push(blossom, _blossom_set->classPrio(blossom) -
79.525 + (*_blossom_data)[blossom].offset);
79.526 + }
79.527 +
79.528 + if (!_blossom_set->trivial(blossom)) {
79.529 + _delta4->erase(blossom);
79.530 + }
79.531 + }
79.532 +
79.533 + void oddToEven(int blossom, int tree) {
79.534 + if (!_blossom_set->trivial(blossom)) {
79.535 + _delta4->erase(blossom);
79.536 + (*_blossom_data)[blossom].pot -=
79.537 + 2 * (2 * _delta_sum - (*_blossom_data)[blossom].offset);
79.538 + }
79.539 +
79.540 for (typename BlossomSet::ItemIt n(*_blossom_set, blossom);
79.541 n != INVALID; ++n) {
79.542 int ni = (*_node_index)[n];
79.543
79.544 + _blossom_set->increase(n, std::numeric_limits<Value>::max());
79.545 +
79.546 + (*_node_data)[ni].heap.clear();
79.547 + (*_node_data)[ni].heap_index.clear();
79.548 + (*_node_data)[ni].pot +=
79.549 + 2 * _delta_sum - (*_blossom_data)[blossom].offset;
79.550 +
79.551 + _delta1->push(n, (*_node_data)[ni].pot);
79.552 +
79.553 for (InArcIt e(_graph, n); e != INVALID; ++e) {
79.554 Node v = _graph.source(e);
79.555 int vb = _blossom_set->find(v);
79.556 @@ -1221,54 +1125,44 @@
79.557 Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
79.558 dualScale * _weight[e];
79.559
79.560 - if (vb == blossom) {
79.561 - if (_delta3->state(e) == _delta3->IN_HEAP) {
79.562 - _delta3->erase(e);
79.563 + if ((*_blossom_data)[vb].status == EVEN) {
79.564 + if (_delta3->state(e) != _delta3->IN_HEAP && blossom != vb) {
79.565 + _delta3->push(e, rw / 2);
79.566 }
79.567 - } else if ((*_blossom_data)[vb].status == EVEN) {
79.568 -
79.569 - if (_delta3->state(e) == _delta3->IN_HEAP) {
79.570 - _delta3->erase(e);
79.571 - }
79.572 -
79.573 - int vt = _tree_set->find(vb);
79.574 -
79.575 - Arc r = _graph.oppositeArc(e);
79.576 + } else {
79.577
79.578 typename std::map<int, Arc>::iterator it =
79.579 - (*_node_data)[ni].heap_index.find(vt);
79.580 -
79.581 - if (it != (*_node_data)[ni].heap_index.end()) {
79.582 - if ((*_node_data)[ni].heap[it->second] > rw) {
79.583 - (*_node_data)[ni].heap.replace(it->second, r);
79.584 - (*_node_data)[ni].heap.decrease(r, rw);
79.585 - it->second = r;
79.586 + (*_node_data)[vi].heap_index.find(tree);
79.587 +
79.588 + if (it != (*_node_data)[vi].heap_index.end()) {
79.589 + if ((*_node_data)[vi].heap[it->second] > rw) {
79.590 + (*_node_data)[vi].heap.replace(it->second, e);
79.591 + (*_node_data)[vi].heap.decrease(e, rw);
79.592 + it->second = e;
79.593 }
79.594 } else {
79.595 - (*_node_data)[ni].heap.push(r, rw);
79.596 - (*_node_data)[ni].heap_index.insert(std::make_pair(vt, r));
79.597 + (*_node_data)[vi].heap.push(e, rw);
79.598 + (*_node_data)[vi].heap_index.insert(std::make_pair(tree, e));
79.599 }
79.600
79.601 - if ((*_blossom_set)[n] > (*_node_data)[ni].heap.prio()) {
79.602 - _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
79.603 -
79.604 - if (_delta2->state(blossom) != _delta2->IN_HEAP) {
79.605 - _delta2->push(blossom, _blossom_set->classPrio(blossom) -
79.606 - (*_blossom_data)[blossom].offset);
79.607 - } else if ((*_delta2)[blossom] > _blossom_set->classPrio(blossom)-
79.608 - (*_blossom_data)[blossom].offset){
79.609 - _delta2->decrease(blossom, _blossom_set->classPrio(blossom) -
79.610 - (*_blossom_data)[blossom].offset);
79.611 + if ((*_blossom_set)[v] > (*_node_data)[vi].heap.prio()) {
79.612 + _blossom_set->decrease(v, (*_node_data)[vi].heap.prio());
79.613 +
79.614 + if ((*_blossom_data)[vb].status == MATCHED) {
79.615 + if (_delta2->state(vb) != _delta2->IN_HEAP) {
79.616 + _delta2->push(vb, _blossom_set->classPrio(vb) -
79.617 + (*_blossom_data)[vb].offset);
79.618 + } else if ((*_delta2)[vb] > _blossom_set->classPrio(vb) -
79.619 + (*_blossom_data)[vb].offset) {
79.620 + _delta2->decrease(vb, _blossom_set->classPrio(vb) -
79.621 + (*_blossom_data)[vb].offset);
79.622 + }
79.623 }
79.624 }
79.625 -
79.626 - } else if ((*_blossom_data)[vb].status == UNMATCHED) {
79.627 - if (_delta3->state(e) == _delta3->IN_HEAP) {
79.628 - _delta3->erase(e);
79.629 - }
79.630 }
79.631 }
79.632 }
79.633 + (*_blossom_data)[blossom].offset = 0;
79.634 }
79.635
79.636 void alternatePath(int even, int tree) {
79.637 @@ -1313,39 +1207,42 @@
79.638 alternatePath(blossom, tree);
79.639 destroyTree(tree);
79.640
79.641 - (*_blossom_data)[blossom].status = UNMATCHED;
79.642 (*_blossom_data)[blossom].base = node;
79.643 - matchedToUnmatched(blossom);
79.644 + (*_blossom_data)[blossom].next = INVALID;
79.645 }
79.646
79.647 -
79.648 void augmentOnEdge(const Edge& edge) {
79.649
79.650 int left = _blossom_set->find(_graph.u(edge));
79.651 int right = _blossom_set->find(_graph.v(edge));
79.652
79.653 - if ((*_blossom_data)[left].status == EVEN) {
79.654 - int left_tree = _tree_set->find(left);
79.655 - alternatePath(left, left_tree);
79.656 - destroyTree(left_tree);
79.657 - } else {
79.658 - (*_blossom_data)[left].status = MATCHED;
79.659 - unmatchedToMatched(left);
79.660 - }
79.661 -
79.662 - if ((*_blossom_data)[right].status == EVEN) {
79.663 - int right_tree = _tree_set->find(right);
79.664 - alternatePath(right, right_tree);
79.665 - destroyTree(right_tree);
79.666 - } else {
79.667 - (*_blossom_data)[right].status = MATCHED;
79.668 - unmatchedToMatched(right);
79.669 - }
79.670 + int left_tree = _tree_set->find(left);
79.671 + alternatePath(left, left_tree);
79.672 + destroyTree(left_tree);
79.673 +
79.674 + int right_tree = _tree_set->find(right);
79.675 + alternatePath(right, right_tree);
79.676 + destroyTree(right_tree);
79.677
79.678 (*_blossom_data)[left].next = _graph.direct(edge, true);
79.679 (*_blossom_data)[right].next = _graph.direct(edge, false);
79.680 }
79.681
79.682 + void augmentOnArc(const Arc& arc) {
79.683 +
79.684 + int left = _blossom_set->find(_graph.source(arc));
79.685 + int right = _blossom_set->find(_graph.target(arc));
79.686 +
79.687 + (*_blossom_data)[left].status = MATCHED;
79.688 +
79.689 + int right_tree = _tree_set->find(right);
79.690 + alternatePath(right, right_tree);
79.691 + destroyTree(right_tree);
79.692 +
79.693 + (*_blossom_data)[left].next = arc;
79.694 + (*_blossom_data)[right].next = _graph.oppositeArc(arc);
79.695 + }
79.696 +
79.697 void extendOnArc(const Arc& arc) {
79.698 int base = _blossom_set->find(_graph.target(arc));
79.699 int tree = _tree_set->find(base);
79.700 @@ -1548,7 +1445,7 @@
79.701 _tree_set->insert(sb, tree);
79.702 (*_blossom_data)[sb].pred = pred;
79.703 (*_blossom_data)[sb].next =
79.704 - _graph.oppositeArc((*_blossom_data)[tb].next);
79.705 + _graph.oppositeArc((*_blossom_data)[tb].next);
79.706
79.707 pred = (*_blossom_data)[ub].next;
79.708
79.709 @@ -1648,7 +1545,7 @@
79.710 }
79.711
79.712 for (int i = 0; i < int(blossoms.size()); ++i) {
79.713 - if ((*_blossom_data)[blossoms[i]].status == MATCHED) {
79.714 + if ((*_blossom_data)[blossoms[i]].next != INVALID) {
79.715
79.716 Value offset = (*_blossom_data)[blossoms[i]].offset;
79.717 (*_blossom_data)[blossoms[i]].pot += 2 * offset;
79.718 @@ -1686,10 +1583,16 @@
79.719 _delta3_index(0), _delta3(0),
79.720 _delta4_index(0), _delta4(0),
79.721
79.722 - _delta_sum() {}
79.723 + _delta_sum(), _unmatched(0),
79.724 +
79.725 + _fractional(0)
79.726 + {}
79.727
79.728 ~MaxWeightedMatching() {
79.729 destroyStructures();
79.730 + if (_fractional) {
79.731 + delete _fractional;
79.732 + }
79.733 }
79.734
79.735 /// \name Execution Control
79.736 @@ -1720,7 +1623,9 @@
79.737 (*_delta2_index)[i] = _delta2->PRE_HEAP;
79.738 (*_delta4_index)[i] = _delta4->PRE_HEAP;
79.739 }
79.740 -
79.741 +
79.742 + _unmatched = _node_num;
79.743 +
79.744 _delta1->clear();
79.745 _delta2->clear();
79.746 _delta3->clear();
79.747 @@ -1764,18 +1669,167 @@
79.748 }
79.749 }
79.750
79.751 + /// \brief Initialize the algorithm with fractional matching
79.752 + ///
79.753 + /// This function initializes the algorithm with a fractional
79.754 + /// matching. This initialization is also called jumpstart heuristic.
79.755 + void fractionalInit() {
79.756 + createStructures();
79.757 +
79.758 + _blossom_node_list.clear();
79.759 + _blossom_potential.clear();
79.760 +
79.761 + if (_fractional == 0) {
79.762 + _fractional = new FractionalMatching(_graph, _weight, false);
79.763 + }
79.764 + _fractional->run();
79.765 +
79.766 + for (ArcIt e(_graph); e != INVALID; ++e) {
79.767 + (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
79.768 + }
79.769 + for (NodeIt n(_graph); n != INVALID; ++n) {
79.770 + (*_delta1_index)[n] = _delta1->PRE_HEAP;
79.771 + }
79.772 + for (EdgeIt e(_graph); e != INVALID; ++e) {
79.773 + (*_delta3_index)[e] = _delta3->PRE_HEAP;
79.774 + }
79.775 + for (int i = 0; i < _blossom_num; ++i) {
79.776 + (*_delta2_index)[i] = _delta2->PRE_HEAP;
79.777 + (*_delta4_index)[i] = _delta4->PRE_HEAP;
79.778 + }
79.779 +
79.780 + _unmatched = 0;
79.781 +
79.782 + _delta1->clear();
79.783 + _delta2->clear();
79.784 + _delta3->clear();
79.785 + _delta4->clear();
79.786 + _blossom_set->clear();
79.787 + _tree_set->clear();
79.788 +
79.789 + int index = 0;
79.790 + for (NodeIt n(_graph); n != INVALID; ++n) {
79.791 + Value pot = _fractional->nodeValue(n);
79.792 + (*_node_index)[n] = index;
79.793 + (*_node_data)[index].pot = pot;
79.794 + (*_node_data)[index].heap_index.clear();
79.795 + (*_node_data)[index].heap.clear();
79.796 + int blossom =
79.797 + _blossom_set->insert(n, std::numeric_limits<Value>::max());
79.798 +
79.799 + (*_blossom_data)[blossom].status = MATCHED;
79.800 + (*_blossom_data)[blossom].pred = INVALID;
79.801 + (*_blossom_data)[blossom].next = _fractional->matching(n);
79.802 + if (_fractional->matching(n) == INVALID) {
79.803 + (*_blossom_data)[blossom].base = n;
79.804 + }
79.805 + (*_blossom_data)[blossom].pot = 0;
79.806 + (*_blossom_data)[blossom].offset = 0;
79.807 + ++index;
79.808 + }
79.809 +
79.810 + typename Graph::template NodeMap<bool> processed(_graph, false);
79.811 + for (NodeIt n(_graph); n != INVALID; ++n) {
79.812 + if (processed[n]) continue;
79.813 + processed[n] = true;
79.814 + if (_fractional->matching(n) == INVALID) continue;
79.815 + int num = 1;
79.816 + Node v = _graph.target(_fractional->matching(n));
79.817 + while (n != v) {
79.818 + processed[v] = true;
79.819 + v = _graph.target(_fractional->matching(v));
79.820 + ++num;
79.821 + }
79.822 +
79.823 + if (num % 2 == 1) {
79.824 + std::vector<int> subblossoms(num);
79.825 +
79.826 + subblossoms[--num] = _blossom_set->find(n);
79.827 + _delta1->push(n, _fractional->nodeValue(n));
79.828 + v = _graph.target(_fractional->matching(n));
79.829 + while (n != v) {
79.830 + subblossoms[--num] = _blossom_set->find(v);
79.831 + _delta1->push(v, _fractional->nodeValue(v));
79.832 + v = _graph.target(_fractional->matching(v));
79.833 + }
79.834 +
79.835 + int surface =
79.836 + _blossom_set->join(subblossoms.begin(), subblossoms.end());
79.837 + (*_blossom_data)[surface].status = EVEN;
79.838 + (*_blossom_data)[surface].pred = INVALID;
79.839 + (*_blossom_data)[surface].next = INVALID;
79.840 + (*_blossom_data)[surface].pot = 0;
79.841 + (*_blossom_data)[surface].offset = 0;
79.842 +
79.843 + _tree_set->insert(surface);
79.844 + ++_unmatched;
79.845 + }
79.846 + }
79.847 +
79.848 + for (EdgeIt e(_graph); e != INVALID; ++e) {
79.849 + int si = (*_node_index)[_graph.u(e)];
79.850 + int sb = _blossom_set->find(_graph.u(e));
79.851 + int ti = (*_node_index)[_graph.v(e)];
79.852 + int tb = _blossom_set->find(_graph.v(e));
79.853 + if ((*_blossom_data)[sb].status == EVEN &&
79.854 + (*_blossom_data)[tb].status == EVEN && sb != tb) {
79.855 + _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
79.856 + dualScale * _weight[e]) / 2);
79.857 + }
79.858 + }
79.859 +
79.860 + for (NodeIt n(_graph); n != INVALID; ++n) {
79.861 + int nb = _blossom_set->find(n);
79.862 + if ((*_blossom_data)[nb].status != MATCHED) continue;
79.863 + int ni = (*_node_index)[n];
79.864 +
79.865 + for (OutArcIt e(_graph, n); e != INVALID; ++e) {
79.866 + Node v = _graph.target(e);
79.867 + int vb = _blossom_set->find(v);
79.868 + int vi = (*_node_index)[v];
79.869 +
79.870 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
79.871 + dualScale * _weight[e];
79.872 +
79.873 + if ((*_blossom_data)[vb].status == EVEN) {
79.874 +
79.875 + int vt = _tree_set->find(vb);
79.876 +
79.877 + typename std::map<int, Arc>::iterator it =
79.878 + (*_node_data)[ni].heap_index.find(vt);
79.879 +
79.880 + if (it != (*_node_data)[ni].heap_index.end()) {
79.881 + if ((*_node_data)[ni].heap[it->second] > rw) {
79.882 + (*_node_data)[ni].heap.replace(it->second, e);
79.883 + (*_node_data)[ni].heap.decrease(e, rw);
79.884 + it->second = e;
79.885 + }
79.886 + } else {
79.887 + (*_node_data)[ni].heap.push(e, rw);
79.888 + (*_node_data)[ni].heap_index.insert(std::make_pair(vt, e));
79.889 + }
79.890 + }
79.891 + }
79.892 +
79.893 + if (!(*_node_data)[ni].heap.empty()) {
79.894 + _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
79.895 + _delta2->push(nb, _blossom_set->classPrio(nb));
79.896 + }
79.897 + }
79.898 + }
79.899 +
79.900 /// \brief Start the algorithm
79.901 ///
79.902 /// This function starts the algorithm.
79.903 ///
79.904 - /// \pre \ref init() must be called before using this function.
79.905 + /// \pre \ref init() or \ref fractionalInit() must be called
79.906 + /// before using this function.
79.907 void start() {
79.908 enum OpType {
79.909 D1, D2, D3, D4
79.910 };
79.911
79.912 - int unmatched = _node_num;
79.913 - while (unmatched > 0) {
79.914 + while (_unmatched > 0) {
79.915 Value d1 = !_delta1->empty() ?
79.916 _delta1->prio() : std::numeric_limits<Value>::max();
79.917
79.918 @@ -1788,26 +1842,30 @@
79.919 Value d4 = !_delta4->empty() ?
79.920 _delta4->prio() : std::numeric_limits<Value>::max();
79.921
79.922 - _delta_sum = d1; OpType ot = D1;
79.923 + _delta_sum = d3; OpType ot = D3;
79.924 + if (d1 < _delta_sum) { _delta_sum = d1; ot = D1; }
79.925 if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
79.926 - if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
79.927 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
79.928
79.929 -
79.930 switch (ot) {
79.931 case D1:
79.932 {
79.933 Node n = _delta1->top();
79.934 unmatchNode(n);
79.935 - --unmatched;
79.936 + --_unmatched;
79.937 }
79.938 break;
79.939 case D2:
79.940 {
79.941 int blossom = _delta2->top();
79.942 Node n = _blossom_set->classTop(blossom);
79.943 - Arc e = (*_node_data)[(*_node_index)[n]].heap.top();
79.944 - extendOnArc(e);
79.945 + Arc a = (*_node_data)[(*_node_index)[n]].heap.top();
79.946 + if ((*_blossom_data)[blossom].next == INVALID) {
79.947 + augmentOnArc(a);
79.948 + --_unmatched;
79.949 + } else {
79.950 + extendOnArc(a);
79.951 + }
79.952 }
79.953 break;
79.954 case D3:
79.955 @@ -1820,26 +1878,14 @@
79.956 if (left_blossom == right_blossom) {
79.957 _delta3->pop();
79.958 } else {
79.959 - int left_tree;
79.960 - if ((*_blossom_data)[left_blossom].status == EVEN) {
79.961 - left_tree = _tree_set->find(left_blossom);
79.962 - } else {
79.963 - left_tree = -1;
79.964 - ++unmatched;
79.965 - }
79.966 - int right_tree;
79.967 - if ((*_blossom_data)[right_blossom].status == EVEN) {
79.968 - right_tree = _tree_set->find(right_blossom);
79.969 - } else {
79.970 - right_tree = -1;
79.971 - ++unmatched;
79.972 - }
79.973 + int left_tree = _tree_set->find(left_blossom);
79.974 + int right_tree = _tree_set->find(right_blossom);
79.975
79.976 if (left_tree == right_tree) {
79.977 shrinkOnEdge(e, left_tree);
79.978 } else {
79.979 augmentOnEdge(e);
79.980 - unmatched -= 2;
79.981 + _unmatched -= 2;
79.982 }
79.983 }
79.984 } break;
79.985 @@ -1857,18 +1903,18 @@
79.986 ///
79.987 /// \note mwm.run() is just a shortcut of the following code.
79.988 /// \code
79.989 - /// mwm.init();
79.990 + /// mwm.fractionalInit();
79.991 /// mwm.start();
79.992 /// \endcode
79.993 void run() {
79.994 - init();
79.995 + fractionalInit();
79.996 start();
79.997 }
79.998
79.999 /// @}
79.1000
79.1001 /// \name Primal Solution
79.1002 - /// Functions to get the primal solution, i.e. the maximum weighted
79.1003 + /// Functions to get the primal solution, i.e. the maximum weighted
79.1004 /// matching.\n
79.1005 /// Either \ref run() or \ref start() function should be called before
79.1006 /// using them.
79.1007 @@ -1887,7 +1933,7 @@
79.1008 sum += _weight[(*_matching)[n]];
79.1009 }
79.1010 }
79.1011 - return sum /= 2;
79.1012 + return sum / 2;
79.1013 }
79.1014
79.1015 /// \brief Return the size (cardinality) of the matching.
79.1016 @@ -1907,7 +1953,7 @@
79.1017
79.1018 /// \brief Return \c true if the given edge is in the matching.
79.1019 ///
79.1020 - /// This function returns \c true if the given edge is in the found
79.1021 + /// This function returns \c true if the given edge is in the found
79.1022 /// matching.
79.1023 ///
79.1024 /// \pre Either run() or start() must be called before using this function.
79.1025 @@ -1918,7 +1964,7 @@
79.1026 /// \brief Return the matching arc (or edge) incident to the given node.
79.1027 ///
79.1028 /// This function returns the matching arc (or edge) incident to the
79.1029 - /// given node in the found matching or \c INVALID if the node is
79.1030 + /// given node in the found matching or \c INVALID if the node is
79.1031 /// not covered by the matching.
79.1032 ///
79.1033 /// \pre Either run() or start() must be called before using this function.
79.1034 @@ -1936,7 +1982,7 @@
79.1035
79.1036 /// \brief Return the mate of the given node.
79.1037 ///
79.1038 - /// This function returns the mate of the given node in the found
79.1039 + /// This function returns the mate of the given node in the found
79.1040 /// matching or \c INVALID if the node is not covered by the matching.
79.1041 ///
79.1042 /// \pre Either run() or start() must be called before using this function.
79.1043 @@ -1956,8 +2002,8 @@
79.1044
79.1045 /// \brief Return the value of the dual solution.
79.1046 ///
79.1047 - /// This function returns the value of the dual solution.
79.1048 - /// It should be equal to the primal value scaled by \ref dualScale
79.1049 + /// This function returns the value of the dual solution.
79.1050 + /// It should be equal to the primal value scaled by \ref dualScale
79.1051 /// "dual scale".
79.1052 ///
79.1053 /// \pre Either run() or start() must be called before using this function.
79.1054 @@ -2012,9 +2058,9 @@
79.1055
79.1056 /// \brief Iterator for obtaining the nodes of a blossom.
79.1057 ///
79.1058 - /// This class provides an iterator for obtaining the nodes of the
79.1059 + /// This class provides an iterator for obtaining the nodes of the
79.1060 /// given blossom. It lists a subset of the nodes.
79.1061 - /// Before using this iterator, you must allocate a
79.1062 + /// Before using this iterator, you must allocate a
79.1063 /// MaxWeightedMatching class and execute it.
79.1064 class BlossomIt {
79.1065 public:
79.1066 @@ -2023,8 +2069,8 @@
79.1067 ///
79.1068 /// Constructor to get the nodes of the given variable.
79.1069 ///
79.1070 - /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or
79.1071 - /// \ref MaxWeightedMatching::start() "algorithm.start()" must be
79.1072 + /// \pre Either \ref MaxWeightedMatching::run() "algorithm.run()" or
79.1073 + /// \ref MaxWeightedMatching::start() "algorithm.start()" must be
79.1074 /// called before initializing this iterator.
79.1075 BlossomIt(const MaxWeightedMatching& algorithm, int variable)
79.1076 : _algorithm(&algorithm)
79.1077 @@ -2077,8 +2123,8 @@
79.1078 /// is based on extensive use of priority queues and provides
79.1079 /// \f$O(nm\log n)\f$ time complexity.
79.1080 ///
79.1081 - /// The maximum weighted perfect matching problem is to find a subset of
79.1082 - /// the edges in an undirected graph with maximum overall weight for which
79.1083 + /// The maximum weighted perfect matching problem is to find a subset of
79.1084 + /// the edges in an undirected graph with maximum overall weight for which
79.1085 /// each node has exactly one incident edge.
79.1086 /// It can be formulated with the following linear program.
79.1087 /// \f[ \sum_{e \in \delta(u)}x_e = 1 \quad \forall u\in V\f]
79.1088 @@ -2101,16 +2147,16 @@
79.1089 /** \f[\min \sum_{u \in V}y_u + \sum_{B \in \mathcal{O}}
79.1090 \frac{\vert B \vert - 1}{2}z_B\f] */
79.1091 ///
79.1092 - /// The algorithm can be executed with the run() function.
79.1093 + /// The algorithm can be executed with the run() function.
79.1094 /// After it the matching (the primal solution) and the dual solution
79.1095 - /// can be obtained using the query functions and the
79.1096 - /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class,
79.1097 - /// which is able to iterate on the nodes of a blossom.
79.1098 + /// can be obtained using the query functions and the
79.1099 + /// \ref MaxWeightedPerfectMatching::BlossomIt "BlossomIt" nested class,
79.1100 + /// which is able to iterate on the nodes of a blossom.
79.1101 /// If the value type is integer, then the dual solution is multiplied
79.1102 /// by \ref MaxWeightedMatching::dualScale "4".
79.1103 ///
79.1104 /// \tparam GR The undirected graph type the algorithm runs on.
79.1105 - /// \tparam WM The type edge weight map. The default type is
79.1106 + /// \tparam WM The type edge weight map. The default type is
79.1107 /// \ref concepts::Graph::EdgeMap "GR::EdgeMap<int>".
79.1108 #ifdef DOXYGEN
79.1109 template <typename GR, typename WM>
79.1110 @@ -2221,6 +2267,11 @@
79.1111 BinHeap<Value, IntIntMap> *_delta4;
79.1112
79.1113 Value _delta_sum;
79.1114 + int _unmatched;
79.1115 +
79.1116 + typedef MaxWeightedPerfectFractionalMatching<Graph, WeightMap>
79.1117 + FractionalMatching;
79.1118 + FractionalMatching *_fractional;
79.1119
79.1120 void createStructures() {
79.1121 _node_num = countNodes(_graph);
79.1122 @@ -2282,9 +2333,6 @@
79.1123 }
79.1124
79.1125 void destroyStructures() {
79.1126 - _node_num = countNodes(_graph);
79.1127 - _blossom_num = _node_num * 3 / 2;
79.1128 -
79.1129 if (_matching) {
79.1130 delete _matching;
79.1131 }
79.1132 @@ -2957,10 +3005,16 @@
79.1133 _delta3_index(0), _delta3(0),
79.1134 _delta4_index(0), _delta4(0),
79.1135
79.1136 - _delta_sum() {}
79.1137 + _delta_sum(), _unmatched(0),
79.1138 +
79.1139 + _fractional(0)
79.1140 + {}
79.1141
79.1142 ~MaxWeightedPerfectMatching() {
79.1143 destroyStructures();
79.1144 + if (_fractional) {
79.1145 + delete _fractional;
79.1146 + }
79.1147 }
79.1148
79.1149 /// \name Execution Control
79.1150 @@ -2989,6 +3043,8 @@
79.1151 (*_delta4_index)[i] = _delta4->PRE_HEAP;
79.1152 }
79.1153
79.1154 + _unmatched = _node_num;
79.1155 +
79.1156 _delta2->clear();
79.1157 _delta3->clear();
79.1158 _delta4->clear();
79.1159 @@ -3030,18 +3086,163 @@
79.1160 }
79.1161 }
79.1162
79.1163 + /// \brief Initialize the algorithm with fractional matching
79.1164 + ///
79.1165 + /// This function initializes the algorithm with a fractional
79.1166 + /// matching. This initialization is also called jumpstart heuristic.
79.1167 + void fractionalInit() {
79.1168 + createStructures();
79.1169 +
79.1170 + _blossom_node_list.clear();
79.1171 + _blossom_potential.clear();
79.1172 +
79.1173 + if (_fractional == 0) {
79.1174 + _fractional = new FractionalMatching(_graph, _weight, false);
79.1175 + }
79.1176 + if (!_fractional->run()) {
79.1177 + _unmatched = -1;
79.1178 + return;
79.1179 + }
79.1180 +
79.1181 + for (ArcIt e(_graph); e != INVALID; ++e) {
79.1182 + (*_node_heap_index)[e] = BinHeap<Value, IntArcMap>::PRE_HEAP;
79.1183 + }
79.1184 + for (EdgeIt e(_graph); e != INVALID; ++e) {
79.1185 + (*_delta3_index)[e] = _delta3->PRE_HEAP;
79.1186 + }
79.1187 + for (int i = 0; i < _blossom_num; ++i) {
79.1188 + (*_delta2_index)[i] = _delta2->PRE_HEAP;
79.1189 + (*_delta4_index)[i] = _delta4->PRE_HEAP;
79.1190 + }
79.1191 +
79.1192 + _unmatched = 0;
79.1193 +
79.1194 + _delta2->clear();
79.1195 + _delta3->clear();
79.1196 + _delta4->clear();
79.1197 + _blossom_set->clear();
79.1198 + _tree_set->clear();
79.1199 +
79.1200 + int index = 0;
79.1201 + for (NodeIt n(_graph); n != INVALID; ++n) {
79.1202 + Value pot = _fractional->nodeValue(n);
79.1203 + (*_node_index)[n] = index;
79.1204 + (*_node_data)[index].pot = pot;
79.1205 + (*_node_data)[index].heap_index.clear();
79.1206 + (*_node_data)[index].heap.clear();
79.1207 + int blossom =
79.1208 + _blossom_set->insert(n, std::numeric_limits<Value>::max());
79.1209 +
79.1210 + (*_blossom_data)[blossom].status = MATCHED;
79.1211 + (*_blossom_data)[blossom].pred = INVALID;
79.1212 + (*_blossom_data)[blossom].next = _fractional->matching(n);
79.1213 + (*_blossom_data)[blossom].pot = 0;
79.1214 + (*_blossom_data)[blossom].offset = 0;
79.1215 + ++index;
79.1216 + }
79.1217 +
79.1218 + typename Graph::template NodeMap<bool> processed(_graph, false);
79.1219 + for (NodeIt n(_graph); n != INVALID; ++n) {
79.1220 + if (processed[n]) continue;
79.1221 + processed[n] = true;
79.1222 + if (_fractional->matching(n) == INVALID) continue;
79.1223 + int num = 1;
79.1224 + Node v = _graph.target(_fractional->matching(n));
79.1225 + while (n != v) {
79.1226 + processed[v] = true;
79.1227 + v = _graph.target(_fractional->matching(v));
79.1228 + ++num;
79.1229 + }
79.1230 +
79.1231 + if (num % 2 == 1) {
79.1232 + std::vector<int> subblossoms(num);
79.1233 +
79.1234 + subblossoms[--num] = _blossom_set->find(n);
79.1235 + v = _graph.target(_fractional->matching(n));
79.1236 + while (n != v) {
79.1237 + subblossoms[--num] = _blossom_set->find(v);
79.1238 + v = _graph.target(_fractional->matching(v));
79.1239 + }
79.1240 +
79.1241 + int surface =
79.1242 + _blossom_set->join(subblossoms.begin(), subblossoms.end());
79.1243 + (*_blossom_data)[surface].status = EVEN;
79.1244 + (*_blossom_data)[surface].pred = INVALID;
79.1245 + (*_blossom_data)[surface].next = INVALID;
79.1246 + (*_blossom_data)[surface].pot = 0;
79.1247 + (*_blossom_data)[surface].offset = 0;
79.1248 +
79.1249 + _tree_set->insert(surface);
79.1250 + ++_unmatched;
79.1251 + }
79.1252 + }
79.1253 +
79.1254 + for (EdgeIt e(_graph); e != INVALID; ++e) {
79.1255 + int si = (*_node_index)[_graph.u(e)];
79.1256 + int sb = _blossom_set->find(_graph.u(e));
79.1257 + int ti = (*_node_index)[_graph.v(e)];
79.1258 + int tb = _blossom_set->find(_graph.v(e));
79.1259 + if ((*_blossom_data)[sb].status == EVEN &&
79.1260 + (*_blossom_data)[tb].status == EVEN && sb != tb) {
79.1261 + _delta3->push(e, ((*_node_data)[si].pot + (*_node_data)[ti].pot -
79.1262 + dualScale * _weight[e]) / 2);
79.1263 + }
79.1264 + }
79.1265 +
79.1266 + for (NodeIt n(_graph); n != INVALID; ++n) {
79.1267 + int nb = _blossom_set->find(n);
79.1268 + if ((*_blossom_data)[nb].status != MATCHED) continue;
79.1269 + int ni = (*_node_index)[n];
79.1270 +
79.1271 + for (OutArcIt e(_graph, n); e != INVALID; ++e) {
79.1272 + Node v = _graph.target(e);
79.1273 + int vb = _blossom_set->find(v);
79.1274 + int vi = (*_node_index)[v];
79.1275 +
79.1276 + Value rw = (*_node_data)[ni].pot + (*_node_data)[vi].pot -
79.1277 + dualScale * _weight[e];
79.1278 +
79.1279 + if ((*_blossom_data)[vb].status == EVEN) {
79.1280 +
79.1281 + int vt = _tree_set->find(vb);
79.1282 +
79.1283 + typename std::map<int, Arc>::iterator it =
79.1284 + (*_node_data)[ni].heap_index.find(vt);
79.1285 +
79.1286 + if (it != (*_node_data)[ni].heap_index.end()) {
79.1287 + if ((*_node_data)[ni].heap[it->second] > rw) {
79.1288 + (*_node_data)[ni].heap.replace(it->second, e);
79.1289 + (*_node_data)[ni].heap.decrease(e, rw);
79.1290 + it->second = e;
79.1291 + }
79.1292 + } else {
79.1293 + (*_node_data)[ni].heap.push(e, rw);
79.1294 + (*_node_data)[ni].heap_index.insert(std::make_pair(vt, e));
79.1295 + }
79.1296 + }
79.1297 + }
79.1298 +
79.1299 + if (!(*_node_data)[ni].heap.empty()) {
79.1300 + _blossom_set->decrease(n, (*_node_data)[ni].heap.prio());
79.1301 + _delta2->push(nb, _blossom_set->classPrio(nb));
79.1302 + }
79.1303 + }
79.1304 + }
79.1305 +
79.1306 /// \brief Start the algorithm
79.1307 ///
79.1308 /// This function starts the algorithm.
79.1309 ///
79.1310 - /// \pre \ref init() must be called before using this function.
79.1311 + /// \pre \ref init() or \ref fractionalInit() must be called before
79.1312 + /// using this function.
79.1313 bool start() {
79.1314 enum OpType {
79.1315 D2, D3, D4
79.1316 };
79.1317
79.1318 - int unmatched = _node_num;
79.1319 - while (unmatched > 0) {
79.1320 + if (_unmatched == -1) return false;
79.1321 +
79.1322 + while (_unmatched > 0) {
79.1323 Value d2 = !_delta2->empty() ?
79.1324 _delta2->prio() : std::numeric_limits<Value>::max();
79.1325
79.1326 @@ -3051,8 +3252,8 @@
79.1327 Value d4 = !_delta4->empty() ?
79.1328 _delta4->prio() : std::numeric_limits<Value>::max();
79.1329
79.1330 - _delta_sum = d2; OpType ot = D2;
79.1331 - if (d3 < _delta_sum) { _delta_sum = d3; ot = D3; }
79.1332 + _delta_sum = d3; OpType ot = D3;
79.1333 + if (d2 < _delta_sum) { _delta_sum = d2; ot = D2; }
79.1334 if (d4 < _delta_sum) { _delta_sum = d4; ot = D4; }
79.1335
79.1336 if (_delta_sum == std::numeric_limits<Value>::max()) {
79.1337 @@ -3085,7 +3286,7 @@
79.1338 shrinkOnEdge(e, left_tree);
79.1339 } else {
79.1340 augmentOnEdge(e);
79.1341 - unmatched -= 2;
79.1342 + _unmatched -= 2;
79.1343 }
79.1344 }
79.1345 } break;
79.1346 @@ -3104,18 +3305,18 @@
79.1347 ///
79.1348 /// \note mwpm.run() is just a shortcut of the following code.
79.1349 /// \code
79.1350 - /// mwpm.init();
79.1351 + /// mwpm.fractionalInit();
79.1352 /// mwpm.start();
79.1353 /// \endcode
79.1354 bool run() {
79.1355 - init();
79.1356 + fractionalInit();
79.1357 return start();
79.1358 }
79.1359
79.1360 /// @}
79.1361
79.1362 /// \name Primal Solution
79.1363 - /// Functions to get the primal solution, i.e. the maximum weighted
79.1364 + /// Functions to get the primal solution, i.e. the maximum weighted
79.1365 /// perfect matching.\n
79.1366 /// Either \ref run() or \ref start() function should be called before
79.1367 /// using them.
79.1368 @@ -3134,12 +3335,12 @@
79.1369 sum += _weight[(*_matching)[n]];
79.1370 }
79.1371 }
79.1372 - return sum /= 2;
79.1373 + return sum / 2;
79.1374 }
79.1375
79.1376 /// \brief Return \c true if the given edge is in the matching.
79.1377 ///
79.1378 - /// This function returns \c true if the given edge is in the found
79.1379 + /// This function returns \c true if the given edge is in the found
79.1380 /// matching.
79.1381 ///
79.1382 /// \pre Either run() or start() must be called before using this function.
79.1383 @@ -3150,7 +3351,7 @@
79.1384 /// \brief Return the matching arc (or edge) incident to the given node.
79.1385 ///
79.1386 /// This function returns the matching arc (or edge) incident to the
79.1387 - /// given node in the found matching or \c INVALID if the node is
79.1388 + /// given node in the found matching or \c INVALID if the node is
79.1389 /// not covered by the matching.
79.1390 ///
79.1391 /// \pre Either run() or start() must be called before using this function.
79.1392 @@ -3168,7 +3369,7 @@
79.1393
79.1394 /// \brief Return the mate of the given node.
79.1395 ///
79.1396 - /// This function returns the mate of the given node in the found
79.1397 + /// This function returns the mate of the given node in the found
79.1398 /// matching or \c INVALID if the node is not covered by the matching.
79.1399 ///
79.1400 /// \pre Either run() or start() must be called before using this function.
79.1401 @@ -3187,8 +3388,8 @@
79.1402
79.1403 /// \brief Return the value of the dual solution.
79.1404 ///
79.1405 - /// This function returns the value of the dual solution.
79.1406 - /// It should be equal to the primal value scaled by \ref dualScale
79.1407 + /// This function returns the value of the dual solution.
79.1408 + /// It should be equal to the primal value scaled by \ref dualScale
79.1409 /// "dual scale".
79.1410 ///
79.1411 /// \pre Either run() or start() must be called before using this function.
79.1412 @@ -3243,9 +3444,9 @@
79.1413
79.1414 /// \brief Iterator for obtaining the nodes of a blossom.
79.1415 ///
79.1416 - /// This class provides an iterator for obtaining the nodes of the
79.1417 + /// This class provides an iterator for obtaining the nodes of the
79.1418 /// given blossom. It lists a subset of the nodes.
79.1419 - /// Before using this iterator, you must allocate a
79.1420 + /// Before using this iterator, you must allocate a
79.1421 /// MaxWeightedPerfectMatching class and execute it.
79.1422 class BlossomIt {
79.1423 public:
79.1424 @@ -3254,8 +3455,8 @@
79.1425 ///
79.1426 /// Constructor to get the nodes of the given variable.
79.1427 ///
79.1428 - /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()"
79.1429 - /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()"
79.1430 + /// \pre Either \ref MaxWeightedPerfectMatching::run() "algorithm.run()"
79.1431 + /// or \ref MaxWeightedPerfectMatching::start() "algorithm.start()"
79.1432 /// must be called before initializing this iterator.
79.1433 BlossomIt(const MaxWeightedPerfectMatching& algorithm, int variable)
79.1434 : _algorithm(&algorithm)
79.1435 @@ -3301,4 +3502,4 @@
79.1436
79.1437 } //END OF NAMESPACE LEMON
79.1438
79.1439 -#endif //LEMON_MAX_MATCHING_H
79.1440 +#endif //LEMON_MATCHING_H
80.1 --- a/lemon/math.h Tue Dec 20 17:44:38 2011 +0100
80.2 +++ b/lemon/math.h Tue Dec 20 18:15:14 2011 +0100
80.3 @@ -2,7 +2,7 @@
80.4 *
80.5 * This file is a part of LEMON, a generic C++ optimization library.
80.6 *
80.7 - * Copyright (C) 2003-2009
80.8 + * Copyright (C) 2003-2010
80.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
80.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
80.11 *
80.12 @@ -56,7 +56,7 @@
80.13 const long double SQRT1_2 = 0.7071067811865475244008443621048490L;
80.14
80.15 ///Check whether the parameter is NaN or not
80.16 -
80.17 +
80.18 ///This function checks whether the parameter is NaN or not.
80.19 ///Is should be equivalent with std::isnan(), but it is not
80.20 ///provided by all compilers.
81.1 --- a/lemon/min_cost_arborescence.h Tue Dec 20 17:44:38 2011 +0100
81.2 +++ b/lemon/min_cost_arborescence.h Tue Dec 20 18:15:14 2011 +0100
81.3 @@ -2,7 +2,7 @@
81.4 *
81.5 * This file is a part of LEMON, a generic C++ optimization library.
81.6 *
81.7 - * Copyright (C) 2003-2008
81.8 + * Copyright (C) 2003-2010
81.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
81.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
81.11 *
81.12 @@ -112,23 +112,24 @@
81.13 /// relatively time consuming process to compute the arc costs if
81.14 /// it is necessary. The default map type is \ref
81.15 /// concepts::Digraph::ArcMap "Digraph::ArcMap<int>".
81.16 - /// \param TR Traits class to set various data types used
81.17 - /// by the algorithm. The default traits class is
81.18 - /// \ref MinCostArborescenceDefaultTraits
81.19 + /// \tparam TR The traits class that defines various types used by the
81.20 + /// algorithm. By default, it is \ref MinCostArborescenceDefaultTraits
81.21 /// "MinCostArborescenceDefaultTraits<GR, CM>".
81.22 + /// In most cases, this parameter should not be set directly,
81.23 + /// consider to use the named template parameters instead.
81.24 #ifndef DOXYGEN
81.25 template <typename GR,
81.26 typename CM = typename GR::template ArcMap<int>,
81.27 typename TR =
81.28 MinCostArborescenceDefaultTraits<GR, CM> >
81.29 #else
81.30 - template <typename GR, typename CM, typedef TR>
81.31 + template <typename GR, typename CM, typename TR>
81.32 #endif
81.33 class MinCostArborescence {
81.34 public:
81.35
81.36 - /// \brief The \ref MinCostArborescenceDefaultTraits "traits class"
81.37 - /// of the algorithm.
81.38 + /// \brief The \ref MinCostArborescenceDefaultTraits "traits class"
81.39 + /// of the algorithm.
81.40 typedef TR Traits;
81.41 /// The type of the underlying digraph.
81.42 typedef typename Traits::Digraph Digraph;
81.43 @@ -435,7 +436,7 @@
81.44 ///
81.45 /// \ref named-templ-param "Named parameter" for setting
81.46 /// \c PredMap type.
81.47 - /// It must meet the \ref concepts::WriteMap "WriteMap" concept,
81.48 + /// It must meet the \ref concepts::WriteMap "WriteMap" concept,
81.49 /// and its value type must be the \c Arc type of the digraph.
81.50 template <class T>
81.51 struct SetPredMap
81.52 @@ -488,8 +489,8 @@
81.53 /// \name Execution Control
81.54 /// The simplest way to execute the algorithm is to use
81.55 /// one of the member functions called \c run(...). \n
81.56 - /// If you need more control on the execution,
81.57 - /// first you must call \ref init(), then you can add several
81.58 + /// If you need better control on the execution,
81.59 + /// you have to call \ref init() first, then you can add several
81.60 /// source nodes with \ref addSource().
81.61 /// Finally \ref start() will perform the arborescence
81.62 /// computation.
82.1 --- a/lemon/network_simplex.h Tue Dec 20 17:44:38 2011 +0100
82.2 +++ b/lemon/network_simplex.h Tue Dec 20 18:15:14 2011 +0100
82.3 @@ -2,7 +2,7 @@
82.4 *
82.5 * This file is a part of LEMON, a generic C++ optimization library.
82.6 *
82.7 - * Copyright (C) 2003-2009
82.8 + * Copyright (C) 2003-2010
82.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
82.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
82.11 *
82.12 @@ -40,15 +40,17 @@
82.13 /// for finding a \ref min_cost_flow "minimum cost flow".
82.14 ///
82.15 /// \ref NetworkSimplex implements the primal Network Simplex algorithm
82.16 - /// for finding a \ref min_cost_flow "minimum cost flow".
82.17 - /// This algorithm is a specialized version of the linear programming
82.18 - /// simplex method directly for the minimum cost flow problem.
82.19 - /// It is one of the most efficient solution methods.
82.20 + /// for finding a \ref min_cost_flow "minimum cost flow"
82.21 + /// \ref amo93networkflows, \ref dantzig63linearprog,
82.22 + /// \ref kellyoneill91netsimplex.
82.23 + /// This algorithm is a highly efficient specialized version of the
82.24 + /// linear programming simplex method directly for the minimum cost
82.25 + /// flow problem.
82.26 ///
82.27 - /// In general this class is the fastest implementation available
82.28 - /// in LEMON for the minimum cost flow problem.
82.29 - /// Moreover it supports both directions of the supply/demand inequality
82.30 - /// constraints. For more information see \ref SupplyType.
82.31 + /// In general, %NetworkSimplex is the fastest implementation available
82.32 + /// in LEMON for this problem.
82.33 + /// Moreover, it supports both directions of the supply/demand inequality
82.34 + /// constraints. For more information, see \ref SupplyType.
82.35 ///
82.36 /// Most of the parameters of the problem (except for the digraph)
82.37 /// can be given using separate functions, and the algorithm can be
82.38 @@ -56,17 +58,17 @@
82.39 /// specified, then default values will be used.
82.40 ///
82.41 /// \tparam GR The digraph type the algorithm runs on.
82.42 - /// \tparam V The value type used for flow amounts, capacity bounds
82.43 - /// and supply values in the algorithm. By default it is \c int.
82.44 - /// \tparam C The value type used for costs and potentials in the
82.45 - /// algorithm. By default it is the same as \c V.
82.46 + /// \tparam V The number type used for flow amounts, capacity bounds
82.47 + /// and supply values in the algorithm. By default, it is \c int.
82.48 + /// \tparam C The number type used for costs and potentials in the
82.49 + /// algorithm. By default, it is the same as \c V.
82.50 ///
82.51 - /// \warning Both value types must be signed and all input data must
82.52 + /// \warning Both number types must be signed and all input data must
82.53 /// be integer.
82.54 ///
82.55 /// \note %NetworkSimplex provides five different pivot rule
82.56 /// implementations, from which the most efficient one is used
82.57 - /// by default. For more information see \ref PivotRule.
82.58 + /// by default. For more information, see \ref PivotRule.
82.59 template <typename GR, typename V = int, typename C = V>
82.60 class NetworkSimplex
82.61 {
82.62 @@ -95,7 +97,7 @@
82.63 /// infinite upper bound.
82.64 UNBOUNDED
82.65 };
82.66 -
82.67 +
82.68 /// \brief Constants for selecting the type of the supply constraints.
82.69 ///
82.70 /// Enum type containing constants for selecting the supply type,
82.71 @@ -113,7 +115,7 @@
82.72 /// supply/demand constraints in the definition of the problem.
82.73 LEQ
82.74 };
82.75 -
82.76 +
82.77 /// \brief Constants for selecting the pivot rule.
82.78 ///
82.79 /// Enum type containing constants for selecting the pivot rule for
82.80 @@ -122,59 +124,62 @@
82.81 /// \ref NetworkSimplex provides five different pivot rule
82.82 /// implementations that significantly affect the running time
82.83 /// of the algorithm.
82.84 - /// By default \ref BLOCK_SEARCH "Block Search" is used, which
82.85 + /// By default, \ref BLOCK_SEARCH "Block Search" is used, which
82.86 /// proved to be the most efficient and the most robust on various
82.87 - /// test inputs according to our benchmark tests.
82.88 - /// However another pivot rule can be selected using the \ref run()
82.89 + /// test inputs.
82.90 + /// However, another pivot rule can be selected using the \ref run()
82.91 /// function with the proper parameter.
82.92 enum PivotRule {
82.93
82.94 - /// The First Eligible pivot rule.
82.95 + /// The \e First \e Eligible pivot rule.
82.96 /// The next eligible arc is selected in a wraparound fashion
82.97 /// in every iteration.
82.98 FIRST_ELIGIBLE,
82.99
82.100 - /// The Best Eligible pivot rule.
82.101 + /// The \e Best \e Eligible pivot rule.
82.102 /// The best eligible arc is selected in every iteration.
82.103 BEST_ELIGIBLE,
82.104
82.105 - /// The Block Search pivot rule.
82.106 + /// The \e Block \e Search pivot rule.
82.107 /// A specified number of arcs are examined in every iteration
82.108 /// in a wraparound fashion and the best eligible arc is selected
82.109 /// from this block.
82.110 BLOCK_SEARCH,
82.111
82.112 - /// The Candidate List pivot rule.
82.113 + /// The \e Candidate \e List pivot rule.
82.114 /// In a major iteration a candidate list is built from eligible arcs
82.115 /// in a wraparound fashion and in the following minor iterations
82.116 /// the best eligible arc is selected from this list.
82.117 CANDIDATE_LIST,
82.118
82.119 - /// The Altering Candidate List pivot rule.
82.120 + /// The \e Altering \e Candidate \e List pivot rule.
82.121 /// It is a modified version of the Candidate List method.
82.122 /// It keeps only the several best eligible arcs from the former
82.123 /// candidate list and extends this list in every iteration.
82.124 ALTERING_LIST
82.125 };
82.126 -
82.127 +
82.128 private:
82.129
82.130 TEMPLATE_DIGRAPH_TYPEDEFS(GR);
82.131
82.132 - typedef std::vector<Arc> ArcVector;
82.133 - typedef std::vector<Node> NodeVector;
82.134 typedef std::vector<int> IntVector;
82.135 - typedef std::vector<bool> BoolVector;
82.136 typedef std::vector<Value> ValueVector;
82.137 typedef std::vector<Cost> CostVector;
82.138 + typedef std::vector<char> BoolVector;
82.139 + // Note: vector<char> is used instead of vector<bool> for efficiency reasons
82.140
82.141 // State constants for arcs
82.142 - enum ArcStateEnum {
82.143 + enum ArcState {
82.144 STATE_UPPER = -1,
82.145 STATE_TREE = 0,
82.146 STATE_LOWER = 1
82.147 };
82.148
82.149 + typedef std::vector<signed char> StateVector;
82.150 + // Note: vector<signed char> is used instead of vector<ArcState> for
82.151 + // efficiency reasons
82.152 +
82.153 private:
82.154
82.155 // Data related to the underlying digraph
82.156 @@ -194,6 +199,7 @@
82.157 IntArcMap _arc_id;
82.158 IntVector _source;
82.159 IntVector _target;
82.160 + bool _arc_mixing;
82.161
82.162 // Node and arc data
82.163 ValueVector _lower;
82.164 @@ -213,7 +219,7 @@
82.165 IntVector _last_succ;
82.166 IntVector _dirty_revs;
82.167 BoolVector _forward;
82.168 - IntVector _state;
82.169 + StateVector _state;
82.170 int _root;
82.171
82.172 // Temporary data used in the current pivot iteration
82.173 @@ -222,8 +228,10 @@
82.174 int stem, par_stem, new_stem;
82.175 Value delta;
82.176
82.177 + const Value MAX;
82.178 +
82.179 public:
82.180 -
82.181 +
82.182 /// \brief Constant for infinite upper bounds (capacities).
82.183 ///
82.184 /// Constant for infinite upper bounds (capacities).
82.185 @@ -242,7 +250,7 @@
82.186 const IntVector &_source;
82.187 const IntVector &_target;
82.188 const CostVector &_cost;
82.189 - const IntVector &_state;
82.190 + const StateVector &_state;
82.191 const CostVector &_pi;
82.192 int &_in_arc;
82.193 int _search_arc_num;
82.194 @@ -263,7 +271,7 @@
82.195 // Find next entering arc
82.196 bool findEnteringArc() {
82.197 Cost c;
82.198 - for (int e = _next_arc; e < _search_arc_num; ++e) {
82.199 + for (int e = _next_arc; e != _search_arc_num; ++e) {
82.200 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
82.201 if (c < 0) {
82.202 _in_arc = e;
82.203 @@ -271,7 +279,7 @@
82.204 return true;
82.205 }
82.206 }
82.207 - for (int e = 0; e < _next_arc; ++e) {
82.208 + for (int e = 0; e != _next_arc; ++e) {
82.209 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
82.210 if (c < 0) {
82.211 _in_arc = e;
82.212 @@ -294,7 +302,7 @@
82.213 const IntVector &_source;
82.214 const IntVector &_target;
82.215 const CostVector &_cost;
82.216 - const IntVector &_state;
82.217 + const StateVector &_state;
82.218 const CostVector &_pi;
82.219 int &_in_arc;
82.220 int _search_arc_num;
82.221 @@ -311,7 +319,7 @@
82.222 // Find next entering arc
82.223 bool findEnteringArc() {
82.224 Cost c, min = 0;
82.225 - for (int e = 0; e < _search_arc_num; ++e) {
82.226 + for (int e = 0; e != _search_arc_num; ++e) {
82.227 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
82.228 if (c < min) {
82.229 min = c;
82.230 @@ -333,7 +341,7 @@
82.231 const IntVector &_source;
82.232 const IntVector &_target;
82.233 const CostVector &_cost;
82.234 - const IntVector &_state;
82.235 + const StateVector &_state;
82.236 const CostVector &_pi;
82.237 int &_in_arc;
82.238 int _search_arc_num;
82.239 @@ -352,7 +360,7 @@
82.240 _next_arc(0)
82.241 {
82.242 // The main parameters of the pivot rule
82.243 - const double BLOCK_SIZE_FACTOR = 0.5;
82.244 + const double BLOCK_SIZE_FACTOR = 1.0;
82.245 const int MIN_BLOCK_SIZE = 10;
82.246
82.247 _block_size = std::max( int(BLOCK_SIZE_FACTOR *
82.248 @@ -364,33 +372,32 @@
82.249 bool findEnteringArc() {
82.250 Cost c, min = 0;
82.251 int cnt = _block_size;
82.252 - int e, min_arc = _next_arc;
82.253 - for (e = _next_arc; e < _search_arc_num; ++e) {
82.254 + int e;
82.255 + for (e = _next_arc; e != _search_arc_num; ++e) {
82.256 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
82.257 if (c < min) {
82.258 min = c;
82.259 - min_arc = e;
82.260 + _in_arc = e;
82.261 }
82.262 if (--cnt == 0) {
82.263 - if (min < 0) break;
82.264 + if (min < 0) goto search_end;
82.265 cnt = _block_size;
82.266 }
82.267 }
82.268 - if (min == 0 || cnt > 0) {
82.269 - for (e = 0; e < _next_arc; ++e) {
82.270 - c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
82.271 - if (c < min) {
82.272 - min = c;
82.273 - min_arc = e;
82.274 - }
82.275 - if (--cnt == 0) {
82.276 - if (min < 0) break;
82.277 - cnt = _block_size;
82.278 - }
82.279 + for (e = 0; e != _next_arc; ++e) {
82.280 + c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
82.281 + if (c < min) {
82.282 + min = c;
82.283 + _in_arc = e;
82.284 + }
82.285 + if (--cnt == 0) {
82.286 + if (min < 0) goto search_end;
82.287 + cnt = _block_size;
82.288 }
82.289 }
82.290 if (min >= 0) return false;
82.291 - _in_arc = min_arc;
82.292 +
82.293 + search_end:
82.294 _next_arc = e;
82.295 return true;
82.296 }
82.297 @@ -407,7 +414,7 @@
82.298 const IntVector &_source;
82.299 const IntVector &_target;
82.300 const CostVector &_cost;
82.301 - const IntVector &_state;
82.302 + const StateVector &_state;
82.303 const CostVector &_pi;
82.304 int &_in_arc;
82.305 int _search_arc_num;
82.306 @@ -428,7 +435,7 @@
82.307 _next_arc(0)
82.308 {
82.309 // The main parameters of the pivot rule
82.310 - const double LIST_LENGTH_FACTOR = 1.0;
82.311 + const double LIST_LENGTH_FACTOR = 0.25;
82.312 const int MIN_LIST_LENGTH = 10;
82.313 const double MINOR_LIMIT_FACTOR = 0.1;
82.314 const int MIN_MINOR_LIMIT = 3;
82.315 @@ -445,7 +452,7 @@
82.316 /// Find next entering arc
82.317 bool findEnteringArc() {
82.318 Cost min, c;
82.319 - int e, min_arc = _next_arc;
82.320 + int e;
82.321 if (_curr_length > 0 && _minor_count < _minor_limit) {
82.322 // Minor iteration: select the best eligible arc from the
82.323 // current candidate list
82.324 @@ -456,48 +463,44 @@
82.325 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
82.326 if (c < min) {
82.327 min = c;
82.328 - min_arc = e;
82.329 + _in_arc = e;
82.330 }
82.331 - if (c >= 0) {
82.332 + else if (c >= 0) {
82.333 _candidates[i--] = _candidates[--_curr_length];
82.334 }
82.335 }
82.336 - if (min < 0) {
82.337 - _in_arc = min_arc;
82.338 - return true;
82.339 - }
82.340 + if (min < 0) return true;
82.341 }
82.342
82.343 // Major iteration: build a new candidate list
82.344 min = 0;
82.345 _curr_length = 0;
82.346 - for (e = _next_arc; e < _search_arc_num; ++e) {
82.347 + for (e = _next_arc; e != _search_arc_num; ++e) {
82.348 c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
82.349 if (c < 0) {
82.350 _candidates[_curr_length++] = e;
82.351 if (c < min) {
82.352 min = c;
82.353 - min_arc = e;
82.354 + _in_arc = e;
82.355 }
82.356 - if (_curr_length == _list_length) break;
82.357 + if (_curr_length == _list_length) goto search_end;
82.358 }
82.359 }
82.360 - if (_curr_length < _list_length) {
82.361 - for (e = 0; e < _next_arc; ++e) {
82.362 - c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
82.363 - if (c < 0) {
82.364 - _candidates[_curr_length++] = e;
82.365 - if (c < min) {
82.366 - min = c;
82.367 - min_arc = e;
82.368 - }
82.369 - if (_curr_length == _list_length) break;
82.370 + for (e = 0; e != _next_arc; ++e) {
82.371 + c = _state[e] * (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
82.372 + if (c < 0) {
82.373 + _candidates[_curr_length++] = e;
82.374 + if (c < min) {
82.375 + min = c;
82.376 + _in_arc = e;
82.377 }
82.378 + if (_curr_length == _list_length) goto search_end;
82.379 }
82.380 }
82.381 if (_curr_length == 0) return false;
82.382 +
82.383 + search_end:
82.384 _minor_count = 1;
82.385 - _in_arc = min_arc;
82.386 _next_arc = e;
82.387 return true;
82.388 }
82.389 @@ -514,7 +517,7 @@
82.390 const IntVector &_source;
82.391 const IntVector &_target;
82.392 const CostVector &_cost;
82.393 - const IntVector &_state;
82.394 + const StateVector &_state;
82.395 const CostVector &_pi;
82.396 int &_in_arc;
82.397 int _search_arc_num;
82.398 @@ -549,7 +552,7 @@
82.399 _next_arc(0), _cand_cost(ns._search_arc_num), _sort_func(_cand_cost)
82.400 {
82.401 // The main parameters of the pivot rule
82.402 - const double BLOCK_SIZE_FACTOR = 1.5;
82.403 + const double BLOCK_SIZE_FACTOR = 1.0;
82.404 const int MIN_BLOCK_SIZE = 10;
82.405 const double HEAD_LENGTH_FACTOR = 0.1;
82.406 const int MIN_HEAD_LENGTH = 3;
82.407 @@ -567,7 +570,7 @@
82.408 bool findEnteringArc() {
82.409 // Check the current candidate list
82.410 int e;
82.411 - for (int i = 0; i < _curr_length; ++i) {
82.412 + for (int i = 0; i != _curr_length; ++i) {
82.413 e = _candidates[i];
82.414 _cand_cost[e] = _state[e] *
82.415 (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
82.416 @@ -578,39 +581,35 @@
82.417
82.418 // Extend the list
82.419 int cnt = _block_size;
82.420 - int last_arc = 0;
82.421 int limit = _head_length;
82.422
82.423 - for (int e = _next_arc; e < _search_arc_num; ++e) {
82.424 + for (e = _next_arc; e != _search_arc_num; ++e) {
82.425 _cand_cost[e] = _state[e] *
82.426 (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
82.427 if (_cand_cost[e] < 0) {
82.428 _candidates[_curr_length++] = e;
82.429 - last_arc = e;
82.430 }
82.431 if (--cnt == 0) {
82.432 - if (_curr_length > limit) break;
82.433 + if (_curr_length > limit) goto search_end;
82.434 limit = 0;
82.435 cnt = _block_size;
82.436 }
82.437 }
82.438 - if (_curr_length <= limit) {
82.439 - for (int e = 0; e < _next_arc; ++e) {
82.440 - _cand_cost[e] = _state[e] *
82.441 - (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
82.442 - if (_cand_cost[e] < 0) {
82.443 - _candidates[_curr_length++] = e;
82.444 - last_arc = e;
82.445 - }
82.446 - if (--cnt == 0) {
82.447 - if (_curr_length > limit) break;
82.448 - limit = 0;
82.449 - cnt = _block_size;
82.450 - }
82.451 + for (e = 0; e != _next_arc; ++e) {
82.452 + _cand_cost[e] = _state[e] *
82.453 + (_cost[e] + _pi[_source[e]] - _pi[_target[e]]);
82.454 + if (_cand_cost[e] < 0) {
82.455 + _candidates[_curr_length++] = e;
82.456 + }
82.457 + if (--cnt == 0) {
82.458 + if (_curr_length > limit) goto search_end;
82.459 + limit = 0;
82.460 + cnt = _block_size;
82.461 }
82.462 }
82.463 if (_curr_length == 0) return false;
82.464 - _next_arc = last_arc + 1;
82.465 +
82.466 + search_end:
82.467
82.468 // Make heap of the candidate list (approximating a partial sort)
82.469 make_heap( _candidates.begin(), _candidates.begin() + _curr_length,
82.470 @@ -618,6 +617,7 @@
82.471
82.472 // Pop the first element of the heap
82.473 _in_arc = _candidates[0];
82.474 + _next_arc = e;
82.475 pop_heap( _candidates.begin(), _candidates.begin() + _curr_length,
82.476 _sort_func );
82.477 _curr_length = std::min(_head_length, _curr_length - 1);
82.478 @@ -633,69 +633,25 @@
82.479 /// The constructor of the class.
82.480 ///
82.481 /// \param graph The digraph the algorithm runs on.
82.482 - NetworkSimplex(const GR& graph) :
82.483 + /// \param arc_mixing Indicate if the arcs have to be stored in a
82.484 + /// mixed order in the internal data structure.
82.485 + /// In special cases, it could lead to better overall performance,
82.486 + /// but it is usually slower. Therefore it is disabled by default.
82.487 + NetworkSimplex(const GR& graph, bool arc_mixing = false) :
82.488 _graph(graph), _node_id(graph), _arc_id(graph),
82.489 + _arc_mixing(arc_mixing),
82.490 + MAX(std::numeric_limits<Value>::max()),
82.491 INF(std::numeric_limits<Value>::has_infinity ?
82.492 - std::numeric_limits<Value>::infinity() :
82.493 - std::numeric_limits<Value>::max())
82.494 + std::numeric_limits<Value>::infinity() : MAX)
82.495 {
82.496 - // Check the value types
82.497 + // Check the number types
82.498 LEMON_ASSERT(std::numeric_limits<Value>::is_signed,
82.499 "The flow type of NetworkSimplex must be signed");
82.500 LEMON_ASSERT(std::numeric_limits<Cost>::is_signed,
82.501 "The cost type of NetworkSimplex must be signed");
82.502 -
82.503 - // Resize vectors
82.504 - _node_num = countNodes(_graph);
82.505 - _arc_num = countArcs(_graph);
82.506 - int all_node_num = _node_num + 1;
82.507 - int max_arc_num = _arc_num + 2 * _node_num;
82.508
82.509 - _source.resize(max_arc_num);
82.510 - _target.resize(max_arc_num);
82.511 -
82.512 - _lower.resize(_arc_num);
82.513 - _upper.resize(_arc_num);
82.514 - _cap.resize(max_arc_num);
82.515 - _cost.resize(max_arc_num);
82.516 - _supply.resize(all_node_num);
82.517 - _flow.resize(max_arc_num);
82.518 - _pi.resize(all_node_num);
82.519 -
82.520 - _parent.resize(all_node_num);
82.521 - _pred.resize(all_node_num);
82.522 - _forward.resize(all_node_num);
82.523 - _thread.resize(all_node_num);
82.524 - _rev_thread.resize(all_node_num);
82.525 - _succ_num.resize(all_node_num);
82.526 - _last_succ.resize(all_node_num);
82.527 - _state.resize(max_arc_num);
82.528 -
82.529 - // Copy the graph (store the arcs in a mixed order)
82.530 - int i = 0;
82.531 - for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
82.532 - _node_id[n] = i;
82.533 - }
82.534 - int k = std::max(int(std::sqrt(double(_arc_num))), 10);
82.535 - i = 0;
82.536 - for (ArcIt a(_graph); a != INVALID; ++a) {
82.537 - _arc_id[a] = i;
82.538 - _source[i] = _node_id[_graph.source(a)];
82.539 - _target[i] = _node_id[_graph.target(a)];
82.540 - if ((i += k) >= _arc_num) i = (i % k) + 1;
82.541 - }
82.542 -
82.543 - // Initialize maps
82.544 - for (int i = 0; i != _node_num; ++i) {
82.545 - _supply[i] = 0;
82.546 - }
82.547 - for (int i = 0; i != _arc_num; ++i) {
82.548 - _lower[i] = 0;
82.549 - _upper[i] = INF;
82.550 - _cost[i] = 1;
82.551 - }
82.552 - _have_lower = false;
82.553 - _stype = GEQ;
82.554 + // Reset data structures
82.555 + reset();
82.556 }
82.557
82.558 /// \name Parameters
82.559 @@ -729,7 +685,7 @@
82.560 /// This function sets the upper bounds (capacities) on the arcs.
82.561 /// If it is not used before calling \ref run(), the upper bounds
82.562 /// will be set to \ref INF on all arcs (i.e. the flow value will be
82.563 - /// unbounded from above on each arc).
82.564 + /// unbounded from above).
82.565 ///
82.566 /// \param map An arc map storing the upper bounds.
82.567 /// Its \c Value type must be convertible to the \c Value type
82.568 @@ -768,7 +724,6 @@
82.569 /// This function sets the supply values of the nodes.
82.570 /// If neither this function nor \ref stSupply() is used before
82.571 /// calling \ref run(), the supply of each node will be set to zero.
82.572 - /// (It makes sense only if non-zero lower bounds are given.)
82.573 ///
82.574 /// \param map A node map storing the supply values.
82.575 /// Its \c Value type must be convertible to the \c Value type
82.576 @@ -789,7 +744,6 @@
82.577 /// and the required flow value.
82.578 /// If neither this function nor \ref supplyMap() is used before
82.579 /// calling \ref run(), the supply of each node will be set to zero.
82.580 - /// (It makes sense only if non-zero lower bounds are given.)
82.581 ///
82.582 /// Using this function has the same effect as using \ref supplyMap()
82.583 /// with such a map in which \c k is assigned to \c s, \c -k is
82.584 @@ -809,14 +763,14 @@
82.585 _supply[_node_id[t]] = -k;
82.586 return *this;
82.587 }
82.588 -
82.589 +
82.590 /// \brief Set the type of the supply constraints.
82.591 ///
82.592 /// This function sets the type of the supply/demand constraints.
82.593 /// If it is not used before calling \ref run(), the \ref GEQ supply
82.594 /// type will be used.
82.595 ///
82.596 - /// For more information see \ref SupplyType.
82.597 + /// For more information, see \ref SupplyType.
82.598 ///
82.599 /// \return <tt>(*this)</tt>
82.600 NetworkSimplex& supplyType(SupplyType supply_type) {
82.601 @@ -835,7 +789,7 @@
82.602 ///
82.603 /// This function runs the algorithm.
82.604 /// The paramters can be specified using functions \ref lowerMap(),
82.605 - /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply(),
82.606 + /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply(),
82.607 /// \ref supplyType().
82.608 /// For example,
82.609 /// \code
82.610 @@ -844,15 +798,15 @@
82.611 /// .supplyMap(sup).run();
82.612 /// \endcode
82.613 ///
82.614 - /// This function can be called more than once. All the parameters
82.615 - /// that have been given are kept for the next call, unless
82.616 - /// \ref reset() is called, thus only the modified parameters
82.617 - /// have to be set again. See \ref reset() for examples.
82.618 - /// However the underlying digraph must not be modified after this
82.619 - /// class have been constructed, since it copies and extends the graph.
82.620 + /// This function can be called more than once. All the given parameters
82.621 + /// are kept for the next call, unless \ref resetParams() or \ref reset()
82.622 + /// is used, thus only the modified parameters have to be set again.
82.623 + /// If the underlying digraph was also modified after the construction
82.624 + /// of the class (or the last \ref reset() call), then the \ref reset()
82.625 + /// function must be called.
82.626 ///
82.627 /// \param pivot_rule The pivot rule that will be used during the
82.628 - /// algorithm. For more information see \ref PivotRule.
82.629 + /// algorithm. For more information, see \ref PivotRule.
82.630 ///
82.631 /// \return \c INFEASIBLE if no feasible flow exists,
82.632 /// \n \c OPTIMAL if the problem has optimal solution
82.633 @@ -863,6 +817,7 @@
82.634 /// cost and infinite upper bound.
82.635 ///
82.636 /// \see ProblemType, PivotRule
82.637 + /// \see resetParams(), reset()
82.638 ProblemType run(PivotRule pivot_rule = BLOCK_SEARCH) {
82.639 if (!init()) return INFEASIBLE;
82.640 return start(pivot_rule);
82.641 @@ -874,11 +829,12 @@
82.642 /// before using functions \ref lowerMap(), \ref upperMap(),
82.643 /// \ref costMap(), \ref supplyMap(), \ref stSupply(), \ref supplyType().
82.644 ///
82.645 - /// It is useful for multiple run() calls. If this function is not
82.646 - /// used, all the parameters given before are kept for the next
82.647 - /// \ref run() call.
82.648 - /// However the underlying digraph must not be modified after this
82.649 - /// class have been constructed, since it copies and extends the graph.
82.650 + /// It is useful for multiple \ref run() calls. Basically, all the given
82.651 + /// parameters are kept for the next \ref run() call, unless
82.652 + /// \ref resetParams() or \ref reset() is used.
82.653 + /// If the underlying digraph was also modified after the construction
82.654 + /// of the class or the last \ref reset() call, then the \ref reset()
82.655 + /// function must be used, otherwise \ref resetParams() is sufficient.
82.656 ///
82.657 /// For example,
82.658 /// \code
82.659 @@ -888,20 +844,22 @@
82.660 /// ns.lowerMap(lower).upperMap(upper).costMap(cost)
82.661 /// .supplyMap(sup).run();
82.662 ///
82.663 - /// // Run again with modified cost map (reset() is not called,
82.664 + /// // Run again with modified cost map (resetParams() is not called,
82.665 /// // so only the cost map have to be set again)
82.666 /// cost[e] += 100;
82.667 /// ns.costMap(cost).run();
82.668 ///
82.669 - /// // Run again from scratch using reset()
82.670 + /// // Run again from scratch using resetParams()
82.671 /// // (the lower bounds will be set to zero on all arcs)
82.672 - /// ns.reset();
82.673 + /// ns.resetParams();
82.674 /// ns.upperMap(capacity).costMap(cost)
82.675 /// .supplyMap(sup).run();
82.676 /// \endcode
82.677 ///
82.678 /// \return <tt>(*this)</tt>
82.679 - NetworkSimplex& reset() {
82.680 + ///
82.681 + /// \see reset(), run()
82.682 + NetworkSimplex& resetParams() {
82.683 for (int i = 0; i != _node_num; ++i) {
82.684 _supply[i] = 0;
82.685 }
82.686 @@ -915,6 +873,83 @@
82.687 return *this;
82.688 }
82.689
82.690 + /// \brief Reset the internal data structures and all the parameters
82.691 + /// that have been given before.
82.692 + ///
82.693 + /// This function resets the internal data structures and all the
82.694 + /// paramaters that have been given before using functions \ref lowerMap(),
82.695 + /// \ref upperMap(), \ref costMap(), \ref supplyMap(), \ref stSupply(),
82.696 + /// \ref supplyType().
82.697 + ///
82.698 + /// It is useful for multiple \ref run() calls. Basically, all the given
82.699 + /// parameters are kept for the next \ref run() call, unless
82.700 + /// \ref resetParams() or \ref reset() is used.
82.701 + /// If the underlying digraph was also modified after the construction
82.702 + /// of the class or the last \ref reset() call, then the \ref reset()
82.703 + /// function must be used, otherwise \ref resetParams() is sufficient.
82.704 + ///
82.705 + /// See \ref resetParams() for examples.
82.706 + ///
82.707 + /// \return <tt>(*this)</tt>
82.708 + ///
82.709 + /// \see resetParams(), run()
82.710 + NetworkSimplex& reset() {
82.711 + // Resize vectors
82.712 + _node_num = countNodes(_graph);
82.713 + _arc_num = countArcs(_graph);
82.714 + int all_node_num = _node_num + 1;
82.715 + int max_arc_num = _arc_num + 2 * _node_num;
82.716 +
82.717 + _source.resize(max_arc_num);
82.718 + _target.resize(max_arc_num);
82.719 +
82.720 + _lower.resize(_arc_num);
82.721 + _upper.resize(_arc_num);
82.722 + _cap.resize(max_arc_num);
82.723 + _cost.resize(max_arc_num);
82.724 + _supply.resize(all_node_num);
82.725 + _flow.resize(max_arc_num);
82.726 + _pi.resize(all_node_num);
82.727 +
82.728 + _parent.resize(all_node_num);
82.729 + _pred.resize(all_node_num);
82.730 + _forward.resize(all_node_num);
82.731 + _thread.resize(all_node_num);
82.732 + _rev_thread.resize(all_node_num);
82.733 + _succ_num.resize(all_node_num);
82.734 + _last_succ.resize(all_node_num);
82.735 + _state.resize(max_arc_num);
82.736 +
82.737 + // Copy the graph
82.738 + int i = 0;
82.739 + for (NodeIt n(_graph); n != INVALID; ++n, ++i) {
82.740 + _node_id[n] = i;
82.741 + }
82.742 + if (_arc_mixing) {
82.743 + // Store the arcs in a mixed order
82.744 + int k = std::max(int(std::sqrt(double(_arc_num))), 10);
82.745 + int i = 0, j = 0;
82.746 + for (ArcIt a(_graph); a != INVALID; ++a) {
82.747 + _arc_id[a] = i;
82.748 + _source[i] = _node_id[_graph.source(a)];
82.749 + _target[i] = _node_id[_graph.target(a)];
82.750 + if ((i += k) >= _arc_num) i = ++j;
82.751 + }
82.752 + } else {
82.753 + // Store the arcs in the original order
82.754 + int i = 0;
82.755 + for (ArcIt a(_graph); a != INVALID; ++a, ++i) {
82.756 + _arc_id[a] = i;
82.757 + _source[i] = _node_id[_graph.source(a)];
82.758 + _target[i] = _node_id[_graph.target(a)];
82.759 + }
82.760 + }
82.761 +
82.762 + // Reset parameters
82.763 + resetParams();
82.764 + return *this;
82.765 + }
82.766 +
82.767 /// @}
82.768
82.769 /// \name Query Functions
82.770 @@ -1024,9 +1059,9 @@
82.771 for (int i = 0; i != _arc_num; ++i) {
82.772 Value c = _lower[i];
82.773 if (c >= 0) {
82.774 - _cap[i] = _upper[i] < INF ? _upper[i] - c : INF;
82.775 + _cap[i] = _upper[i] < MAX ? _upper[i] - c : INF;
82.776 } else {
82.777 - _cap[i] = _upper[i] < INF + c ? _upper[i] - c : INF;
82.778 + _cap[i] = _upper[i] < MAX + c ? _upper[i] - c : INF;
82.779 }
82.780 _supply[_source[i]] -= c;
82.781 _supply[_target[i]] += c;
82.782 @@ -1054,7 +1089,7 @@
82.783 _flow[i] = 0;
82.784 _state[i] = STATE_LOWER;
82.785 }
82.786 -
82.787 +
82.788 // Set data for the artificial root node
82.789 _root = _node_num;
82.790 _parent[_root] = -1;
82.791 @@ -1218,7 +1253,7 @@
82.792 for (int u = first; u != join; u = _parent[u]) {
82.793 e = _pred[u];
82.794 d = _forward[u] ?
82.795 - _flow[e] : (_cap[e] == INF ? INF : _cap[e] - _flow[e]);
82.796 + _flow[e] : (_cap[e] >= MAX ? INF : _cap[e] - _flow[e]);
82.797 if (d < delta) {
82.798 delta = d;
82.799 u_out = u;
82.800 @@ -1228,8 +1263,8 @@
82.801 // Search the cycle along the path form the second node to the root
82.802 for (int u = second; u != join; u = _parent[u]) {
82.803 e = _pred[u];
82.804 - d = _forward[u] ?
82.805 - (_cap[e] == INF ? INF : _cap[e] - _flow[e]) : _flow[e];
82.806 + d = _forward[u] ?
82.807 + (_cap[e] >= MAX ? INF : _cap[e] - _flow[e]) : _flow[e];
82.808 if (d <= delta) {
82.809 delta = d;
82.810 u_out = u;
82.811 @@ -1330,7 +1365,7 @@
82.812 }
82.813
82.814 // Update _rev_thread using the new _thread values
82.815 - for (int i = 0; i < int(_dirty_revs.size()); ++i) {
82.816 + for (int i = 0; i != int(_dirty_revs.size()); ++i) {
82.817 u = _dirty_revs[i];
82.818 _rev_thread[_thread[u]] = u;
82.819 }
82.820 @@ -1402,6 +1437,100 @@
82.821 }
82.822 }
82.823
82.824 + // Heuristic initial pivots
82.825 + bool initialPivots() {
82.826 + Value curr, total = 0;
82.827 + std::vector<Node> supply_nodes, demand_nodes;
82.828 + for (NodeIt u(_graph); u != INVALID; ++u) {
82.829 + curr = _supply[_node_id[u]];
82.830 + if (curr > 0) {
82.831 + total += curr;
82.832 + supply_nodes.push_back(u);
82.833 + }
82.834 + else if (curr < 0) {
82.835 + demand_nodes.push_back(u);
82.836 + }
82.837 + }
82.838 + if (_sum_supply > 0) total -= _sum_supply;
82.839 + if (total <= 0) return true;
82.840 +
82.841 + IntVector arc_vector;
82.842 + if (_sum_supply >= 0) {
82.843 + if (supply_nodes.size() == 1 && demand_nodes.size() == 1) {
82.844 + // Perform a reverse graph search from the sink to the source
82.845 + typename GR::template NodeMap<bool> reached(_graph, false);
82.846 + Node s = supply_nodes[0], t = demand_nodes[0];
82.847 + std::vector<Node> stack;
82.848 + reached[t] = true;
82.849 + stack.push_back(t);
82.850 + while (!stack.empty()) {
82.851 + Node u, v = stack.back();
82.852 + stack.pop_back();
82.853 + if (v == s) break;
82.854 + for (InArcIt a(_graph, v); a != INVALID; ++a) {
82.855 + if (reached[u = _graph.source(a)]) continue;
82.856 + int j = _arc_id[a];
82.857 + if (_cap[j] >= total) {
82.858 + arc_vector.push_back(j);
82.859 + reached[u] = true;
82.860 + stack.push_back(u);
82.861 + }
82.862 + }
82.863 + }
82.864 + } else {
82.865 + // Find the min. cost incomming arc for each demand node
82.866 + for (int i = 0; i != int(demand_nodes.size()); ++i) {
82.867 + Node v = demand_nodes[i];
82.868 + Cost c, min_cost = std::numeric_limits<Cost>::max();
82.869 + Arc min_arc = INVALID;
82.870 + for (InArcIt a(_graph, v); a != INVALID; ++a) {
82.871 + c = _cost[_arc_id[a]];
82.872 + if (c < min_cost) {
82.873 + min_cost = c;
82.874 + min_arc = a;
82.875 + }
82.876 + }
82.877 + if (min_arc != INVALID) {
82.878 + arc_vector.push_back(_arc_id[min_arc]);
82.879 + }
82.880 + }
82.881 + }
82.882 + } else {
82.883 + // Find the min. cost outgoing arc for each supply node
82.884 + for (int i = 0; i != int(supply_nodes.size()); ++i) {
82.885 + Node u = supply_nodes[i];
82.886 + Cost c, min_cost = std::numeric_limits<Cost>::max();
82.887 + Arc min_arc = INVALID;
82.888 + for (OutArcIt a(_graph, u); a != INVALID; ++a) {
82.889 + c = _cost[_arc_id[a]];
82.890 + if (c < min_cost) {
82.891 + min_cost = c;
82.892 + min_arc = a;
82.893 + }
82.894 + }
82.895 + if (min_arc != INVALID) {
82.896 + arc_vector.push_back(_arc_id[min_arc]);
82.897 + }
82.898 + }
82.899 + }
82.900 +
82.901 + // Perform heuristic initial pivots
82.902 + for (int i = 0; i != int(arc_vector.size()); ++i) {
82.903 + in_arc = arc_vector[i];
82.904 + if (_state[in_arc] * (_cost[in_arc] + _pi[_source[in_arc]] -
82.905 + _pi[_target[in_arc]]) >= 0) continue;
82.906 + findJoinNode();
82.907 + bool change = findLeavingArc();
82.908 + if (delta >= MAX) return false;
82.909 + changeFlow(change);
82.910 + if (change) {
82.911 + updateTreeStructure();
82.912 + updatePotential();
82.913 + }
82.914 + }
82.915 + return true;
82.916 + }
82.917 +
82.918 // Execute the algorithm
82.919 ProblemType start(PivotRule pivot_rule) {
82.920 // Select the pivot rule implementation
82.921 @@ -1424,18 +1553,21 @@
82.922 ProblemType start() {
82.923 PivotRuleImpl pivot(*this);
82.924
82.925 + // Perform heuristic initial pivots
82.926 + if (!initialPivots()) return UNBOUNDED;
82.927 +
82.928 // Execute the Network Simplex algorithm
82.929 while (pivot.findEnteringArc()) {
82.930 findJoinNode();
82.931 bool change = findLeavingArc();
82.932 - if (delta >= INF) return UNBOUNDED;
82.933 + if (delta >= MAX) return UNBOUNDED;
82.934 changeFlow(change);
82.935 if (change) {
82.936 updateTreeStructure();
82.937 updatePotential();
82.938 }
82.939 }
82.940 -
82.941 +
82.942 // Check feasibility
82.943 for (int e = _search_arc_num; e != _all_arc_num; ++e) {
82.944 if (_flow[e] != 0) return INFEASIBLE;
82.945 @@ -1452,7 +1584,7 @@
82.946 }
82.947 }
82.948 }
82.949 -
82.950 +
82.951 // Shift potentials to meet the requirements of the GEQ/LEQ type
82.952 // optimality conditions
82.953 if (_sum_supply == 0) {
83.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
83.2 +++ b/lemon/pairing_heap.h Tue Dec 20 18:15:14 2011 +0100
83.3 @@ -0,0 +1,474 @@
83.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
83.5 + *
83.6 + * This file is a part of LEMON, a generic C++ optimization library.
83.7 + *
83.8 + * Copyright (C) 2003-2009
83.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
83.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
83.11 + *
83.12 + * Permission to use, modify and distribute this software is granted
83.13 + * provided that this copyright notice appears in all copies. For
83.14 + * precise terms see the accompanying LICENSE file.
83.15 + *
83.16 + * This software is provided "AS IS" with no warranty of any kind,
83.17 + * express or implied, and with no claim as to its suitability for any
83.18 + * purpose.
83.19 + *
83.20 + */
83.21 +
83.22 +#ifndef LEMON_PAIRING_HEAP_H
83.23 +#define LEMON_PAIRING_HEAP_H
83.24 +
83.25 +///\file
83.26 +///\ingroup heaps
83.27 +///\brief Pairing heap implementation.
83.28 +
83.29 +#include <vector>
83.30 +#include <utility>
83.31 +#include <functional>
83.32 +#include <lemon/math.h>
83.33 +
83.34 +namespace lemon {
83.35 +
83.36 + /// \ingroup heaps
83.37 + ///
83.38 + ///\brief Pairing Heap.
83.39 + ///
83.40 + /// This class implements the \e pairing \e heap data structure.
83.41 + /// It fully conforms to the \ref concepts::Heap "heap concept".
83.42 + ///
83.43 + /// The methods \ref increase() and \ref erase() are not efficient
83.44 + /// in a pairing heap. In case of many calls of these operations,
83.45 + /// it is better to use other heap structure, e.g. \ref BinHeap
83.46 + /// "binary heap".
83.47 + ///
83.48 + /// \tparam PR Type of the priorities of the items.
83.49 + /// \tparam IM A read-writable item map with \c int values, used
83.50 + /// internally to handle the cross references.
83.51 + /// \tparam CMP A functor class for comparing the priorities.
83.52 + /// The default is \c std::less<PR>.
83.53 +#ifdef DOXYGEN
83.54 + template <typename PR, typename IM, typename CMP>
83.55 +#else
83.56 + template <typename PR, typename IM, typename CMP = std::less<PR> >
83.57 +#endif
83.58 + class PairingHeap {
83.59 + public:
83.60 + /// Type of the item-int map.
83.61 + typedef IM ItemIntMap;
83.62 + /// Type of the priorities.
83.63 + typedef PR Prio;
83.64 + /// Type of the items stored in the heap.
83.65 + typedef typename ItemIntMap::Key Item;
83.66 + /// Functor type for comparing the priorities.
83.67 + typedef CMP Compare;
83.68 +
83.69 + /// \brief Type to represent the states of the items.
83.70 + ///
83.71 + /// Each item has a state associated to it. It can be "in heap",
83.72 + /// "pre-heap" or "post-heap". The latter two are indifferent from the
83.73 + /// heap's point of view, but may be useful to the user.
83.74 + ///
83.75 + /// The item-int map must be initialized in such way that it assigns
83.76 + /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
83.77 + enum State {
83.78 + IN_HEAP = 0, ///< = 0.
83.79 + PRE_HEAP = -1, ///< = -1.
83.80 + POST_HEAP = -2 ///< = -2.
83.81 + };
83.82 +
83.83 + private:
83.84 + class store;
83.85 +
83.86 + std::vector<store> _data;
83.87 + int _min;
83.88 + ItemIntMap &_iim;
83.89 + Compare _comp;
83.90 + int _num_items;
83.91 +
83.92 + public:
83.93 + /// \brief Constructor.
83.94 + ///
83.95 + /// Constructor.
83.96 + /// \param map A map that assigns \c int values to the items.
83.97 + /// It is used internally to handle the cross references.
83.98 + /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
83.99 + explicit PairingHeap(ItemIntMap &map)
83.100 + : _min(0), _iim(map), _num_items(0) {}
83.101 +
83.102 + /// \brief Constructor.
83.103 + ///
83.104 + /// Constructor.
83.105 + /// \param map A map that assigns \c int values to the items.
83.106 + /// It is used internally to handle the cross references.
83.107 + /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
83.108 + /// \param comp The function object used for comparing the priorities.
83.109 + PairingHeap(ItemIntMap &map, const Compare &comp)
83.110 + : _min(0), _iim(map), _comp(comp), _num_items(0) {}
83.111 +
83.112 + /// \brief The number of items stored in the heap.
83.113 + ///
83.114 + /// This function returns the number of items stored in the heap.
83.115 + int size() const { return _num_items; }
83.116 +
83.117 + /// \brief Check if the heap is empty.
83.118 + ///
83.119 + /// This function returns \c true if the heap is empty.
83.120 + bool empty() const { return _num_items==0; }
83.121 +
83.122 + /// \brief Make the heap empty.
83.123 + ///
83.124 + /// This functon makes the heap empty.
83.125 + /// It does not change the cross reference map. If you want to reuse
83.126 + /// a heap that is not surely empty, you should first clear it and
83.127 + /// then you should set the cross reference map to \c PRE_HEAP
83.128 + /// for each item.
83.129 + void clear() {
83.130 + _data.clear();
83.131 + _min = 0;
83.132 + _num_items = 0;
83.133 + }
83.134 +
83.135 + /// \brief Set the priority of an item or insert it, if it is
83.136 + /// not stored in the heap.
83.137 + ///
83.138 + /// This method sets the priority of the given item if it is
83.139 + /// already stored in the heap. Otherwise it inserts the given
83.140 + /// item into the heap with the given priority.
83.141 + /// \param item The item.
83.142 + /// \param value The priority.
83.143 + void set (const Item& item, const Prio& value) {
83.144 + int i=_iim[item];
83.145 + if ( i>=0 && _data[i].in ) {
83.146 + if ( _comp(value, _data[i].prio) ) decrease(item, value);
83.147 + if ( _comp(_data[i].prio, value) ) increase(item, value);
83.148 + } else push(item, value);
83.149 + }
83.150 +
83.151 + /// \brief Insert an item into the heap with the given priority.
83.152 + ///
83.153 + /// This function inserts the given item into the heap with the
83.154 + /// given priority.
83.155 + /// \param item The item to insert.
83.156 + /// \param value The priority of the item.
83.157 + /// \pre \e item must not be stored in the heap.
83.158 + void push (const Item& item, const Prio& value) {
83.159 + int i=_iim[item];
83.160 + if( i<0 ) {
83.161 + int s=_data.size();
83.162 + _iim.set(item, s);
83.163 + store st;
83.164 + st.name=item;
83.165 + _data.push_back(st);
83.166 + i=s;
83.167 + } else {
83.168 + _data[i].parent=_data[i].child=-1;
83.169 + _data[i].left_child=false;
83.170 + _data[i].degree=0;
83.171 + _data[i].in=true;
83.172 + }
83.173 +
83.174 + _data[i].prio=value;
83.175 +
83.176 + if ( _num_items!=0 ) {
83.177 + if ( _comp( value, _data[_min].prio) ) {
83.178 + fuse(i,_min);
83.179 + _min=i;
83.180 + }
83.181 + else fuse(_min,i);
83.182 + }
83.183 + else _min=i;
83.184 +
83.185 + ++_num_items;
83.186 + }
83.187 +
83.188 + /// \brief Return the item having minimum priority.
83.189 + ///
83.190 + /// This function returns the item having minimum priority.
83.191 + /// \pre The heap must be non-empty.
83.192 + Item top() const { return _data[_min].name; }
83.193 +
83.194 + /// \brief The minimum priority.
83.195 + ///
83.196 + /// This function returns the minimum priority.
83.197 + /// \pre The heap must be non-empty.
83.198 + const Prio& prio() const { return _data[_min].prio; }
83.199 +
83.200 + /// \brief The priority of the given item.
83.201 + ///
83.202 + /// This function returns the priority of the given item.
83.203 + /// \param item The item.
83.204 + /// \pre \e item must be in the heap.
83.205 + const Prio& operator[](const Item& item) const {
83.206 + return _data[_iim[item]].prio;
83.207 + }
83.208 +
83.209 + /// \brief Remove the item having minimum priority.
83.210 + ///
83.211 + /// This function removes the item having minimum priority.
83.212 + /// \pre The heap must be non-empty.
83.213 + void pop() {
83.214 + std::vector<int> trees;
83.215 + int i=0, child_right = 0;
83.216 + _data[_min].in=false;
83.217 +
83.218 + if( -1!=_data[_min].child ) {
83.219 + i=_data[_min].child;
83.220 + trees.push_back(i);
83.221 + _data[i].parent = -1;
83.222 + _data[_min].child = -1;
83.223 +
83.224 + int ch=-1;
83.225 + while( _data[i].child!=-1 ) {
83.226 + ch=_data[i].child;
83.227 + if( _data[ch].left_child && i==_data[ch].parent ) {
83.228 + break;
83.229 + } else {
83.230 + if( _data[ch].left_child ) {
83.231 + child_right=_data[ch].parent;
83.232 + _data[ch].parent = i;
83.233 + --_data[i].degree;
83.234 + }
83.235 + else {
83.236 + child_right=ch;
83.237 + _data[i].child=-1;
83.238 + _data[i].degree=0;
83.239 + }
83.240 + _data[child_right].parent = -1;
83.241 + trees.push_back(child_right);
83.242 + i = child_right;
83.243 + }
83.244 + }
83.245 +
83.246 + int num_child = trees.size();
83.247 + int other;
83.248 + for( i=0; i<num_child-1; i+=2 ) {
83.249 + if ( !_comp(_data[trees[i]].prio, _data[trees[i+1]].prio) ) {
83.250 + other=trees[i];
83.251 + trees[i]=trees[i+1];
83.252 + trees[i+1]=other;
83.253 + }
83.254 + fuse( trees[i], trees[i+1] );
83.255 + }
83.256 +
83.257 + i = (0==(num_child % 2)) ? num_child-2 : num_child-1;
83.258 + while(i>=2) {
83.259 + if ( _comp(_data[trees[i]].prio, _data[trees[i-2]].prio) ) {
83.260 + other=trees[i];
83.261 + trees[i]=trees[i-2];
83.262 + trees[i-2]=other;
83.263 + }
83.264 + fuse( trees[i-2], trees[i] );
83.265 + i-=2;
83.266 + }
83.267 + _min = trees[0];
83.268 + }
83.269 + else {
83.270 + _min = _data[_min].child;
83.271 + }
83.272 +
83.273 + if (_min >= 0) _data[_min].left_child = false;
83.274 + --_num_items;
83.275 + }
83.276 +
83.277 + /// \brief Remove the given item from the heap.
83.278 + ///
83.279 + /// This function removes the given item from the heap if it is
83.280 + /// already stored.
83.281 + /// \param item The item to delete.
83.282 + /// \pre \e item must be in the heap.
83.283 + void erase (const Item& item) {
83.284 + int i=_iim[item];
83.285 + if ( i>=0 && _data[i].in ) {
83.286 + decrease( item, _data[_min].prio-1 );
83.287 + pop();
83.288 + }
83.289 + }
83.290 +
83.291 + /// \brief Decrease the priority of an item to the given value.
83.292 + ///
83.293 + /// This function decreases the priority of an item to the given value.
83.294 + /// \param item The item.
83.295 + /// \param value The priority.
83.296 + /// \pre \e item must be stored in the heap with priority at least \e value.
83.297 + void decrease (Item item, const Prio& value) {
83.298 + int i=_iim[item];
83.299 + _data[i].prio=value;
83.300 + int p=_data[i].parent;
83.301 +
83.302 + if( _data[i].left_child && i!=_data[p].child ) {
83.303 + p=_data[p].parent;
83.304 + }
83.305 +
83.306 + if ( p!=-1 && _comp(value,_data[p].prio) ) {
83.307 + cut(i,p);
83.308 + if ( _comp(_data[_min].prio,value) ) {
83.309 + fuse(_min,i);
83.310 + } else {
83.311 + fuse(i,_min);
83.312 + _min=i;
83.313 + }
83.314 + }
83.315 + }
83.316 +
83.317 + /// \brief Increase the priority of an item to the given value.
83.318 + ///
83.319 + /// This function increases the priority of an item to the given value.
83.320 + /// \param item The item.
83.321 + /// \param value The priority.
83.322 + /// \pre \e item must be stored in the heap with priority at most \e value.
83.323 + void increase (Item item, const Prio& value) {
83.324 + erase(item);
83.325 + push(item,value);
83.326 + }
83.327 +
83.328 + /// \brief Return the state of an item.
83.329 + ///
83.330 + /// This method returns \c PRE_HEAP if the given item has never
83.331 + /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
83.332 + /// and \c POST_HEAP otherwise.
83.333 + /// In the latter case it is possible that the item will get back
83.334 + /// to the heap again.
83.335 + /// \param item The item.
83.336 + State state(const Item &item) const {
83.337 + int i=_iim[item];
83.338 + if( i>=0 ) {
83.339 + if( _data[i].in ) i=0;
83.340 + else i=-2;
83.341 + }
83.342 + return State(i);
83.343 + }
83.344 +
83.345 + /// \brief Set the state of an item in the heap.
83.346 + ///
83.347 + /// This function sets the state of the given item in the heap.
83.348 + /// It can be used to manually clear the heap when it is important
83.349 + /// to achive better time complexity.
83.350 + /// \param i The item.
83.351 + /// \param st The state. It should not be \c IN_HEAP.
83.352 + void state(const Item& i, State st) {
83.353 + switch (st) {
83.354 + case POST_HEAP:
83.355 + case PRE_HEAP:
83.356 + if (state(i) == IN_HEAP) erase(i);
83.357 + _iim[i]=st;
83.358 + break;
83.359 + case IN_HEAP:
83.360 + break;
83.361 + }
83.362 + }
83.363 +
83.364 + private:
83.365 +
83.366 + void cut(int a, int b) {
83.367 + int child_a;
83.368 + switch (_data[a].degree) {
83.369 + case 2:
83.370 + child_a = _data[_data[a].child].parent;
83.371 + if( _data[a].left_child ) {
83.372 + _data[child_a].left_child=true;
83.373 + _data[b].child=child_a;
83.374 + _data[child_a].parent=_data[a].parent;
83.375 + }
83.376 + else {
83.377 + _data[child_a].left_child=false;
83.378 + _data[child_a].parent=b;
83.379 + if( a!=_data[b].child )
83.380 + _data[_data[b].child].parent=child_a;
83.381 + else
83.382 + _data[b].child=child_a;
83.383 + }
83.384 + --_data[a].degree;
83.385 + _data[_data[a].child].parent=a;
83.386 + break;
83.387 +
83.388 + case 1:
83.389 + child_a = _data[a].child;
83.390 + if( !_data[child_a].left_child ) {
83.391 + --_data[a].degree;
83.392 + if( _data[a].left_child ) {
83.393 + _data[child_a].left_child=true;
83.394 + _data[child_a].parent=_data[a].parent;
83.395 + _data[b].child=child_a;
83.396 + }
83.397 + else {
83.398 + _data[child_a].left_child=false;
83.399 + _data[child_a].parent=b;
83.400 + if( a!=_data[b].child )
83.401 + _data[_data[b].child].parent=child_a;
83.402 + else
83.403 + _data[b].child=child_a;
83.404 + }
83.405 + _data[a].child=-1;
83.406 + }
83.407 + else {
83.408 + --_data[b].degree;
83.409 + if( _data[a].left_child ) {
83.410 + _data[b].child =
83.411 + (1==_data[b].degree) ? _data[a].parent : -1;
83.412 + } else {
83.413 + if (1==_data[b].degree)
83.414 + _data[_data[b].child].parent=b;
83.415 + else
83.416 + _data[b].child=-1;
83.417 + }
83.418 + }
83.419 + break;
83.420 +
83.421 + case 0:
83.422 + --_data[b].degree;
83.423 + if( _data[a].left_child ) {
83.424 + _data[b].child =
83.425 + (0!=_data[b].degree) ? _data[a].parent : -1;
83.426 + } else {
83.427 + if( 0!=_data[b].degree )
83.428 + _data[_data[b].child].parent=b;
83.429 + else
83.430 + _data[b].child=-1;
83.431 + }
83.432 + break;
83.433 + }
83.434 + _data[a].parent=-1;
83.435 + _data[a].left_child=false;
83.436 + }
83.437 +
83.438 + void fuse(int a, int b) {
83.439 + int child_a = _data[a].child;
83.440 + int child_b = _data[b].child;
83.441 + _data[a].child=b;
83.442 + _data[b].parent=a;
83.443 + _data[b].left_child=true;
83.444 +
83.445 + if( -1!=child_a ) {
83.446 + _data[b].child=child_a;
83.447 + _data[child_a].parent=b;
83.448 + _data[child_a].left_child=false;
83.449 + ++_data[b].degree;
83.450 +
83.451 + if( -1!=child_b ) {
83.452 + _data[b].child=child_b;
83.453 + _data[child_b].parent=child_a;
83.454 + }
83.455 + }
83.456 + else { ++_data[a].degree; }
83.457 + }
83.458 +
83.459 + class store {
83.460 + friend class PairingHeap;
83.461 +
83.462 + Item name;
83.463 + int parent;
83.464 + int child;
83.465 + bool left_child;
83.466 + int degree;
83.467 + bool in;
83.468 + Prio prio;
83.469 +
83.470 + store() : parent(-1), child(-1), left_child(false), degree(0), in(true) {}
83.471 + };
83.472 + };
83.473 +
83.474 +} //namespace lemon
83.475 +
83.476 +#endif //LEMON_PAIRING_HEAP_H
83.477 +
84.1 --- a/lemon/path.h Tue Dec 20 17:44:38 2011 +0100
84.2 +++ b/lemon/path.h Tue Dec 20 18:15:14 2011 +0100
84.3 @@ -2,7 +2,7 @@
84.4 *
84.5 * This file is a part of LEMON, a generic C++ optimization library.
84.6 *
84.7 - * Copyright (C) 2003-2009
84.8 + * Copyright (C) 2003-2010
84.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
84.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
84.11 *
84.12 @@ -966,20 +966,20 @@
84.13 }
84.14 };
84.15
84.16 -
84.17 +
84.18 template <typename From, typename To,
84.19 bool revEnable = RevPathTagIndicator<From>::value>
84.20 struct PathCopySelector {
84.21 static void copy(const From& from, To& to) {
84.22 PathCopySelectorForward<From, To>::copy(from, to);
84.23 - }
84.24 + }
84.25 };
84.26
84.27 template <typename From, typename To>
84.28 struct PathCopySelector<From, To, true> {
84.29 static void copy(const From& from, To& to) {
84.30 PathCopySelectorBackward<From, To>::copy(from, to);
84.31 - }
84.32 + }
84.33 };
84.34
84.35 }
85.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
85.2 +++ b/lemon/planarity.h Tue Dec 20 18:15:14 2011 +0100
85.3 @@ -0,0 +1,2755 @@
85.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
85.5 + *
85.6 + * This file is a part of LEMON, a generic C++ optimization library.
85.7 + *
85.8 + * Copyright (C) 2003-2010
85.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
85.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
85.11 + *
85.12 + * Permission to use, modify and distribute this software is granted
85.13 + * provided that this copyright notice appears in all copies. For
85.14 + * precise terms see the accompanying LICENSE file.
85.15 + *
85.16 + * This software is provided "AS IS" with no warranty of any kind,
85.17 + * express or implied, and with no claim as to its suitability for any
85.18 + * purpose.
85.19 + *
85.20 + */
85.21 +
85.22 +#ifndef LEMON_PLANARITY_H
85.23 +#define LEMON_PLANARITY_H
85.24 +
85.25 +/// \ingroup planar
85.26 +/// \file
85.27 +/// \brief Planarity checking, embedding, drawing and coloring
85.28 +
85.29 +#include <vector>
85.30 +#include <list>
85.31 +
85.32 +#include <lemon/dfs.h>
85.33 +#include <lemon/bfs.h>
85.34 +#include <lemon/radix_sort.h>
85.35 +#include <lemon/maps.h>
85.36 +#include <lemon/path.h>
85.37 +#include <lemon/bucket_heap.h>
85.38 +#include <lemon/adaptors.h>
85.39 +#include <lemon/edge_set.h>
85.40 +#include <lemon/color.h>
85.41 +#include <lemon/dim2.h>
85.42 +
85.43 +namespace lemon {
85.44 +
85.45 + namespace _planarity_bits {
85.46 +
85.47 + template <typename Graph>
85.48 + struct PlanarityVisitor : DfsVisitor<Graph> {
85.49 +
85.50 + TEMPLATE_GRAPH_TYPEDEFS(Graph);
85.51 +
85.52 + typedef typename Graph::template NodeMap<Arc> PredMap;
85.53 +
85.54 + typedef typename Graph::template EdgeMap<bool> TreeMap;
85.55 +
85.56 + typedef typename Graph::template NodeMap<int> OrderMap;
85.57 + typedef std::vector<Node> OrderList;
85.58 +
85.59 + typedef typename Graph::template NodeMap<int> LowMap;
85.60 + typedef typename Graph::template NodeMap<int> AncestorMap;
85.61 +
85.62 + PlanarityVisitor(const Graph& graph,
85.63 + PredMap& pred_map, TreeMap& tree_map,
85.64 + OrderMap& order_map, OrderList& order_list,
85.65 + AncestorMap& ancestor_map, LowMap& low_map)
85.66 + : _graph(graph), _pred_map(pred_map), _tree_map(tree_map),
85.67 + _order_map(order_map), _order_list(order_list),
85.68 + _ancestor_map(ancestor_map), _low_map(low_map) {}
85.69 +
85.70 + void reach(const Node& node) {
85.71 + _order_map[node] = _order_list.size();
85.72 + _low_map[node] = _order_list.size();
85.73 + _ancestor_map[node] = _order_list.size();
85.74 + _order_list.push_back(node);
85.75 + }
85.76 +
85.77 + void discover(const Arc& arc) {
85.78 + Node source = _graph.source(arc);
85.79 + Node target = _graph.target(arc);
85.80 +
85.81 + _tree_map[arc] = true;
85.82 + _pred_map[target] = arc;
85.83 + }
85.84 +
85.85 + void examine(const Arc& arc) {
85.86 + Node source = _graph.source(arc);
85.87 + Node target = _graph.target(arc);
85.88 +
85.89 + if (_order_map[target] < _order_map[source] && !_tree_map[arc]) {
85.90 + if (_low_map[source] > _order_map[target]) {
85.91 + _low_map[source] = _order_map[target];
85.92 + }
85.93 + if (_ancestor_map[source] > _order_map[target]) {
85.94 + _ancestor_map[source] = _order_map[target];
85.95 + }
85.96 + }
85.97 + }
85.98 +
85.99 + void backtrack(const Arc& arc) {
85.100 + Node source = _graph.source(arc);
85.101 + Node target = _graph.target(arc);
85.102 +
85.103 + if (_low_map[source] > _low_map[target]) {
85.104 + _low_map[source] = _low_map[target];
85.105 + }
85.106 + }
85.107 +
85.108 + const Graph& _graph;
85.109 + PredMap& _pred_map;
85.110 + TreeMap& _tree_map;
85.111 + OrderMap& _order_map;
85.112 + OrderList& _order_list;
85.113 + AncestorMap& _ancestor_map;
85.114 + LowMap& _low_map;
85.115 + };
85.116 +
85.117 + template <typename Graph, bool embedding = true>
85.118 + struct NodeDataNode {
85.119 + int prev, next;
85.120 + int visited;
85.121 + typename Graph::Arc first;
85.122 + bool inverted;
85.123 + };
85.124 +
85.125 + template <typename Graph>
85.126 + struct NodeDataNode<Graph, false> {
85.127 + int prev, next;
85.128 + int visited;
85.129 + };
85.130 +
85.131 + template <typename Graph>
85.132 + struct ChildListNode {
85.133 + typedef typename Graph::Node Node;
85.134 + Node first;
85.135 + Node prev, next;
85.136 + };
85.137 +
85.138 + template <typename Graph>
85.139 + struct ArcListNode {
85.140 + typename Graph::Arc prev, next;
85.141 + };
85.142 +
85.143 + template <typename Graph>
85.144 + class PlanarityChecking {
85.145 + private:
85.146 +
85.147 + TEMPLATE_GRAPH_TYPEDEFS(Graph);
85.148 +
85.149 + const Graph& _graph;
85.150 +
85.151 + private:
85.152 +
85.153 + typedef typename Graph::template NodeMap<Arc> PredMap;
85.154 +
85.155 + typedef typename Graph::template EdgeMap<bool> TreeMap;
85.156 +
85.157 + typedef typename Graph::template NodeMap<int> OrderMap;
85.158 + typedef std::vector<Node> OrderList;
85.159 +
85.160 + typedef typename Graph::template NodeMap<int> LowMap;
85.161 + typedef typename Graph::template NodeMap<int> AncestorMap;
85.162 +
85.163 + typedef _planarity_bits::NodeDataNode<Graph> NodeDataNode;
85.164 + typedef std::vector<NodeDataNode> NodeData;
85.165 +
85.166 + typedef _planarity_bits::ChildListNode<Graph> ChildListNode;
85.167 + typedef typename Graph::template NodeMap<ChildListNode> ChildLists;
85.168 +
85.169 + typedef typename Graph::template NodeMap<std::list<int> > MergeRoots;
85.170 +
85.171 + typedef typename Graph::template NodeMap<bool> EmbedArc;
85.172 +
85.173 + public:
85.174 +
85.175 + PlanarityChecking(const Graph& graph) : _graph(graph) {}
85.176 +
85.177 + bool run() {
85.178 + typedef _planarity_bits::PlanarityVisitor<Graph> Visitor;
85.179 +
85.180 + PredMap pred_map(_graph, INVALID);
85.181 + TreeMap tree_map(_graph, false);
85.182 +
85.183 + OrderMap order_map(_graph, -1);
85.184 + OrderList order_list;
85.185 +
85.186 + AncestorMap ancestor_map(_graph, -1);
85.187 + LowMap low_map(_graph, -1);
85.188 +
85.189 + Visitor visitor(_graph, pred_map, tree_map,
85.190 + order_map, order_list, ancestor_map, low_map);
85.191 + DfsVisit<Graph, Visitor> visit(_graph, visitor);
85.192 + visit.run();
85.193 +
85.194 + ChildLists child_lists(_graph);
85.195 + createChildLists(tree_map, order_map, low_map, child_lists);
85.196 +
85.197 + NodeData node_data(2 * order_list.size());
85.198 +
85.199 + EmbedArc embed_arc(_graph, false);
85.200 +
85.201 + MergeRoots merge_roots(_graph);
85.202 +
85.203 + for (int i = order_list.size() - 1; i >= 0; --i) {
85.204 +
85.205 + Node node = order_list[i];
85.206 +
85.207 + Node source = node;
85.208 + for (OutArcIt e(_graph, node); e != INVALID; ++e) {
85.209 + Node target = _graph.target(e);
85.210 +
85.211 + if (order_map[source] < order_map[target] && tree_map[e]) {
85.212 + initFace(target, node_data, order_map, order_list);
85.213 + }
85.214 + }
85.215 +
85.216 + for (OutArcIt e(_graph, node); e != INVALID; ++e) {
85.217 + Node target = _graph.target(e);
85.218 +
85.219 + if (order_map[source] < order_map[target] && !tree_map[e]) {
85.220 + embed_arc[target] = true;
85.221 + walkUp(target, source, i, pred_map, low_map,
85.222 + order_map, order_list, node_data, merge_roots);
85.223 + }
85.224 + }
85.225 +
85.226 + for (typename MergeRoots::Value::iterator it =
85.227 + merge_roots[node].begin();
85.228 + it != merge_roots[node].end(); ++it) {
85.229 + int rn = *it;
85.230 + walkDown(rn, i, node_data, order_list, child_lists,
85.231 + ancestor_map, low_map, embed_arc, merge_roots);
85.232 + }
85.233 + merge_roots[node].clear();
85.234 +
85.235 + for (OutArcIt e(_graph, node); e != INVALID; ++e) {
85.236 + Node target = _graph.target(e);
85.237 +
85.238 + if (order_map[source] < order_map[target] && !tree_map[e]) {
85.239 + if (embed_arc[target]) {
85.240 + return false;
85.241 + }
85.242 + }
85.243 + }
85.244 + }
85.245 +
85.246 + return true;
85.247 + }
85.248 +
85.249 + private:
85.250 +
85.251 + void createChildLists(const TreeMap& tree_map, const OrderMap& order_map,
85.252 + const LowMap& low_map, ChildLists& child_lists) {
85.253 +
85.254 + for (NodeIt n(_graph); n != INVALID; ++n) {
85.255 + Node source = n;
85.256 +
85.257 + std::vector<Node> targets;
85.258 + for (OutArcIt e(_graph, n); e != INVALID; ++e) {
85.259 + Node target = _graph.target(e);
85.260 +
85.261 + if (order_map[source] < order_map[target] && tree_map[e]) {
85.262 + targets.push_back(target);
85.263 + }
85.264 + }
85.265 +
85.266 + if (targets.size() == 0) {
85.267 + child_lists[source].first = INVALID;
85.268 + } else if (targets.size() == 1) {
85.269 + child_lists[source].first = targets[0];
85.270 + child_lists[targets[0]].prev = INVALID;
85.271 + child_lists[targets[0]].next = INVALID;
85.272 + } else {
85.273 + radixSort(targets.begin(), targets.end(), mapToFunctor(low_map));
85.274 + for (int i = 1; i < int(targets.size()); ++i) {
85.275 + child_lists[targets[i]].prev = targets[i - 1];
85.276 + child_lists[targets[i - 1]].next = targets[i];
85.277 + }
85.278 + child_lists[targets.back()].next = INVALID;
85.279 + child_lists[targets.front()].prev = INVALID;
85.280 + child_lists[source].first = targets.front();
85.281 + }
85.282 + }
85.283 + }
85.284 +
85.285 + void walkUp(const Node& node, Node root, int rorder,
85.286 + const PredMap& pred_map, const LowMap& low_map,
85.287 + const OrderMap& order_map, const OrderList& order_list,
85.288 + NodeData& node_data, MergeRoots& merge_roots) {
85.289 +
85.290 + int na, nb;
85.291 + bool da, db;
85.292 +
85.293 + na = nb = order_map[node];
85.294 + da = true; db = false;
85.295 +
85.296 + while (true) {
85.297 +
85.298 + if (node_data[na].visited == rorder) break;
85.299 + if (node_data[nb].visited == rorder) break;
85.300 +
85.301 + node_data[na].visited = rorder;
85.302 + node_data[nb].visited = rorder;
85.303 +
85.304 + int rn = -1;
85.305 +
85.306 + if (na >= int(order_list.size())) {
85.307 + rn = na;
85.308 + } else if (nb >= int(order_list.size())) {
85.309 + rn = nb;
85.310 + }
85.311 +
85.312 + if (rn == -1) {
85.313 + int nn;
85.314 +
85.315 + nn = da ? node_data[na].prev : node_data[na].next;
85.316 + da = node_data[nn].prev != na;
85.317 + na = nn;
85.318 +
85.319 + nn = db ? node_data[nb].prev : node_data[nb].next;
85.320 + db = node_data[nn].prev != nb;
85.321 + nb = nn;
85.322 +
85.323 + } else {
85.324 +
85.325 + Node rep = order_list[rn - order_list.size()];
85.326 + Node parent = _graph.source(pred_map[rep]);
85.327 +
85.328 + if (low_map[rep] < rorder) {
85.329 + merge_roots[parent].push_back(rn);
85.330 + } else {
85.331 + merge_roots[parent].push_front(rn);
85.332 + }
85.333 +
85.334 + if (parent != root) {
85.335 + na = nb = order_map[parent];
85.336 + da = true; db = false;
85.337 + } else {
85.338 + break;
85.339 + }
85.340 + }
85.341 + }
85.342 + }
85.343 +
85.344 + void walkDown(int rn, int rorder, NodeData& node_data,
85.345 + OrderList& order_list, ChildLists& child_lists,
85.346 + AncestorMap& ancestor_map, LowMap& low_map,
85.347 + EmbedArc& embed_arc, MergeRoots& merge_roots) {
85.348 +
85.349 + std::vector<std::pair<int, bool> > merge_stack;
85.350 +
85.351 + for (int di = 0; di < 2; ++di) {
85.352 + bool rd = di == 0;
85.353 + int pn = rn;
85.354 + int n = rd ? node_data[rn].next : node_data[rn].prev;
85.355 +
85.356 + while (n != rn) {
85.357 +
85.358 + Node node = order_list[n];
85.359 +
85.360 + if (embed_arc[node]) {
85.361 +
85.362 + // Merging components on the critical path
85.363 + while (!merge_stack.empty()) {
85.364 +
85.365 + // Component root
85.366 + int cn = merge_stack.back().first;
85.367 + bool cd = merge_stack.back().second;
85.368 + merge_stack.pop_back();
85.369 +
85.370 + // Parent of component
85.371 + int dn = merge_stack.back().first;
85.372 + bool dd = merge_stack.back().second;
85.373 + merge_stack.pop_back();
85.374 +
85.375 + Node parent = order_list[dn];
85.376 +
85.377 + // Erasing from merge_roots
85.378 + merge_roots[parent].pop_front();
85.379 +
85.380 + Node child = order_list[cn - order_list.size()];
85.381 +
85.382 + // Erasing from child_lists
85.383 + if (child_lists[child].prev != INVALID) {
85.384 + child_lists[child_lists[child].prev].next =
85.385 + child_lists[child].next;
85.386 + } else {
85.387 + child_lists[parent].first = child_lists[child].next;
85.388 + }
85.389 +
85.390 + if (child_lists[child].next != INVALID) {
85.391 + child_lists[child_lists[child].next].prev =
85.392 + child_lists[child].prev;
85.393 + }
85.394 +
85.395 + // Merging external faces
85.396 + {
85.397 + int en = cn;
85.398 + cn = cd ? node_data[cn].prev : node_data[cn].next;
85.399 + cd = node_data[cn].next == en;
85.400 +
85.401 + }
85.402 +
85.403 + if (cd) node_data[cn].next = dn; else node_data[cn].prev = dn;
85.404 + if (dd) node_data[dn].prev = cn; else node_data[dn].next = cn;
85.405 +
85.406 + }
85.407 +
85.408 + bool d = pn == node_data[n].prev;
85.409 +
85.410 + if (node_data[n].prev == node_data[n].next &&
85.411 + node_data[n].inverted) {
85.412 + d = !d;
85.413 + }
85.414 +
85.415 + // Embedding arc into external face
85.416 + if (rd) node_data[rn].next = n; else node_data[rn].prev = n;
85.417 + if (d) node_data[n].prev = rn; else node_data[n].next = rn;
85.418 + pn = rn;
85.419 +
85.420 + embed_arc[order_list[n]] = false;
85.421 + }
85.422 +
85.423 + if (!merge_roots[node].empty()) {
85.424 +
85.425 + bool d = pn == node_data[n].prev;
85.426 +
85.427 + merge_stack.push_back(std::make_pair(n, d));
85.428 +
85.429 + int rn = merge_roots[node].front();
85.430 +
85.431 + int xn = node_data[rn].next;
85.432 + Node xnode = order_list[xn];
85.433 +
85.434 + int yn = node_data[rn].prev;
85.435 + Node ynode = order_list[yn];
85.436 +
85.437 + bool rd;
85.438 + if (!external(xnode, rorder, child_lists,
85.439 + ancestor_map, low_map)) {
85.440 + rd = true;
85.441 + } else if (!external(ynode, rorder, child_lists,
85.442 + ancestor_map, low_map)) {
85.443 + rd = false;
85.444 + } else if (pertinent(xnode, embed_arc, merge_roots)) {
85.445 + rd = true;
85.446 + } else {
85.447 + rd = false;
85.448 + }
85.449 +
85.450 + merge_stack.push_back(std::make_pair(rn, rd));
85.451 +
85.452 + pn = rn;
85.453 + n = rd ? xn : yn;
85.454 +
85.455 + } else if (!external(node, rorder, child_lists,
85.456 + ancestor_map, low_map)) {
85.457 + int nn = (node_data[n].next != pn ?
85.458 + node_data[n].next : node_data[n].prev);
85.459 +
85.460 + bool nd = n == node_data[nn].prev;
85.461 +
85.462 + if (nd) node_data[nn].prev = pn;
85.463 + else node_data[nn].next = pn;
85.464 +
85.465 + if (n == node_data[pn].prev) node_data[pn].prev = nn;
85.466 + else node_data[pn].next = nn;
85.467 +
85.468 + node_data[nn].inverted =
85.469 + (node_data[nn].prev == node_data[nn].next && nd != rd);
85.470 +
85.471 + n = nn;
85.472 + }
85.473 + else break;
85.474 +
85.475 + }
85.476 +
85.477 + if (!merge_stack.empty() || n == rn) {
85.478 + break;
85.479 + }
85.480 + }
85.481 + }
85.482 +
85.483 + void initFace(const Node& node, NodeData& node_data,
85.484 + const OrderMap& order_map, const OrderList& order_list) {
85.485 + int n = order_map[node];
85.486 + int rn = n + order_list.size();
85.487 +
85.488 + node_data[n].next = node_data[n].prev = rn;
85.489 + node_data[rn].next = node_data[rn].prev = n;
85.490 +
85.491 + node_data[n].visited = order_list.size();
85.492 + node_data[rn].visited = order_list.size();
85.493 +
85.494 + }
85.495 +
85.496 + bool external(const Node& node, int rorder,
85.497 + ChildLists& child_lists, AncestorMap& ancestor_map,
85.498 + LowMap& low_map) {
85.499 + Node child = child_lists[node].first;
85.500 +
85.501 + if (child != INVALID) {
85.502 + if (low_map[child] < rorder) return true;
85.503 + }
85.504 +
85.505 + if (ancestor_map[node] < rorder) return true;
85.506 +
85.507 + return false;
85.508 + }
85.509 +
85.510 + bool pertinent(const Node& node, const EmbedArc& embed_arc,
85.511 + const MergeRoots& merge_roots) {
85.512 + return !merge_roots[node].empty() || embed_arc[node];
85.513 + }
85.514 +
85.515 + };
85.516 +
85.517 + }
85.518 +
85.519 + /// \ingroup planar
85.520 + ///
85.521 + /// \brief Planarity checking of an undirected simple graph
85.522 + ///
85.523 + /// This function implements the Boyer-Myrvold algorithm for
85.524 + /// planarity checking of an undirected simple graph. It is a simplified
85.525 + /// version of the PlanarEmbedding algorithm class because neither
85.526 + /// the embedding nor the Kuratowski subdivisons are computed.
85.527 + template <typename GR>
85.528 + bool checkPlanarity(const GR& graph) {
85.529 + _planarity_bits::PlanarityChecking<GR> pc(graph);
85.530 + return pc.run();
85.531 + }
85.532 +
85.533 + /// \ingroup planar
85.534 + ///
85.535 + /// \brief Planar embedding of an undirected simple graph
85.536 + ///
85.537 + /// This class implements the Boyer-Myrvold algorithm for planar
85.538 + /// embedding of an undirected simple graph. The planar embedding is an
85.539 + /// ordering of the outgoing edges of the nodes, which is a possible
85.540 + /// configuration to draw the graph in the plane. If there is not
85.541 + /// such ordering then the graph contains a K<sub>5</sub> (full graph
85.542 + /// with 5 nodes) or a K<sub>3,3</sub> (complete bipartite graph on
85.543 + /// 3 Red and 3 Blue nodes) subdivision.
85.544 + ///
85.545 + /// The current implementation calculates either an embedding or a
85.546 + /// Kuratowski subdivision. The running time of the algorithm is O(n).
85.547 + ///
85.548 + /// \see PlanarDrawing, checkPlanarity()
85.549 + template <typename Graph>
85.550 + class PlanarEmbedding {
85.551 + private:
85.552 +
85.553 + TEMPLATE_GRAPH_TYPEDEFS(Graph);
85.554 +
85.555 + const Graph& _graph;
85.556 + typename Graph::template ArcMap<Arc> _embedding;
85.557 +
85.558 + typename Graph::template EdgeMap<bool> _kuratowski;
85.559 +
85.560 + private:
85.561 +
85.562 + typedef typename Graph::template NodeMap<Arc> PredMap;
85.563 +
85.564 + typedef typename Graph::template EdgeMap<bool> TreeMap;
85.565 +
85.566 + typedef typename Graph::template NodeMap<int> OrderMap;
85.567 + typedef std::vector<Node> OrderList;
85.568 +
85.569 + typedef typename Graph::template NodeMap<int> LowMap;
85.570 + typedef typename Graph::template NodeMap<int> AncestorMap;
85.571 +
85.572 + typedef _planarity_bits::NodeDataNode<Graph> NodeDataNode;
85.573 + typedef std::vector<NodeDataNode> NodeData;
85.574 +
85.575 + typedef _planarity_bits::ChildListNode<Graph> ChildListNode;
85.576 + typedef typename Graph::template NodeMap<ChildListNode> ChildLists;
85.577 +
85.578 + typedef typename Graph::template NodeMap<std::list<int> > MergeRoots;
85.579 +
85.580 + typedef typename Graph::template NodeMap<Arc> EmbedArc;
85.581 +
85.582 + typedef _planarity_bits::ArcListNode<Graph> ArcListNode;
85.583 + typedef typename Graph::template ArcMap<ArcListNode> ArcLists;
85.584 +
85.585 + typedef typename Graph::template NodeMap<bool> FlipMap;
85.586 +
85.587 + typedef typename Graph::template NodeMap<int> TypeMap;
85.588 +
85.589 + enum IsolatorNodeType {
85.590 + HIGHX = 6, LOWX = 7,
85.591 + HIGHY = 8, LOWY = 9,
85.592 + ROOT = 10, PERTINENT = 11,
85.593 + INTERNAL = 12
85.594 + };
85.595 +
85.596 + public:
85.597 +
85.598 + /// \brief The map type for storing the embedding
85.599 + ///
85.600 + /// The map type for storing the embedding.
85.601 + /// \see embeddingMap()
85.602 + typedef typename Graph::template ArcMap<Arc> EmbeddingMap;
85.603 +
85.604 + /// \brief Constructor
85.605 + ///
85.606 + /// Constructor.
85.607 + /// \pre The graph must be simple, i.e. it should not
85.608 + /// contain parallel or loop arcs.
85.609 + PlanarEmbedding(const Graph& graph)
85.610 + : _graph(graph), _embedding(_graph), _kuratowski(graph, false) {}
85.611 +
85.612 + /// \brief Run the algorithm.
85.613 + ///
85.614 + /// This function runs the algorithm.
85.615 + /// \param kuratowski If this parameter is set to \c false, then the
85.616 + /// algorithm does not compute a Kuratowski subdivision.
85.617 + /// \return \c true if the graph is planar.
85.618 + bool run(bool kuratowski = true) {
85.619 + typedef _planarity_bits::PlanarityVisitor<Graph> Visitor;
85.620 +
85.621 + PredMap pred_map(_graph, INVALID);
85.622 + TreeMap tree_map(_graph, false);
85.623 +
85.624 + OrderMap order_map(_graph, -1);
85.625 + OrderList order_list;
85.626 +
85.627 + AncestorMap ancestor_map(_graph, -1);
85.628 + LowMap low_map(_graph, -1);
85.629 +
85.630 + Visitor visitor(_graph, pred_map, tree_map,
85.631 + order_map, order_list, ancestor_map, low_map);
85.632 + DfsVisit<Graph, Visitor> visit(_graph, visitor);
85.633 + visit.run();
85.634 +
85.635 + ChildLists child_lists(_graph);
85.636 + createChildLists(tree_map, order_map, low_map, child_lists);
85.637 +
85.638 + NodeData node_data(2 * order_list.size());
85.639 +
85.640 + EmbedArc embed_arc(_graph, INVALID);
85.641 +
85.642 + MergeRoots merge_roots(_graph);
85.643 +
85.644 + ArcLists arc_lists(_graph);
85.645 +
85.646 + FlipMap flip_map(_graph, false);
85.647 +
85.648 + for (int i = order_list.size() - 1; i >= 0; --i) {
85.649 +
85.650 + Node node = order_list[i];
85.651 +
85.652 + node_data[i].first = INVALID;
85.653 +
85.654 + Node source = node;
85.655 + for (OutArcIt e(_graph, node); e != INVALID; ++e) {
85.656 + Node target = _graph.target(e);
85.657 +
85.658 + if (order_map[source] < order_map[target] && tree_map[e]) {
85.659 + initFace(target, arc_lists, node_data,
85.660 + pred_map, order_map, order_list);
85.661 + }
85.662 + }
85.663 +
85.664 + for (OutArcIt e(_graph, node); e != INVALID; ++e) {
85.665 + Node target = _graph.target(e);
85.666 +
85.667 + if (order_map[source] < order_map[target] && !tree_map[e]) {
85.668 + embed_arc[target] = e;
85.669 + walkUp(target, source, i, pred_map, low_map,
85.670 + order_map, order_list, node_data, merge_roots);
85.671 + }
85.672 + }
85.673 +
85.674 + for (typename MergeRoots::Value::iterator it =
85.675 + merge_roots[node].begin(); it != merge_roots[node].end(); ++it) {
85.676 + int rn = *it;
85.677 + walkDown(rn, i, node_data, arc_lists, flip_map, order_list,
85.678 + child_lists, ancestor_map, low_map, embed_arc, merge_roots);
85.679 + }
85.680 + merge_roots[node].clear();
85.681 +
85.682 + for (OutArcIt e(_graph, node); e != INVALID; ++e) {
85.683 + Node target = _graph.target(e);
85.684 +
85.685 + if (order_map[source] < order_map[target] && !tree_map[e]) {
85.686 + if (embed_arc[target] != INVALID) {
85.687 + if (kuratowski) {
85.688 + isolateKuratowski(e, node_data, arc_lists, flip_map,
85.689 + order_map, order_list, pred_map, child_lists,
85.690 + ancestor_map, low_map,
85.691 + embed_arc, merge_roots);
85.692 + }
85.693 + return false;
85.694 + }
85.695 + }
85.696 + }
85.697 + }
85.698 +
85.699 + for (int i = 0; i < int(order_list.size()); ++i) {
85.700 +
85.701 + mergeRemainingFaces(order_list[i], node_data, order_list, order_map,
85.702 + child_lists, arc_lists);
85.703 + storeEmbedding(order_list[i], node_data, order_map, pred_map,
85.704 + arc_lists, flip_map);
85.705 + }
85.706 +
85.707 + return true;
85.708 + }
85.709 +
85.710 + /// \brief Give back the successor of an arc
85.711 + ///
85.712 + /// This function gives back the successor of an arc. It makes
85.713 + /// possible to query the cyclic order of the outgoing arcs from
85.714 + /// a node.
85.715 + Arc next(const Arc& arc) const {
85.716 + return _embedding[arc];
85.717 + }
85.718 +
85.719 + /// \brief Give back the calculated embedding map
85.720 + ///
85.721 + /// This function gives back the calculated embedding map, which
85.722 + /// contains the successor of each arc in the cyclic order of the
85.723 + /// outgoing arcs of its source node.
85.724 + const EmbeddingMap& embeddingMap() const {
85.725 + return _embedding;
85.726 + }
85.727 +
85.728 + /// \brief Give back \c true if the given edge is in the Kuratowski
85.729 + /// subdivision
85.730 + ///
85.731 + /// This function gives back \c true if the given edge is in the found
85.732 + /// Kuratowski subdivision.
85.733 + /// \pre The \c run() function must be called with \c true parameter
85.734 + /// before using this function.
85.735 + bool kuratowski(const Edge& edge) const {
85.736 + return _kuratowski[edge];
85.737 + }
85.738 +
85.739 + private:
85.740 +
85.741 + void createChildLists(const TreeMap& tree_map, const OrderMap& order_map,
85.742 + const LowMap& low_map, ChildLists& child_lists) {
85.743 +
85.744 + for (NodeIt n(_graph); n != INVALID; ++n) {
85.745 + Node source = n;
85.746 +
85.747 + std::vector<Node> targets;
85.748 + for (OutArcIt e(_graph, n); e != INVALID; ++e) {
85.749 + Node target = _graph.target(e);
85.750 +
85.751 + if (order_map[source] < order_map[target] && tree_map[e]) {
85.752 + targets.push_back(target);
85.753 + }
85.754 + }
85.755 +
85.756 + if (targets.size() == 0) {
85.757 + child_lists[source].first = INVALID;
85.758 + } else if (targets.size() == 1) {
85.759 + child_lists[source].first = targets[0];
85.760 + child_lists[targets[0]].prev = INVALID;
85.761 + child_lists[targets[0]].next = INVALID;
85.762 + } else {
85.763 + radixSort(targets.begin(), targets.end(), mapToFunctor(low_map));
85.764 + for (int i = 1; i < int(targets.size()); ++i) {
85.765 + child_lists[targets[i]].prev = targets[i - 1];
85.766 + child_lists[targets[i - 1]].next = targets[i];
85.767 + }
85.768 + child_lists[targets.back()].next = INVALID;
85.769 + child_lists[targets.front()].prev = INVALID;
85.770 + child_lists[source].first = targets.front();
85.771 + }
85.772 + }
85.773 + }
85.774 +
85.775 + void walkUp(const Node& node, Node root, int rorder,
85.776 + const PredMap& pred_map, const LowMap& low_map,
85.777 + const OrderMap& order_map, const OrderList& order_list,
85.778 + NodeData& node_data, MergeRoots& merge_roots) {
85.779 +
85.780 + int na, nb;
85.781 + bool da, db;
85.782 +
85.783 + na = nb = order_map[node];
85.784 + da = true; db = false;
85.785 +
85.786 + while (true) {
85.787 +
85.788 + if (node_data[na].visited == rorder) break;
85.789 + if (node_data[nb].visited == rorder) break;
85.790 +
85.791 + node_data[na].visited = rorder;
85.792 + node_data[nb].visited = rorder;
85.793 +
85.794 + int rn = -1;
85.795 +
85.796 + if (na >= int(order_list.size())) {
85.797 + rn = na;
85.798 + } else if (nb >= int(order_list.size())) {
85.799 + rn = nb;
85.800 + }
85.801 +
85.802 + if (rn == -1) {
85.803 + int nn;
85.804 +
85.805 + nn = da ? node_data[na].prev : node_data[na].next;
85.806 + da = node_data[nn].prev != na;
85.807 + na = nn;
85.808 +
85.809 + nn = db ? node_data[nb].prev : node_data[nb].next;
85.810 + db = node_data[nn].prev != nb;
85.811 + nb = nn;
85.812 +
85.813 + } else {
85.814 +
85.815 + Node rep = order_list[rn - order_list.size()];
85.816 + Node parent = _graph.source(pred_map[rep]);
85.817 +
85.818 + if (low_map[rep] < rorder) {
85.819 + merge_roots[parent].push_back(rn);
85.820 + } else {
85.821 + merge_roots[parent].push_front(rn);
85.822 + }
85.823 +
85.824 + if (parent != root) {
85.825 + na = nb = order_map[parent];
85.826 + da = true; db = false;
85.827 + } else {
85.828 + break;
85.829 + }
85.830 + }
85.831 + }
85.832 + }
85.833 +
85.834 + void walkDown(int rn, int rorder, NodeData& node_data,
85.835 + ArcLists& arc_lists, FlipMap& flip_map,
85.836 + OrderList& order_list, ChildLists& child_lists,
85.837 + AncestorMap& ancestor_map, LowMap& low_map,
85.838 + EmbedArc& embed_arc, MergeRoots& merge_roots) {
85.839 +
85.840 + std::vector<std::pair<int, bool> > merge_stack;
85.841 +
85.842 + for (int di = 0; di < 2; ++di) {
85.843 + bool rd = di == 0;
85.844 + int pn = rn;
85.845 + int n = rd ? node_data[rn].next : node_data[rn].prev;
85.846 +
85.847 + while (n != rn) {
85.848 +
85.849 + Node node = order_list[n];
85.850 +
85.851 + if (embed_arc[node] != INVALID) {
85.852 +
85.853 + // Merging components on the critical path
85.854 + while (!merge_stack.empty()) {
85.855 +
85.856 + // Component root
85.857 + int cn = merge_stack.back().first;
85.858 + bool cd = merge_stack.back().second;
85.859 + merge_stack.pop_back();
85.860 +
85.861 + // Parent of component
85.862 + int dn = merge_stack.back().first;
85.863 + bool dd = merge_stack.back().second;
85.864 + merge_stack.pop_back();
85.865 +
85.866 + Node parent = order_list[dn];
85.867 +
85.868 + // Erasing from merge_roots
85.869 + merge_roots[parent].pop_front();
85.870 +
85.871 + Node child = order_list[cn - order_list.size()];
85.872 +
85.873 + // Erasing from child_lists
85.874 + if (child_lists[child].prev != INVALID) {
85.875 + child_lists[child_lists[child].prev].next =
85.876 + child_lists[child].next;
85.877 + } else {
85.878 + child_lists[parent].first = child_lists[child].next;
85.879 + }
85.880 +
85.881 + if (child_lists[child].next != INVALID) {
85.882 + child_lists[child_lists[child].next].prev =
85.883 + child_lists[child].prev;
85.884 + }
85.885 +
85.886 + // Merging arcs + flipping
85.887 + Arc de = node_data[dn].first;
85.888 + Arc ce = node_data[cn].first;
85.889 +
85.890 + flip_map[order_list[cn - order_list.size()]] = cd != dd;
85.891 + if (cd != dd) {
85.892 + std::swap(arc_lists[ce].prev, arc_lists[ce].next);
85.893 + ce = arc_lists[ce].prev;
85.894 + std::swap(arc_lists[ce].prev, arc_lists[ce].next);
85.895 + }
85.896 +
85.897 + {
85.898 + Arc dne = arc_lists[de].next;
85.899 + Arc cne = arc_lists[ce].next;
85.900 +
85.901 + arc_lists[de].next = cne;
85.902 + arc_lists[ce].next = dne;
85.903 +
85.904 + arc_lists[dne].prev = ce;
85.905 + arc_lists[cne].prev = de;
85.906 + }
85.907 +
85.908 + if (dd) {
85.909 + node_data[dn].first = ce;
85.910 + }
85.911 +
85.912 + // Merging external faces
85.913 + {
85.914 + int en = cn;
85.915 + cn = cd ? node_data[cn].prev : node_data[cn].next;
85.916 + cd = node_data[cn].next == en;
85.917 +
85.918 + if (node_data[cn].prev == node_data[cn].next &&
85.919 + node_data[cn].inverted) {
85.920 + cd = !cd;
85.921 + }
85.922 + }
85.923 +
85.924 + if (cd) node_data[cn].next = dn; else node_data[cn].prev = dn;
85.925 + if (dd) node_data[dn].prev = cn; else node_data[dn].next = cn;
85.926 +
85.927 + }
85.928 +
85.929 + bool d = pn == node_data[n].prev;
85.930 +
85.931 + if (node_data[n].prev == node_data[n].next &&
85.932 + node_data[n].inverted) {
85.933 + d = !d;
85.934 + }
85.935 +
85.936 + // Add new arc
85.937 + {
85.938 + Arc arc = embed_arc[node];
85.939 + Arc re = node_data[rn].first;
85.940 +
85.941 + arc_lists[arc_lists[re].next].prev = arc;
85.942 + arc_lists[arc].next = arc_lists[re].next;
85.943 + arc_lists[arc].prev = re;
85.944 + arc_lists[re].next = arc;
85.945 +
85.946 + if (!rd) {
85.947 + node_data[rn].first = arc;
85.948 + }
85.949 +
85.950 + Arc rev = _graph.oppositeArc(arc);
85.951 + Arc e = node_data[n].first;
85.952 +
85.953 + arc_lists[arc_lists[e].next].prev = rev;
85.954 + arc_lists[rev].next = arc_lists[e].next;
85.955 + arc_lists[rev].prev = e;
85.956 + arc_lists[e].next = rev;
85.957 +
85.958 + if (d) {
85.959 + node_data[n].first = rev;
85.960 + }
85.961 +
85.962 + }
85.963 +
85.964 + // Embedding arc into external face
85.965 + if (rd) node_data[rn].next = n; else node_data[rn].prev = n;
85.966 + if (d) node_data[n].prev = rn; else node_data[n].next = rn;
85.967 + pn = rn;
85.968 +
85.969 + embed_arc[order_list[n]] = INVALID;
85.970 + }
85.971 +
85.972 + if (!merge_roots[node].empty()) {
85.973 +
85.974 + bool d = pn == node_data[n].prev;
85.975 + if (node_data[n].prev == node_data[n].next &&
85.976 + node_data[n].inverted) {
85.977 + d = !d;
85.978 + }
85.979 +
85.980 + merge_stack.push_back(std::make_pair(n, d));
85.981 +
85.982 + int rn = merge_roots[node].front();
85.983 +
85.984 + int xn = node_data[rn].next;
85.985 + Node xnode = order_list[xn];
85.986 +
85.987 + int yn = node_data[rn].prev;
85.988 + Node ynode = order_list[yn];
85.989 +
85.990 + bool rd;
85.991 + if (!external(xnode, rorder, child_lists, ancestor_map, low_map)) {
85.992 + rd = true;
85.993 + } else if (!external(ynode, rorder, child_lists,
85.994 + ancestor_map, low_map)) {
85.995 + rd = false;
85.996 + } else if (pertinent(xnode, embed_arc, merge_roots)) {
85.997 + rd = true;
85.998 + } else {
85.999 + rd = false;
85.1000 + }
85.1001 +
85.1002 + merge_stack.push_back(std::make_pair(rn, rd));
85.1003 +
85.1004 + pn = rn;
85.1005 + n = rd ? xn : yn;
85.1006 +
85.1007 + } else if (!external(node, rorder, child_lists,
85.1008 + ancestor_map, low_map)) {
85.1009 + int nn = (node_data[n].next != pn ?
85.1010 + node_data[n].next : node_data[n].prev);
85.1011 +
85.1012 + bool nd = n == node_data[nn].prev;
85.1013 +
85.1014 + if (nd) node_data[nn].prev = pn;
85.1015 + else node_data[nn].next = pn;
85.1016 +
85.1017 + if (n == node_data[pn].prev) node_data[pn].prev = nn;
85.1018 + else node_data[pn].next = nn;
85.1019 +
85.1020 + node_data[nn].inverted =
85.1021 + (node_data[nn].prev == node_data[nn].next && nd != rd);
85.1022 +
85.1023 + n = nn;
85.1024 + }
85.1025 + else break;
85.1026 +
85.1027 + }
85.1028 +
85.1029 + if (!merge_stack.empty() || n == rn) {
85.1030 + break;
85.1031 + }
85.1032 + }
85.1033 + }
85.1034 +
85.1035 + void initFace(const Node& node, ArcLists& arc_lists,
85.1036 + NodeData& node_data, const PredMap& pred_map,
85.1037 + const OrderMap& order_map, const OrderList& order_list) {
85.1038 + int n = order_map[node];
85.1039 + int rn = n + order_list.size();
85.1040 +
85.1041 + node_data[n].next = node_data[n].prev = rn;
85.1042 + node_data[rn].next = node_data[rn].prev = n;
85.1043 +
85.1044 + node_data[n].visited = order_list.size();
85.1045 + node_data[rn].visited = order_list.size();
85.1046 +
85.1047 + node_data[n].inverted = false;
85.1048 + node_data[rn].inverted = false;
85.1049 +
85.1050 + Arc arc = pred_map[node];
85.1051 + Arc rev = _graph.oppositeArc(arc);
85.1052 +
85.1053 + node_data[rn].first = arc;
85.1054 + node_data[n].first = rev;
85.1055 +
85.1056 + arc_lists[arc].prev = arc;
85.1057 + arc_lists[arc].next = arc;
85.1058 +
85.1059 + arc_lists[rev].prev = rev;
85.1060 + arc_lists[rev].next = rev;
85.1061 +
85.1062 + }
85.1063 +
85.1064 + void mergeRemainingFaces(const Node& node, NodeData& node_data,
85.1065 + OrderList& order_list, OrderMap& order_map,
85.1066 + ChildLists& child_lists, ArcLists& arc_lists) {
85.1067 + while (child_lists[node].first != INVALID) {
85.1068 + int dd = order_map[node];
85.1069 + Node child = child_lists[node].first;
85.1070 + int cd = order_map[child] + order_list.size();
85.1071 + child_lists[node].first = child_lists[child].next;
85.1072 +
85.1073 + Arc de = node_data[dd].first;
85.1074 + Arc ce = node_data[cd].first;
85.1075 +
85.1076 + if (de != INVALID) {
85.1077 + Arc dne = arc_lists[de].next;
85.1078 + Arc cne = arc_lists[ce].next;
85.1079 +
85.1080 + arc_lists[de].next = cne;
85.1081 + arc_lists[ce].next = dne;
85.1082 +
85.1083 + arc_lists[dne].prev = ce;
85.1084 + arc_lists[cne].prev = de;
85.1085 + }
85.1086 +
85.1087 + node_data[dd].first = ce;
85.1088 +
85.1089 + }
85.1090 + }
85.1091 +
85.1092 + void storeEmbedding(const Node& node, NodeData& node_data,
85.1093 + OrderMap& order_map, PredMap& pred_map,
85.1094 + ArcLists& arc_lists, FlipMap& flip_map) {
85.1095 +
85.1096 + if (node_data[order_map[node]].first == INVALID) return;
85.1097 +
85.1098 + if (pred_map[node] != INVALID) {
85.1099 + Node source = _graph.source(pred_map[node]);
85.1100 + flip_map[node] = flip_map[node] != flip_map[source];
85.1101 + }
85.1102 +
85.1103 + Arc first = node_data[order_map[node]].first;
85.1104 + Arc prev = first;
85.1105 +
85.1106 + Arc arc = flip_map[node] ?
85.1107 + arc_lists[prev].prev : arc_lists[prev].next;
85.1108 +
85.1109 + _embedding[prev] = arc;
85.1110 +
85.1111 + while (arc != first) {
85.1112 + Arc next = arc_lists[arc].prev == prev ?
85.1113 + arc_lists[arc].next : arc_lists[arc].prev;
85.1114 + prev = arc; arc = next;
85.1115 + _embedding[prev] = arc;
85.1116 + }
85.1117 + }
85.1118 +
85.1119 +
85.1120 + bool external(const Node& node, int rorder,
85.1121 + ChildLists& child_lists, AncestorMap& ancestor_map,
85.1122 + LowMap& low_map) {
85.1123 + Node child = child_lists[node].first;
85.1124 +
85.1125 + if (child != INVALID) {
85.1126 + if (low_map[child] < rorder) return true;
85.1127 + }
85.1128 +
85.1129 + if (ancestor_map[node] < rorder) return true;
85.1130 +
85.1131 + return false;
85.1132 + }
85.1133 +
85.1134 + bool pertinent(const Node& node, const EmbedArc& embed_arc,
85.1135 + const MergeRoots& merge_roots) {
85.1136 + return !merge_roots[node].empty() || embed_arc[node] != INVALID;
85.1137 + }
85.1138 +
85.1139 + int lowPoint(const Node& node, OrderMap& order_map, ChildLists& child_lists,
85.1140 + AncestorMap& ancestor_map, LowMap& low_map) {
85.1141 + int low_point;
85.1142 +
85.1143 + Node child = child_lists[node].first;
85.1144 +
85.1145 + if (child != INVALID) {
85.1146 + low_point = low_map[child];
85.1147 + } else {
85.1148 + low_point = order_map[node];
85.1149 + }
85.1150 +
85.1151 + if (low_point > ancestor_map[node]) {
85.1152 + low_point = ancestor_map[node];
85.1153 + }
85.1154 +
85.1155 + return low_point;
85.1156 + }
85.1157 +
85.1158 + int findComponentRoot(Node root, Node node, ChildLists& child_lists,
85.1159 + OrderMap& order_map, OrderList& order_list) {
85.1160 +
85.1161 + int order = order_map[root];
85.1162 + int norder = order_map[node];
85.1163 +
85.1164 + Node child = child_lists[root].first;
85.1165 + while (child != INVALID) {
85.1166 + int corder = order_map[child];
85.1167 + if (corder > order && corder < norder) {
85.1168 + order = corder;
85.1169 + }
85.1170 + child = child_lists[child].next;
85.1171 + }
85.1172 + return order + order_list.size();
85.1173 + }
85.1174 +
85.1175 + Node findPertinent(Node node, OrderMap& order_map, NodeData& node_data,
85.1176 + EmbedArc& embed_arc, MergeRoots& merge_roots) {
85.1177 + Node wnode =_graph.target(node_data[order_map[node]].first);
85.1178 + while (!pertinent(wnode, embed_arc, merge_roots)) {
85.1179 + wnode = _graph.target(node_data[order_map[wnode]].first);
85.1180 + }
85.1181 + return wnode;
85.1182 + }
85.1183 +
85.1184 +
85.1185 + Node findExternal(Node node, int rorder, OrderMap& order_map,
85.1186 + ChildLists& child_lists, AncestorMap& ancestor_map,
85.1187 + LowMap& low_map, NodeData& node_data) {
85.1188 + Node wnode =_graph.target(node_data[order_map[node]].first);
85.1189 + while (!external(wnode, rorder, child_lists, ancestor_map, low_map)) {
85.1190 + wnode = _graph.target(node_data[order_map[wnode]].first);
85.1191 + }
85.1192 + return wnode;
85.1193 + }
85.1194 +
85.1195 + void markCommonPath(Node node, int rorder, Node& wnode, Node& znode,
85.1196 + OrderList& order_list, OrderMap& order_map,
85.1197 + NodeData& node_data, ArcLists& arc_lists,
85.1198 + EmbedArc& embed_arc, MergeRoots& merge_roots,
85.1199 + ChildLists& child_lists, AncestorMap& ancestor_map,
85.1200 + LowMap& low_map) {
85.1201 +
85.1202 + Node cnode = node;
85.1203 + Node pred = INVALID;
85.1204 +
85.1205 + while (true) {
85.1206 +
85.1207 + bool pert = pertinent(cnode, embed_arc, merge_roots);
85.1208 + bool ext = external(cnode, rorder, child_lists, ancestor_map, low_map);
85.1209 +
85.1210 + if (pert && ext) {
85.1211 + if (!merge_roots[cnode].empty()) {
85.1212 + int cn = merge_roots[cnode].back();
85.1213 +
85.1214 + if (low_map[order_list[cn - order_list.size()]] < rorder) {
85.1215 + Arc arc = node_data[cn].first;
85.1216 + _kuratowski.set(arc, true);
85.1217 +
85.1218 + pred = cnode;
85.1219 + cnode = _graph.target(arc);
85.1220 +
85.1221 + continue;
85.1222 + }
85.1223 + }
85.1224 + wnode = znode = cnode;
85.1225 + return;
85.1226 +
85.1227 + } else if (pert) {
85.1228 + wnode = cnode;
85.1229 +
85.1230 + while (!external(cnode, rorder, child_lists, ancestor_map, low_map)) {
85.1231 + Arc arc = node_data[order_map[cnode]].first;
85.1232 +
85.1233 + if (_graph.target(arc) == pred) {
85.1234 + arc = arc_lists[arc].next;
85.1235 + }
85.1236 + _kuratowski.set(arc, true);
85.1237 +
85.1238 + Node next = _graph.target(arc);
85.1239 + pred = cnode; cnode = next;
85.1240 + }
85.1241 +
85.1242 + znode = cnode;
85.1243 + return;
85.1244 +
85.1245 + } else if (ext) {
85.1246 + znode = cnode;
85.1247 +
85.1248 + while (!pertinent(cnode, embed_arc, merge_roots)) {
85.1249 + Arc arc = node_data[order_map[cnode]].first;
85.1250 +
85.1251 + if (_graph.target(arc) == pred) {
85.1252 + arc = arc_lists[arc].next;
85.1253 + }
85.1254 + _kuratowski.set(arc, true);
85.1255 +
85.1256 + Node next = _graph.target(arc);
85.1257 + pred = cnode; cnode = next;
85.1258 + }
85.1259 +
85.1260 + wnode = cnode;
85.1261 + return;
85.1262 +
85.1263 + } else {
85.1264 + Arc arc = node_data[order_map[cnode]].first;
85.1265 +
85.1266 + if (_graph.target(arc) == pred) {
85.1267 + arc = arc_lists[arc].next;
85.1268 + }
85.1269 + _kuratowski.set(arc, true);
85.1270 +
85.1271 + Node next = _graph.target(arc);
85.1272 + pred = cnode; cnode = next;
85.1273 + }
85.1274 +
85.1275 + }
85.1276 +
85.1277 + }
85.1278 +
85.1279 + void orientComponent(Node root, int rn, OrderMap& order_map,
85.1280 + PredMap& pred_map, NodeData& node_data,
85.1281 + ArcLists& arc_lists, FlipMap& flip_map,
85.1282 + TypeMap& type_map) {
85.1283 + node_data[order_map[root]].first = node_data[rn].first;
85.1284 + type_map[root] = 1;
85.1285 +
85.1286 + std::vector<Node> st, qu;
85.1287 +
85.1288 + st.push_back(root);
85.1289 + while (!st.empty()) {
85.1290 + Node node = st.back();
85.1291 + st.pop_back();
85.1292 + qu.push_back(node);
85.1293 +
85.1294 + Arc arc = node_data[order_map[node]].first;
85.1295 +
85.1296 + if (type_map[_graph.target(arc)] == 0) {
85.1297 + st.push_back(_graph.target(arc));
85.1298 + type_map[_graph.target(arc)] = 1;
85.1299 + }
85.1300 +
85.1301 + Arc last = arc, pred = arc;
85.1302 + arc = arc_lists[arc].next;
85.1303 + while (arc != last) {
85.1304 +
85.1305 + if (type_map[_graph.target(arc)] == 0) {
85.1306 + st.push_back(_graph.target(arc));
85.1307 + type_map[_graph.target(arc)] = 1;
85.1308 + }
85.1309 +
85.1310 + Arc next = arc_lists[arc].next != pred ?
85.1311 + arc_lists[arc].next : arc_lists[arc].prev;
85.1312 + pred = arc; arc = next;
85.1313 + }
85.1314 +
85.1315 + }
85.1316 +
85.1317 + type_map[root] = 2;
85.1318 + flip_map[root] = false;
85.1319 +
85.1320 + for (int i = 1; i < int(qu.size()); ++i) {
85.1321 +
85.1322 + Node node = qu[i];
85.1323 +
85.1324 + while (type_map[node] != 2) {
85.1325 + st.push_back(node);
85.1326 + type_map[node] = 2;
85.1327 + node = _graph.source(pred_map[node]);
85.1328 + }
85.1329 +
85.1330 + bool flip = flip_map[node];
85.1331 +
85.1332 + while (!st.empty()) {
85.1333 + node = st.back();
85.1334 + st.pop_back();
85.1335 +
85.1336 + flip_map[node] = flip != flip_map[node];
85.1337 + flip = flip_map[node];
85.1338 +
85.1339 + if (flip) {
85.1340 + Arc arc = node_data[order_map[node]].first;
85.1341 + std::swap(arc_lists[arc].prev, arc_lists[arc].next);
85.1342 + arc = arc_lists[arc].prev;
85.1343 + std::swap(arc_lists[arc].prev, arc_lists[arc].next);
85.1344 + node_data[order_map[node]].first = arc;
85.1345 + }
85.1346 + }
85.1347 + }
85.1348 +
85.1349 + for (int i = 0; i < int(qu.size()); ++i) {
85.1350 +
85.1351 + Arc arc = node_data[order_map[qu[i]]].first;
85.1352 + Arc last = arc, pred = arc;
85.1353 +
85.1354 + arc = arc_lists[arc].next;
85.1355 + while (arc != last) {
85.1356 +
85.1357 + if (arc_lists[arc].next == pred) {
85.1358 + std::swap(arc_lists[arc].next, arc_lists[arc].prev);
85.1359 + }
85.1360 + pred = arc; arc = arc_lists[arc].next;
85.1361 + }
85.1362 +
85.1363 + }
85.1364 + }
85.1365 +
85.1366 + void setFaceFlags(Node root, Node wnode, Node ynode, Node xnode,
85.1367 + OrderMap& order_map, NodeData& node_data,
85.1368 + TypeMap& type_map) {
85.1369 + Node node = _graph.target(node_data[order_map[root]].first);
85.1370 +
85.1371 + while (node != ynode) {
85.1372 + type_map[node] = HIGHY;
85.1373 + node = _graph.target(node_data[order_map[node]].first);
85.1374 + }
85.1375 +
85.1376 + while (node != wnode) {
85.1377 + type_map[node] = LOWY;
85.1378 + node = _graph.target(node_data[order_map[node]].first);
85.1379 + }
85.1380 +
85.1381 + node = _graph.target(node_data[order_map[wnode]].first);
85.1382 +
85.1383 + while (node != xnode) {
85.1384 + type_map[node] = LOWX;
85.1385 + node = _graph.target(node_data[order_map[node]].first);
85.1386 + }
85.1387 + type_map[node] = LOWX;
85.1388 +
85.1389 + node = _graph.target(node_data[order_map[xnode]].first);
85.1390 + while (node != root) {
85.1391 + type_map[node] = HIGHX;
85.1392 + node = _graph.target(node_data[order_map[node]].first);
85.1393 + }
85.1394 +
85.1395 + type_map[wnode] = PERTINENT;
85.1396 + type_map[root] = ROOT;
85.1397 + }
85.1398 +
85.1399 + void findInternalPath(std::vector<Arc>& ipath,
85.1400 + Node wnode, Node root, TypeMap& type_map,
85.1401 + OrderMap& order_map, NodeData& node_data,
85.1402 + ArcLists& arc_lists) {
85.1403 + std::vector<Arc> st;
85.1404 +
85.1405 + Node node = wnode;
85.1406 +
85.1407 + while (node != root) {
85.1408 + Arc arc = arc_lists[node_data[order_map[node]].first].next;
85.1409 + st.push_back(arc);
85.1410 + node = _graph.target(arc);
85.1411 + }
85.1412 +
85.1413 + while (true) {
85.1414 + Arc arc = st.back();
85.1415 + if (type_map[_graph.target(arc)] == LOWX ||
85.1416 + type_map[_graph.target(arc)] == HIGHX) {
85.1417 + break;
85.1418 + }
85.1419 + if (type_map[_graph.target(arc)] == 2) {
85.1420 + type_map[_graph.target(arc)] = 3;
85.1421 +
85.1422 + arc = arc_lists[_graph.oppositeArc(arc)].next;
85.1423 + st.push_back(arc);
85.1424 + } else {
85.1425 + st.pop_back();
85.1426 + arc = arc_lists[arc].next;
85.1427 +
85.1428 + while (_graph.oppositeArc(arc) == st.back()) {
85.1429 + arc = st.back();
85.1430 + st.pop_back();
85.1431 + arc = arc_lists[arc].next;
85.1432 + }
85.1433 + st.push_back(arc);
85.1434 + }
85.1435 + }
85.1436 +
85.1437 + for (int i = 0; i < int(st.size()); ++i) {
85.1438 + if (type_map[_graph.target(st[i])] != LOWY &&
85.1439 + type_map[_graph.target(st[i])] != HIGHY) {
85.1440 + for (; i < int(st.size()); ++i) {
85.1441 + ipath.push_back(st[i]);
85.1442 + }
85.1443 + }
85.1444 + }
85.1445 + }
85.1446 +
85.1447 + void setInternalFlags(std::vector<Arc>& ipath, TypeMap& type_map) {
85.1448 + for (int i = 1; i < int(ipath.size()); ++i) {
85.1449 + type_map[_graph.source(ipath[i])] = INTERNAL;
85.1450 + }
85.1451 + }
85.1452 +
85.1453 + void findPilePath(std::vector<Arc>& ppath,
85.1454 + Node root, TypeMap& type_map, OrderMap& order_map,
85.1455 + NodeData& node_data, ArcLists& arc_lists) {
85.1456 + std::vector<Arc> st;
85.1457 +
85.1458 + st.push_back(_graph.oppositeArc(node_data[order_map[root]].first));
85.1459 + st.push_back(node_data[order_map[root]].first);
85.1460 +
85.1461 + while (st.size() > 1) {
85.1462 + Arc arc = st.back();
85.1463 + if (type_map[_graph.target(arc)] == INTERNAL) {
85.1464 + break;
85.1465 + }
85.1466 + if (type_map[_graph.target(arc)] == 3) {
85.1467 + type_map[_graph.target(arc)] = 4;
85.1468 +
85.1469 + arc = arc_lists[_graph.oppositeArc(arc)].next;
85.1470 + st.push_back(arc);
85.1471 + } else {
85.1472 + st.pop_back();
85.1473 + arc = arc_lists[arc].next;
85.1474 +
85.1475 + while (!st.empty() && _graph.oppositeArc(arc) == st.back()) {
85.1476 + arc = st.back();
85.1477 + st.pop_back();
85.1478 + arc = arc_lists[arc].next;
85.1479 + }
85.1480 + st.push_back(arc);
85.1481 + }
85.1482 + }
85.1483 +
85.1484 + for (int i = 1; i < int(st.size()); ++i) {
85.1485 + ppath.push_back(st[i]);
85.1486 + }
85.1487 + }
85.1488 +
85.1489 +
85.1490 + int markExternalPath(Node node, OrderMap& order_map,
85.1491 + ChildLists& child_lists, PredMap& pred_map,
85.1492 + AncestorMap& ancestor_map, LowMap& low_map) {
85.1493 + int lp = lowPoint(node, order_map, child_lists,
85.1494 + ancestor_map, low_map);
85.1495 +
85.1496 + if (ancestor_map[node] != lp) {
85.1497 + node = child_lists[node].first;
85.1498 + _kuratowski[pred_map[node]] = true;
85.1499 +
85.1500 + while (ancestor_map[node] != lp) {
85.1501 + for (OutArcIt e(_graph, node); e != INVALID; ++e) {
85.1502 + Node tnode = _graph.target(e);
85.1503 + if (order_map[tnode] > order_map[node] && low_map[tnode] == lp) {
85.1504 + node = tnode;
85.1505 + _kuratowski[e] = true;
85.1506 + break;
85.1507 + }
85.1508 + }
85.1509 + }
85.1510 + }
85.1511 +
85.1512 + for (OutArcIt e(_graph, node); e != INVALID; ++e) {
85.1513 + if (order_map[_graph.target(e)] == lp) {
85.1514 + _kuratowski[e] = true;
85.1515 + break;
85.1516 + }
85.1517 + }
85.1518 +
85.1519 + return lp;
85.1520 + }
85.1521 +
85.1522 + void markPertinentPath(Node node, OrderMap& order_map,
85.1523 + NodeData& node_data, ArcLists& arc_lists,
85.1524 + EmbedArc& embed_arc, MergeRoots& merge_roots) {
85.1525 + while (embed_arc[node] == INVALID) {
85.1526 + int n = merge_roots[node].front();
85.1527 + Arc arc = node_data[n].first;
85.1528 +
85.1529 + _kuratowski.set(arc, true);
85.1530 +
85.1531 + Node pred = node;
85.1532 + node = _graph.target(arc);
85.1533 + while (!pertinent(node, embed_arc, merge_roots)) {
85.1534 + arc = node_data[order_map[node]].first;
85.1535 + if (_graph.target(arc) == pred) {
85.1536 + arc = arc_lists[arc].next;
85.1537 + }
85.1538 + _kuratowski.set(arc, true);
85.1539 + pred = node;
85.1540 + node = _graph.target(arc);
85.1541 + }
85.1542 + }
85.1543 + _kuratowski.set(embed_arc[node], true);
85.1544 + }
85.1545 +
85.1546 + void markPredPath(Node node, Node snode, PredMap& pred_map) {
85.1547 + while (node != snode) {
85.1548 + _kuratowski.set(pred_map[node], true);
85.1549 + node = _graph.source(pred_map[node]);
85.1550 + }
85.1551 + }
85.1552 +
85.1553 + void markFacePath(Node ynode, Node xnode,
85.1554 + OrderMap& order_map, NodeData& node_data) {
85.1555 + Arc arc = node_data[order_map[ynode]].first;
85.1556 + Node node = _graph.target(arc);
85.1557 + _kuratowski.set(arc, true);
85.1558 +
85.1559 + while (node != xnode) {
85.1560 + arc = node_data[order_map[node]].first;
85.1561 + _kuratowski.set(arc, true);
85.1562 + node = _graph.target(arc);
85.1563 + }
85.1564 + }
85.1565 +
85.1566 + void markInternalPath(std::vector<Arc>& path) {
85.1567 + for (int i = 0; i < int(path.size()); ++i) {
85.1568 + _kuratowski.set(path[i], true);
85.1569 + }
85.1570 + }
85.1571 +
85.1572 + void markPilePath(std::vector<Arc>& path) {
85.1573 + for (int i = 0; i < int(path.size()); ++i) {
85.1574 + _kuratowski.set(path[i], true);
85.1575 + }
85.1576 + }
85.1577 +
85.1578 + void isolateKuratowski(Arc arc, NodeData& node_data,
85.1579 + ArcLists& arc_lists, FlipMap& flip_map,
85.1580 + OrderMap& order_map, OrderList& order_list,
85.1581 + PredMap& pred_map, ChildLists& child_lists,
85.1582 + AncestorMap& ancestor_map, LowMap& low_map,
85.1583 + EmbedArc& embed_arc, MergeRoots& merge_roots) {
85.1584 +
85.1585 + Node root = _graph.source(arc);
85.1586 + Node enode = _graph.target(arc);
85.1587 +
85.1588 + int rorder = order_map[root];
85.1589 +
85.1590 + TypeMap type_map(_graph, 0);
85.1591 +
85.1592 + int rn = findComponentRoot(root, enode, child_lists,
85.1593 + order_map, order_list);
85.1594 +
85.1595 + Node xnode = order_list[node_data[rn].next];
85.1596 + Node ynode = order_list[node_data[rn].prev];
85.1597 +
85.1598 + // Minor-A
85.1599 + {
85.1600 + while (!merge_roots[xnode].empty() || !merge_roots[ynode].empty()) {
85.1601 +
85.1602 + if (!merge_roots[xnode].empty()) {
85.1603 + root = xnode;
85.1604 + rn = merge_roots[xnode].front();
85.1605 + } else {
85.1606 + root = ynode;
85.1607 + rn = merge_roots[ynode].front();
85.1608 + }
85.1609 +
85.1610 + xnode = order_list[node_data[rn].next];
85.1611 + ynode = order_list[node_data[rn].prev];
85.1612 + }
85.1613 +
85.1614 + if (root != _graph.source(arc)) {
85.1615 + orientComponent(root, rn, order_map, pred_map,
85.1616 + node_data, arc_lists, flip_map, type_map);
85.1617 + markFacePath(root, root, order_map, node_data);
85.1618 + int xlp = markExternalPath(xnode, order_map, child_lists,
85.1619 + pred_map, ancestor_map, low_map);
85.1620 + int ylp = markExternalPath(ynode, order_map, child_lists,
85.1621 + pred_map, ancestor_map, low_map);
85.1622 + markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
85.1623 + Node lwnode = findPertinent(ynode, order_map, node_data,
85.1624 + embed_arc, merge_roots);
85.1625 +
85.1626 + markPertinentPath(lwnode, order_map, node_data, arc_lists,
85.1627 + embed_arc, merge_roots);
85.1628 +
85.1629 + return;
85.1630 + }
85.1631 + }
85.1632 +
85.1633 + orientComponent(root, rn, order_map, pred_map,
85.1634 + node_data, arc_lists, flip_map, type_map);
85.1635 +
85.1636 + Node wnode = findPertinent(ynode, order_map, node_data,
85.1637 + embed_arc, merge_roots);
85.1638 + setFaceFlags(root, wnode, ynode, xnode, order_map, node_data, type_map);
85.1639 +
85.1640 +
85.1641 + //Minor-B
85.1642 + if (!merge_roots[wnode].empty()) {
85.1643 + int cn = merge_roots[wnode].back();
85.1644 + Node rep = order_list[cn - order_list.size()];
85.1645 + if (low_map[rep] < rorder) {
85.1646 + markFacePath(root, root, order_map, node_data);
85.1647 + int xlp = markExternalPath(xnode, order_map, child_lists,
85.1648 + pred_map, ancestor_map, low_map);
85.1649 + int ylp = markExternalPath(ynode, order_map, child_lists,
85.1650 + pred_map, ancestor_map, low_map);
85.1651 +
85.1652 + Node lwnode, lznode;
85.1653 + markCommonPath(wnode, rorder, lwnode, lznode, order_list,
85.1654 + order_map, node_data, arc_lists, embed_arc,
85.1655 + merge_roots, child_lists, ancestor_map, low_map);
85.1656 +
85.1657 + markPertinentPath(lwnode, order_map, node_data, arc_lists,
85.1658 + embed_arc, merge_roots);
85.1659 + int zlp = markExternalPath(lznode, order_map, child_lists,
85.1660 + pred_map, ancestor_map, low_map);
85.1661 +
85.1662 + int minlp = xlp < ylp ? xlp : ylp;
85.1663 + if (zlp < minlp) minlp = zlp;
85.1664 +
85.1665 + int maxlp = xlp > ylp ? xlp : ylp;
85.1666 + if (zlp > maxlp) maxlp = zlp;
85.1667 +
85.1668 + markPredPath(order_list[maxlp], order_list[minlp], pred_map);
85.1669 +
85.1670 + return;
85.1671 + }
85.1672 + }
85.1673 +
85.1674 + Node pxnode, pynode;
85.1675 + std::vector<Arc> ipath;
85.1676 + findInternalPath(ipath, wnode, root, type_map, order_map,
85.1677 + node_data, arc_lists);
85.1678 + setInternalFlags(ipath, type_map);
85.1679 + pynode = _graph.source(ipath.front());
85.1680 + pxnode = _graph.target(ipath.back());
85.1681 +
85.1682 + wnode = findPertinent(pynode, order_map, node_data,
85.1683 + embed_arc, merge_roots);
85.1684 +
85.1685 + // Minor-C
85.1686 + {
85.1687 + if (type_map[_graph.source(ipath.front())] == HIGHY) {
85.1688 + if (type_map[_graph.target(ipath.back())] == HIGHX) {
85.1689 + markFacePath(xnode, pxnode, order_map, node_data);
85.1690 + }
85.1691 + markFacePath(root, xnode, order_map, node_data);
85.1692 + markPertinentPath(wnode, order_map, node_data, arc_lists,
85.1693 + embed_arc, merge_roots);
85.1694 + markInternalPath(ipath);
85.1695 + int xlp = markExternalPath(xnode, order_map, child_lists,
85.1696 + pred_map, ancestor_map, low_map);
85.1697 + int ylp = markExternalPath(ynode, order_map, child_lists,
85.1698 + pred_map, ancestor_map, low_map);
85.1699 + markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
85.1700 + return;
85.1701 + }
85.1702 +
85.1703 + if (type_map[_graph.target(ipath.back())] == HIGHX) {
85.1704 + markFacePath(ynode, root, order_map, node_data);
85.1705 + markPertinentPath(wnode, order_map, node_data, arc_lists,
85.1706 + embed_arc, merge_roots);
85.1707 + markInternalPath(ipath);
85.1708 + int xlp = markExternalPath(xnode, order_map, child_lists,
85.1709 + pred_map, ancestor_map, low_map);
85.1710 + int ylp = markExternalPath(ynode, order_map, child_lists,
85.1711 + pred_map, ancestor_map, low_map);
85.1712 + markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
85.1713 + return;
85.1714 + }
85.1715 + }
85.1716 +
85.1717 + std::vector<Arc> ppath;
85.1718 + findPilePath(ppath, root, type_map, order_map, node_data, arc_lists);
85.1719 +
85.1720 + // Minor-D
85.1721 + if (!ppath.empty()) {
85.1722 + markFacePath(ynode, xnode, order_map, node_data);
85.1723 + markPertinentPath(wnode, order_map, node_data, arc_lists,
85.1724 + embed_arc, merge_roots);
85.1725 + markPilePath(ppath);
85.1726 + markInternalPath(ipath);
85.1727 + int xlp = markExternalPath(xnode, order_map, child_lists,
85.1728 + pred_map, ancestor_map, low_map);
85.1729 + int ylp = markExternalPath(ynode, order_map, child_lists,
85.1730 + pred_map, ancestor_map, low_map);
85.1731 + markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
85.1732 + return;
85.1733 + }
85.1734 +
85.1735 + // Minor-E*
85.1736 + {
85.1737 +
85.1738 + if (!external(wnode, rorder, child_lists, ancestor_map, low_map)) {
85.1739 + Node znode = findExternal(pynode, rorder, order_map,
85.1740 + child_lists, ancestor_map,
85.1741 + low_map, node_data);
85.1742 +
85.1743 + if (type_map[znode] == LOWY) {
85.1744 + markFacePath(root, xnode, order_map, node_data);
85.1745 + markPertinentPath(wnode, order_map, node_data, arc_lists,
85.1746 + embed_arc, merge_roots);
85.1747 + markInternalPath(ipath);
85.1748 + int xlp = markExternalPath(xnode, order_map, child_lists,
85.1749 + pred_map, ancestor_map, low_map);
85.1750 + int zlp = markExternalPath(znode, order_map, child_lists,
85.1751 + pred_map, ancestor_map, low_map);
85.1752 + markPredPath(root, order_list[xlp < zlp ? xlp : zlp], pred_map);
85.1753 + } else {
85.1754 + markFacePath(ynode, root, order_map, node_data);
85.1755 + markPertinentPath(wnode, order_map, node_data, arc_lists,
85.1756 + embed_arc, merge_roots);
85.1757 + markInternalPath(ipath);
85.1758 + int ylp = markExternalPath(ynode, order_map, child_lists,
85.1759 + pred_map, ancestor_map, low_map);
85.1760 + int zlp = markExternalPath(znode, order_map, child_lists,
85.1761 + pred_map, ancestor_map, low_map);
85.1762 + markPredPath(root, order_list[ylp < zlp ? ylp : zlp], pred_map);
85.1763 + }
85.1764 + return;
85.1765 + }
85.1766 +
85.1767 + int xlp = markExternalPath(xnode, order_map, child_lists,
85.1768 + pred_map, ancestor_map, low_map);
85.1769 + int ylp = markExternalPath(ynode, order_map, child_lists,
85.1770 + pred_map, ancestor_map, low_map);
85.1771 + int wlp = markExternalPath(wnode, order_map, child_lists,
85.1772 + pred_map, ancestor_map, low_map);
85.1773 +
85.1774 + if (wlp > xlp && wlp > ylp) {
85.1775 + markFacePath(root, root, order_map, node_data);
85.1776 + markPredPath(root, order_list[xlp < ylp ? xlp : ylp], pred_map);
85.1777 + return;
85.1778 + }
85.1779 +
85.1780 + markInternalPath(ipath);
85.1781 + markPertinentPath(wnode, order_map, node_data, arc_lists,
85.1782 + embed_arc, merge_roots);
85.1783 +
85.1784 + if (xlp > ylp && xlp > wlp) {
85.1785 + markFacePath(root, pynode, order_map, node_data);
85.1786 + markFacePath(wnode, xnode, order_map, node_data);
85.1787 + markPredPath(root, order_list[ylp < wlp ? ylp : wlp], pred_map);
85.1788 + return;
85.1789 + }
85.1790 +
85.1791 + if (ylp > xlp && ylp > wlp) {
85.1792 + markFacePath(pxnode, root, order_map, node_data);
85.1793 + markFacePath(ynode, wnode, order_map, node_data);
85.1794 + markPredPath(root, order_list[xlp < wlp ? xlp : wlp], pred_map);
85.1795 + return;
85.1796 + }
85.1797 +
85.1798 + if (pynode != ynode) {
85.1799 + markFacePath(pxnode, wnode, order_map, node_data);
85.1800 +
85.1801 + int minlp = xlp < ylp ? xlp : ylp;
85.1802 + if (wlp < minlp) minlp = wlp;
85.1803 +
85.1804 + int maxlp = xlp > ylp ? xlp : ylp;
85.1805 + if (wlp > maxlp) maxlp = wlp;
85.1806 +
85.1807 + markPredPath(order_list[maxlp], order_list[minlp], pred_map);
85.1808 + return;
85.1809 + }
85.1810 +
85.1811 + if (pxnode != xnode) {
85.1812 + markFacePath(wnode, pynode, order_map, node_data);
85.1813 +
85.1814 + int minlp = xlp < ylp ? xlp : ylp;
85.1815 + if (wlp < minlp) minlp = wlp;
85.1816 +
85.1817 + int maxlp = xlp > ylp ? xlp : ylp;
85.1818 + if (wlp > maxlp) maxlp = wlp;
85.1819 +
85.1820 + markPredPath(order_list[maxlp], order_list[minlp], pred_map);
85.1821 + return;
85.1822 + }
85.1823 +
85.1824 + markFacePath(root, root, order_map, node_data);
85.1825 + int minlp = xlp < ylp ? xlp : ylp;
85.1826 + if (wlp < minlp) minlp = wlp;
85.1827 + markPredPath(root, order_list[minlp], pred_map);
85.1828 + return;
85.1829 + }
85.1830 +
85.1831 + }
85.1832 +
85.1833 + };
85.1834 +
85.1835 + namespace _planarity_bits {
85.1836 +
85.1837 + template <typename Graph, typename EmbeddingMap>
85.1838 + void makeConnected(Graph& graph, EmbeddingMap& embedding) {
85.1839 + DfsVisitor<Graph> null_visitor;
85.1840 + DfsVisit<Graph, DfsVisitor<Graph> > dfs(graph, null_visitor);
85.1841 + dfs.init();
85.1842 +
85.1843 + typename Graph::Node u = INVALID;
85.1844 + for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
85.1845 + if (!dfs.reached(n)) {
85.1846 + dfs.addSource(n);
85.1847 + dfs.start();
85.1848 + if (u == INVALID) {
85.1849 + u = n;
85.1850 + } else {
85.1851 + typename Graph::Node v = n;
85.1852 +
85.1853 + typename Graph::Arc ue = typename Graph::OutArcIt(graph, u);
85.1854 + typename Graph::Arc ve = typename Graph::OutArcIt(graph, v);
85.1855 +
85.1856 + typename Graph::Arc e = graph.direct(graph.addEdge(u, v), true);
85.1857 +
85.1858 + if (ue != INVALID) {
85.1859 + embedding[e] = embedding[ue];
85.1860 + embedding[ue] = e;
85.1861 + } else {
85.1862 + embedding[e] = e;
85.1863 + }
85.1864 +
85.1865 + if (ve != INVALID) {
85.1866 + embedding[graph.oppositeArc(e)] = embedding[ve];
85.1867 + embedding[ve] = graph.oppositeArc(e);
85.1868 + } else {
85.1869 + embedding[graph.oppositeArc(e)] = graph.oppositeArc(e);
85.1870 + }
85.1871 + }
85.1872 + }
85.1873 + }
85.1874 + }
85.1875 +
85.1876 + template <typename Graph, typename EmbeddingMap>
85.1877 + void makeBiNodeConnected(Graph& graph, EmbeddingMap& embedding) {
85.1878 + typename Graph::template ArcMap<bool> processed(graph);
85.1879 +
85.1880 + std::vector<typename Graph::Arc> arcs;
85.1881 + for (typename Graph::ArcIt e(graph); e != INVALID; ++e) {
85.1882 + arcs.push_back(e);
85.1883 + }
85.1884 +
85.1885 + IterableBoolMap<Graph, typename Graph::Node> visited(graph, false);
85.1886 +
85.1887 + for (int i = 0; i < int(arcs.size()); ++i) {
85.1888 + typename Graph::Arc pp = arcs[i];
85.1889 + if (processed[pp]) continue;
85.1890 +
85.1891 + typename Graph::Arc e = embedding[graph.oppositeArc(pp)];
85.1892 + processed[e] = true;
85.1893 + visited.set(graph.source(e), true);
85.1894 +
85.1895 + typename Graph::Arc p = e, l = e;
85.1896 + e = embedding[graph.oppositeArc(e)];
85.1897 +
85.1898 + while (e != l) {
85.1899 + processed[e] = true;
85.1900 +
85.1901 + if (visited[graph.source(e)]) {
85.1902 +
85.1903 + typename Graph::Arc n =
85.1904 + graph.direct(graph.addEdge(graph.source(p),
85.1905 + graph.target(e)), true);
85.1906 + embedding[n] = p;
85.1907 + embedding[graph.oppositeArc(pp)] = n;
85.1908 +
85.1909 + embedding[graph.oppositeArc(n)] =
85.1910 + embedding[graph.oppositeArc(e)];
85.1911 + embedding[graph.oppositeArc(e)] =
85.1912 + graph.oppositeArc(n);
85.1913 +
85.1914 + p = n;
85.1915 + e = embedding[graph.oppositeArc(n)];
85.1916 + } else {
85.1917 + visited.set(graph.source(e), true);
85.1918 + pp = p;
85.1919 + p = e;
85.1920 + e = embedding[graph.oppositeArc(e)];
85.1921 + }
85.1922 + }
85.1923 + visited.setAll(false);
85.1924 + }
85.1925 + }
85.1926 +
85.1927 +
85.1928 + template <typename Graph, typename EmbeddingMap>
85.1929 + void makeMaxPlanar(Graph& graph, EmbeddingMap& embedding) {
85.1930 +
85.1931 + typename Graph::template NodeMap<int> degree(graph);
85.1932 +
85.1933 + for (typename Graph::NodeIt n(graph); n != INVALID; ++n) {
85.1934 + degree[n] = countIncEdges(graph, n);
85.1935 + }
85.1936 +
85.1937 + typename Graph::template ArcMap<bool> processed(graph);
85.1938 + IterableBoolMap<Graph, typename Graph::Node> visited(graph, false);
85.1939 +
85.1940 + std::vector<typename Graph::Arc> arcs;
85.1941 + for (typename Graph::ArcIt e(graph); e != INVALID; ++e) {
85.1942 + arcs.push_back(e);
85.1943 + }
85.1944 +
85.1945 + for (int i = 0; i < int(arcs.size()); ++i) {
85.1946 + typename Graph::Arc e = arcs[i];
85.1947 +
85.1948 + if (processed[e]) continue;
85.1949 + processed[e] = true;
85.1950 +
85.1951 + typename Graph::Arc mine = e;
85.1952 + int mind = degree[graph.source(e)];
85.1953 +
85.1954 + int face_size = 1;
85.1955 +
85.1956 + typename Graph::Arc l = e;
85.1957 + e = embedding[graph.oppositeArc(e)];
85.1958 + while (l != e) {
85.1959 + processed[e] = true;
85.1960 +
85.1961 + ++face_size;
85.1962 +
85.1963 + if (degree[graph.source(e)] < mind) {
85.1964 + mine = e;
85.1965 + mind = degree[graph.source(e)];
85.1966 + }
85.1967 +
85.1968 + e = embedding[graph.oppositeArc(e)];
85.1969 + }
85.1970 +
85.1971 + if (face_size < 4) {
85.1972 + continue;
85.1973 + }
85.1974 +
85.1975 + typename Graph::Node s = graph.source(mine);
85.1976 + for (typename Graph::OutArcIt e(graph, s); e != INVALID; ++e) {
85.1977 + visited.set(graph.target(e), true);
85.1978 + }
85.1979 +
85.1980 + typename Graph::Arc oppe = INVALID;
85.1981 +
85.1982 + e = embedding[graph.oppositeArc(mine)];
85.1983 + e = embedding[graph.oppositeArc(e)];
85.1984 + while (graph.target(e) != s) {
85.1985 + if (visited[graph.source(e)]) {
85.1986 + oppe = e;
85.1987 + break;
85.1988 + }
85.1989 + e = embedding[graph.oppositeArc(e)];
85.1990 + }
85.1991 + visited.setAll(false);
85.1992 +
85.1993 + if (oppe == INVALID) {
85.1994 +
85.1995 + e = embedding[graph.oppositeArc(mine)];
85.1996 + typename Graph::Arc pn = mine, p = e;
85.1997 +
85.1998 + e = embedding[graph.oppositeArc(e)];
85.1999 + while (graph.target(e) != s) {
85.2000 + typename Graph::Arc n =
85.2001 + graph.direct(graph.addEdge(s, graph.source(e)), true);
85.2002 +
85.2003 + embedding[n] = pn;
85.2004 + embedding[graph.oppositeArc(n)] = e;
85.2005 + embedding[graph.oppositeArc(p)] = graph.oppositeArc(n);
85.2006 +
85.2007 + pn = n;
85.2008 +
85.2009 + p = e;
85.2010 + e = embedding[graph.oppositeArc(e)];
85.2011 + }
85.2012 +
85.2013 + embedding[graph.oppositeArc(e)] = pn;
85.2014 +
85.2015 + } else {
85.2016 +
85.2017 + mine = embedding[graph.oppositeArc(mine)];
85.2018 + s = graph.source(mine);
85.2019 + oppe = embedding[graph.oppositeArc(oppe)];
85.2020 + typename Graph::Node t = graph.source(oppe);
85.2021 +
85.2022 + typename Graph::Arc ce = graph.direct(graph.addEdge(s, t), true);
85.2023 + embedding[ce] = mine;
85.2024 + embedding[graph.oppositeArc(ce)] = oppe;
85.2025 +
85.2026 + typename Graph::Arc pn = ce, p = oppe;
85.2027 + e = embedding[graph.oppositeArc(oppe)];
85.2028 + while (graph.target(e) != s) {
85.2029 + typename Graph::Arc n =
85.2030 + graph.direct(graph.addEdge(s, graph.source(e)), true);
85.2031 +
85.2032 + embedding[n] = pn;
85.2033 + embedding[graph.oppositeArc(n)] = e;
85.2034 + embedding[graph.oppositeArc(p)] = graph.oppositeArc(n);
85.2035 +
85.2036 + pn = n;
85.2037 +
85.2038 + p = e;
85.2039 + e = embedding[graph.oppositeArc(e)];
85.2040 +
85.2041 + }
85.2042 + embedding[graph.oppositeArc(e)] = pn;
85.2043 +
85.2044 + pn = graph.oppositeArc(ce), p = mine;
85.2045 + e = embedding[graph.oppositeArc(mine)];
85.2046 + while (graph.target(e) != t) {
85.2047 + typename Graph::Arc n =
85.2048 + graph.direct(graph.addEdge(t, graph.source(e)), true);
85.2049 +
85.2050 + embedding[n] = pn;
85.2051 + embedding[graph.oppositeArc(n)] = e;
85.2052 + embedding[graph.oppositeArc(p)] = graph.oppositeArc(n);
85.2053 +
85.2054 + pn = n;
85.2055 +
85.2056 + p = e;
85.2057 + e = embedding[graph.oppositeArc(e)];
85.2058 +
85.2059 + }
85.2060 + embedding[graph.oppositeArc(e)] = pn;
85.2061 + }
85.2062 + }
85.2063 + }
85.2064 +
85.2065 + }
85.2066 +
85.2067 + /// \ingroup planar
85.2068 + ///
85.2069 + /// \brief Schnyder's planar drawing algorithm
85.2070 + ///
85.2071 + /// The planar drawing algorithm calculates positions for the nodes
85.2072 + /// in the plane. These coordinates satisfy that if the edges are
85.2073 + /// represented with straight lines, then they will not intersect
85.2074 + /// each other.
85.2075 + ///
85.2076 + /// Scnyder's algorithm embeds the graph on an \c (n-2)x(n-2) size grid,
85.2077 + /// i.e. each node will be located in the \c [0..n-2]x[0..n-2] square.
85.2078 + /// The time complexity of the algorithm is O(n).
85.2079 + ///
85.2080 + /// \see PlanarEmbedding
85.2081 + template <typename Graph>
85.2082 + class PlanarDrawing {
85.2083 + public:
85.2084 +
85.2085 + TEMPLATE_GRAPH_TYPEDEFS(Graph);
85.2086 +
85.2087 + /// \brief The point type for storing coordinates
85.2088 + typedef dim2::Point<int> Point;
85.2089 + /// \brief The map type for storing the coordinates of the nodes
85.2090 + typedef typename Graph::template NodeMap<Point> PointMap;
85.2091 +
85.2092 +
85.2093 + /// \brief Constructor
85.2094 + ///
85.2095 + /// Constructor
85.2096 + /// \pre The graph must be simple, i.e. it should not
85.2097 + /// contain parallel or loop arcs.
85.2098 + PlanarDrawing(const Graph& graph)
85.2099 + : _graph(graph), _point_map(graph) {}
85.2100 +
85.2101 + private:
85.2102 +
85.2103 + template <typename AuxGraph, typename AuxEmbeddingMap>
85.2104 + void drawing(const AuxGraph& graph,
85.2105 + const AuxEmbeddingMap& next,
85.2106 + PointMap& point_map) {
85.2107 + TEMPLATE_GRAPH_TYPEDEFS(AuxGraph);
85.2108 +
85.2109 + typename AuxGraph::template ArcMap<Arc> prev(graph);
85.2110 +
85.2111 + for (NodeIt n(graph); n != INVALID; ++n) {
85.2112 + Arc e = OutArcIt(graph, n);
85.2113 +
85.2114 + Arc p = e, l = e;
85.2115 +
85.2116 + e = next[e];
85.2117 + while (e != l) {
85.2118 + prev[e] = p;
85.2119 + p = e;
85.2120 + e = next[e];
85.2121 + }
85.2122 + prev[e] = p;
85.2123 + }
85.2124 +
85.2125 + Node anode, bnode, cnode;
85.2126 +
85.2127 + {
85.2128 + Arc e = ArcIt(graph);
85.2129 + anode = graph.source(e);
85.2130 + bnode = graph.target(e);
85.2131 + cnode = graph.target(next[graph.oppositeArc(e)]);
85.2132 + }
85.2133 +
85.2134 + IterableBoolMap<AuxGraph, Node> proper(graph, false);
85.2135 + typename AuxGraph::template NodeMap<int> conn(graph, -1);
85.2136 +
85.2137 + conn[anode] = conn[bnode] = -2;
85.2138 + {
85.2139 + for (OutArcIt e(graph, anode); e != INVALID; ++e) {
85.2140 + Node m = graph.target(e);
85.2141 + if (conn[m] == -1) {
85.2142 + conn[m] = 1;
85.2143 + }
85.2144 + }
85.2145 + conn[cnode] = 2;
85.2146 +
85.2147 + for (OutArcIt e(graph, bnode); e != INVALID; ++e) {
85.2148 + Node m = graph.target(e);
85.2149 + if (conn[m] == -1) {
85.2150 + conn[m] = 1;
85.2151 + } else if (conn[m] != -2) {
85.2152 + conn[m] += 1;
85.2153 + Arc pe = graph.oppositeArc(e);
85.2154 + if (conn[graph.target(next[pe])] == -2) {
85.2155 + conn[m] -= 1;
85.2156 + }
85.2157 + if (conn[graph.target(prev[pe])] == -2) {
85.2158 + conn[m] -= 1;
85.2159 + }
85.2160 +
85.2161 + proper.set(m, conn[m] == 1);
85.2162 + }
85.2163 + }
85.2164 + }
85.2165 +
85.2166 +
85.2167 + typename AuxGraph::template ArcMap<int> angle(graph, -1);
85.2168 +
85.2169 + while (proper.trueNum() != 0) {
85.2170 + Node n = typename IterableBoolMap<AuxGraph, Node>::TrueIt(proper);
85.2171 + proper.set(n, false);
85.2172 + conn[n] = -2;
85.2173 +
85.2174 + for (OutArcIt e(graph, n); e != INVALID; ++e) {
85.2175 + Node m = graph.target(e);
85.2176 + if (conn[m] == -1) {
85.2177 + conn[m] = 1;
85.2178 + } else if (conn[m] != -2) {
85.2179 + conn[m] += 1;
85.2180 + Arc pe = graph.oppositeArc(e);
85.2181 + if (conn[graph.target(next[pe])] == -2) {
85.2182 + conn[m] -= 1;
85.2183 + }
85.2184 + if (conn[graph.target(prev[pe])] == -2) {
85.2185 + conn[m] -= 1;
85.2186 + }
85.2187 +
85.2188 + proper.set(m, conn[m] == 1);
85.2189 + }
85.2190 + }
85.2191 +
85.2192 + {
85.2193 + Arc e = OutArcIt(graph, n);
85.2194 + Arc p = e, l = e;
85.2195 +
85.2196 + e = next[e];
85.2197 + while (e != l) {
85.2198 +
85.2199 + if (conn[graph.target(e)] == -2 && conn[graph.target(p)] == -2) {
85.2200 + Arc f = e;
85.2201 + angle[f] = 0;
85.2202 + f = next[graph.oppositeArc(f)];
85.2203 + angle[f] = 1;
85.2204 + f = next[graph.oppositeArc(f)];
85.2205 + angle[f] = 2;
85.2206 + }
85.2207 +
85.2208 + p = e;
85.2209 + e = next[e];
85.2210 + }
85.2211 +
85.2212 + if (conn[graph.target(e)] == -2 && conn[graph.target(p)] == -2) {
85.2213 + Arc f = e;
85.2214 + angle[f] = 0;
85.2215 + f = next[graph.oppositeArc(f)];
85.2216 + angle[f] = 1;
85.2217 + f = next[graph.oppositeArc(f)];
85.2218 + angle[f] = 2;
85.2219 + }
85.2220 + }
85.2221 + }
85.2222 +
85.2223 + typename AuxGraph::template NodeMap<Node> apred(graph, INVALID);
85.2224 + typename AuxGraph::template NodeMap<Node> bpred(graph, INVALID);
85.2225 + typename AuxGraph::template NodeMap<Node> cpred(graph, INVALID);
85.2226 +
85.2227 + typename AuxGraph::template NodeMap<int> apredid(graph, -1);
85.2228 + typename AuxGraph::template NodeMap<int> bpredid(graph, -1);
85.2229 + typename AuxGraph::template NodeMap<int> cpredid(graph, -1);
85.2230 +
85.2231 + for (ArcIt e(graph); e != INVALID; ++e) {
85.2232 + if (angle[e] == angle[next[e]]) {
85.2233 + switch (angle[e]) {
85.2234 + case 2:
85.2235 + apred[graph.target(e)] = graph.source(e);
85.2236 + apredid[graph.target(e)] = graph.id(graph.source(e));
85.2237 + break;
85.2238 + case 1:
85.2239 + bpred[graph.target(e)] = graph.source(e);
85.2240 + bpredid[graph.target(e)] = graph.id(graph.source(e));
85.2241 + break;
85.2242 + case 0:
85.2243 + cpred[graph.target(e)] = graph.source(e);
85.2244 + cpredid[graph.target(e)] = graph.id(graph.source(e));
85.2245 + break;
85.2246 + }
85.2247 + }
85.2248 + }
85.2249 +
85.2250 + cpred[anode] = INVALID;
85.2251 + cpred[bnode] = INVALID;
85.2252 +
85.2253 + std::vector<Node> aorder, border, corder;
85.2254 +
85.2255 + {
85.2256 + typename AuxGraph::template NodeMap<bool> processed(graph, false);
85.2257 + std::vector<Node> st;
85.2258 + for (NodeIt n(graph); n != INVALID; ++n) {
85.2259 + if (!processed[n] && n != bnode && n != cnode) {
85.2260 + st.push_back(n);
85.2261 + processed[n] = true;
85.2262 + Node m = apred[n];
85.2263 + while (m != INVALID && !processed[m]) {
85.2264 + st.push_back(m);
85.2265 + processed[m] = true;
85.2266 + m = apred[m];
85.2267 + }
85.2268 + while (!st.empty()) {
85.2269 + aorder.push_back(st.back());
85.2270 + st.pop_back();
85.2271 + }
85.2272 + }
85.2273 + }
85.2274 + }
85.2275 +
85.2276 + {
85.2277 + typename AuxGraph::template NodeMap<bool> processed(graph, false);
85.2278 + std::vector<Node> st;
85.2279 + for (NodeIt n(graph); n != INVALID; ++n) {
85.2280 + if (!processed[n] && n != cnode && n != anode) {
85.2281 + st.push_back(n);
85.2282 + processed[n] = true;
85.2283 + Node m = bpred[n];
85.2284 + while (m != INVALID && !processed[m]) {
85.2285 + st.push_back(m);
85.2286 + processed[m] = true;
85.2287 + m = bpred[m];
85.2288 + }
85.2289 + while (!st.empty()) {
85.2290 + border.push_back(st.back());
85.2291 + st.pop_back();
85.2292 + }
85.2293 + }
85.2294 + }
85.2295 + }
85.2296 +
85.2297 + {
85.2298 + typename AuxGraph::template NodeMap<bool> processed(graph, false);
85.2299 + std::vector<Node> st;
85.2300 + for (NodeIt n(graph); n != INVALID; ++n) {
85.2301 + if (!processed[n] && n != anode && n != bnode) {
85.2302 + st.push_back(n);
85.2303 + processed[n] = true;
85.2304 + Node m = cpred[n];
85.2305 + while (m != INVALID && !processed[m]) {
85.2306 + st.push_back(m);
85.2307 + processed[m] = true;
85.2308 + m = cpred[m];
85.2309 + }
85.2310 + while (!st.empty()) {
85.2311 + corder.push_back(st.back());
85.2312 + st.pop_back();
85.2313 + }
85.2314 + }
85.2315 + }
85.2316 + }
85.2317 +
85.2318 + typename AuxGraph::template NodeMap<int> atree(graph, 0);
85.2319 + for (int i = aorder.size() - 1; i >= 0; --i) {
85.2320 + Node n = aorder[i];
85.2321 + atree[n] = 1;
85.2322 + for (OutArcIt e(graph, n); e != INVALID; ++e) {
85.2323 + if (apred[graph.target(e)] == n) {
85.2324 + atree[n] += atree[graph.target(e)];
85.2325 + }
85.2326 + }
85.2327 + }
85.2328 +
85.2329 + typename AuxGraph::template NodeMap<int> btree(graph, 0);
85.2330 + for (int i = border.size() - 1; i >= 0; --i) {
85.2331 + Node n = border[i];
85.2332 + btree[n] = 1;
85.2333 + for (OutArcIt e(graph, n); e != INVALID; ++e) {
85.2334 + if (bpred[graph.target(e)] == n) {
85.2335 + btree[n] += btree[graph.target(e)];
85.2336 + }
85.2337 + }
85.2338 + }
85.2339 +
85.2340 + typename AuxGraph::template NodeMap<int> apath(graph, 0);
85.2341 + apath[bnode] = apath[cnode] = 1;
85.2342 + typename AuxGraph::template NodeMap<int> apath_btree(graph, 0);
85.2343 + apath_btree[bnode] = btree[bnode];
85.2344 + for (int i = 1; i < int(aorder.size()); ++i) {
85.2345 + Node n = aorder[i];
85.2346 + apath[n] = apath[apred[n]] + 1;
85.2347 + apath_btree[n] = btree[n] + apath_btree[apred[n]];
85.2348 + }
85.2349 +
85.2350 + typename AuxGraph::template NodeMap<int> bpath_atree(graph, 0);
85.2351 + bpath_atree[anode] = atree[anode];
85.2352 + for (int i = 1; i < int(border.size()); ++i) {
85.2353 + Node n = border[i];
85.2354 + bpath_atree[n] = atree[n] + bpath_atree[bpred[n]];
85.2355 + }
85.2356 +
85.2357 + typename AuxGraph::template NodeMap<int> cpath(graph, 0);
85.2358 + cpath[anode] = cpath[bnode] = 1;
85.2359 + typename AuxGraph::template NodeMap<int> cpath_atree(graph, 0);
85.2360 + cpath_atree[anode] = atree[anode];
85.2361 + typename AuxGraph::template NodeMap<int> cpath_btree(graph, 0);
85.2362 + cpath_btree[bnode] = btree[bnode];
85.2363 + for (int i = 1; i < int(corder.size()); ++i) {
85.2364 + Node n = corder[i];
85.2365 + cpath[n] = cpath[cpred[n]] + 1;
85.2366 + cpath_atree[n] = atree[n] + cpath_atree[cpred[n]];
85.2367 + cpath_btree[n] = btree[n] + cpath_btree[cpred[n]];
85.2368 + }
85.2369 +
85.2370 + typename AuxGraph::template NodeMap<int> third(graph);
85.2371 + for (NodeIt n(graph); n != INVALID; ++n) {
85.2372 + point_map[n].x =
85.2373 + bpath_atree[n] + cpath_atree[n] - atree[n] - cpath[n] + 1;
85.2374 + point_map[n].y =
85.2375 + cpath_btree[n] + apath_btree[n] - btree[n] - apath[n] + 1;
85.2376 + }
85.2377 +
85.2378 + }
85.2379 +
85.2380 + public:
85.2381 +
85.2382 + /// \brief Calculate the node positions
85.2383 + ///
85.2384 + /// This function calculates the node positions on the plane.
85.2385 + /// \return \c true if the graph is planar.
85.2386 + bool run() {
85.2387 + PlanarEmbedding<Graph> pe(_graph);
85.2388 + if (!pe.run()) return false;
85.2389 +
85.2390 + run(pe);
85.2391 + return true;
85.2392 + }
85.2393 +
85.2394 + /// \brief Calculate the node positions according to a
85.2395 + /// combinatorical embedding
85.2396 + ///
85.2397 + /// This function calculates the node positions on the plane.
85.2398 + /// The given \c embedding map should contain a valid combinatorical
85.2399 + /// embedding, i.e. a valid cyclic order of the arcs.
85.2400 + /// It can be computed using PlanarEmbedding.
85.2401 + template <typename EmbeddingMap>
85.2402 + void run(const EmbeddingMap& embedding) {
85.2403 + typedef SmartEdgeSet<Graph> AuxGraph;
85.2404 +
85.2405 + if (3 * countNodes(_graph) - 6 == countEdges(_graph)) {
85.2406 + drawing(_graph, embedding, _point_map);
85.2407 + return;
85.2408 + }
85.2409 +
85.2410 + AuxGraph aux_graph(_graph);
85.2411 + typename AuxGraph::template ArcMap<typename AuxGraph::Arc>
85.2412 + aux_embedding(aux_graph);
85.2413 +
85.2414 + {
85.2415 +
85.2416 + typename Graph::template EdgeMap<typename AuxGraph::Edge>
85.2417 + ref(_graph);
85.2418 +
85.2419 + for (EdgeIt e(_graph); e != INVALID; ++e) {
85.2420 + ref[e] = aux_graph.addEdge(_graph.u(e), _graph.v(e));
85.2421 + }
85.2422 +
85.2423 + for (EdgeIt e(_graph); e != INVALID; ++e) {
85.2424 + Arc ee = embedding[_graph.direct(e, true)];
85.2425 + aux_embedding[aux_graph.direct(ref[e], true)] =
85.2426 + aux_graph.direct(ref[ee], _graph.direction(ee));
85.2427 + ee = embedding[_graph.direct(e, false)];
85.2428 + aux_embedding[aux_graph.direct(ref[e], false)] =
85.2429 + aux_graph.direct(ref[ee], _graph.direction(ee));
85.2430 + }
85.2431 + }
85.2432 + _planarity_bits::makeConnected(aux_graph, aux_embedding);
85.2433 + _planarity_bits::makeBiNodeConnected(aux_graph, aux_embedding);
85.2434 + _planarity_bits::makeMaxPlanar(aux_graph, aux_embedding);
85.2435 + drawing(aux_graph, aux_embedding, _point_map);
85.2436 + }
85.2437 +
85.2438 + /// \brief The coordinate of the given node
85.2439 + ///
85.2440 + /// This function returns the coordinate of the given node.
85.2441 + Point operator[](const Node& node) const {
85.2442 + return _point_map[node];
85.2443 + }
85.2444 +
85.2445 + /// \brief Return the grid embedding in a node map
85.2446 + ///
85.2447 + /// This function returns the grid embedding in a node map of
85.2448 + /// \c dim2::Point<int> coordinates.
85.2449 + const PointMap& coords() const {
85.2450 + return _point_map;
85.2451 + }
85.2452 +
85.2453 + private:
85.2454 +
85.2455 + const Graph& _graph;
85.2456 + PointMap _point_map;
85.2457 +
85.2458 + };
85.2459 +
85.2460 + namespace _planarity_bits {
85.2461 +
85.2462 + template <typename ColorMap>
85.2463 + class KempeFilter {
85.2464 + public:
85.2465 + typedef typename ColorMap::Key Key;
85.2466 + typedef bool Value;
85.2467 +
85.2468 + KempeFilter(const ColorMap& color_map,
85.2469 + const typename ColorMap::Value& first,
85.2470 + const typename ColorMap::Value& second)
85.2471 + : _color_map(color_map), _first(first), _second(second) {}
85.2472 +
85.2473 + Value operator[](const Key& key) const {
85.2474 + return _color_map[key] == _first || _color_map[key] == _second;
85.2475 + }
85.2476 +
85.2477 + private:
85.2478 + const ColorMap& _color_map;
85.2479 + typename ColorMap::Value _first, _second;
85.2480 + };
85.2481 + }
85.2482 +
85.2483 + /// \ingroup planar
85.2484 + ///
85.2485 + /// \brief Coloring planar graphs
85.2486 + ///
85.2487 + /// The graph coloring problem is the coloring of the graph nodes
85.2488 + /// so that there are no adjacent nodes with the same color. The
85.2489 + /// planar graphs can always be colored with four colors, which is
85.2490 + /// proved by Appel and Haken. Their proofs provide a quadratic
85.2491 + /// time algorithm for four coloring, but it could not be used to
85.2492 + /// implement an efficient algorithm. The five and six coloring can be
85.2493 + /// made in linear time, but in this class, the five coloring has
85.2494 + /// quadratic worst case time complexity. The two coloring (if
85.2495 + /// possible) is solvable with a graph search algorithm and it is
85.2496 + /// implemented in \ref bipartitePartitions() function in LEMON. To
85.2497 + /// decide whether a planar graph is three colorable is NP-complete.
85.2498 + ///
85.2499 + /// This class contains member functions for calculate colorings
85.2500 + /// with five and six colors. The six coloring algorithm is a simple
85.2501 + /// greedy coloring on the backward minimum outgoing order of nodes.
85.2502 + /// This order can be computed by selecting the node with least
85.2503 + /// outgoing arcs to unprocessed nodes in each phase. This order
85.2504 + /// guarantees that when a node is chosen for coloring it has at
85.2505 + /// most five already colored adjacents. The five coloring algorithm
85.2506 + /// use the same method, but if the greedy approach fails to color
85.2507 + /// with five colors, i.e. the node has five already different
85.2508 + /// colored neighbours, it swaps the colors in one of the connected
85.2509 + /// two colored sets with the Kempe recoloring method.
85.2510 + template <typename Graph>
85.2511 + class PlanarColoring {
85.2512 + public:
85.2513 +
85.2514 + TEMPLATE_GRAPH_TYPEDEFS(Graph);
85.2515 +
85.2516 + /// \brief The map type for storing color indices
85.2517 + typedef typename Graph::template NodeMap<int> IndexMap;
85.2518 + /// \brief The map type for storing colors
85.2519 + ///
85.2520 + /// The map type for storing colors.
85.2521 + /// \see Palette, Color
85.2522 + typedef ComposeMap<Palette, IndexMap> ColorMap;
85.2523 +
85.2524 + /// \brief Constructor
85.2525 + ///
85.2526 + /// Constructor.
85.2527 + /// \pre The graph must be simple, i.e. it should not
85.2528 + /// contain parallel or loop arcs.
85.2529 + PlanarColoring(const Graph& graph)
85.2530 + : _graph(graph), _color_map(graph), _palette(0) {
85.2531 + _palette.add(Color(1,0,0));
85.2532 + _palette.add(Color(0,1,0));
85.2533 + _palette.add(Color(0,0,1));
85.2534 + _palette.add(Color(1,1,0));
85.2535 + _palette.add(Color(1,0,1));
85.2536 + _palette.add(Color(0,1,1));
85.2537 + }
85.2538 +
85.2539 + /// \brief Return the node map of color indices
85.2540 + ///
85.2541 + /// This function returns the node map of color indices. The values are
85.2542 + /// in the range \c [0..4] or \c [0..5] according to the coloring method.
85.2543 + IndexMap colorIndexMap() const {
85.2544 + return _color_map;
85.2545 + }
85.2546 +
85.2547 + /// \brief Return the node map of colors
85.2548 + ///
85.2549 + /// This function returns the node map of colors. The values are among
85.2550 + /// five or six distinct \ref lemon::Color "colors".
85.2551 + ColorMap colorMap() const {
85.2552 + return composeMap(_palette, _color_map);
85.2553 + }
85.2554 +
85.2555 + /// \brief Return the color index of the node
85.2556 + ///
85.2557 + /// This function returns the color index of the given node. The value is
85.2558 + /// in the range \c [0..4] or \c [0..5] according to the coloring method.
85.2559 + int colorIndex(const Node& node) const {
85.2560 + return _color_map[node];
85.2561 + }
85.2562 +
85.2563 + /// \brief Return the color of the node
85.2564 + ///
85.2565 + /// This function returns the color of the given node. The value is among
85.2566 + /// five or six distinct \ref lemon::Color "colors".
85.2567 + Color color(const Node& node) const {
85.2568 + return _palette[_color_map[node]];
85.2569 + }
85.2570 +
85.2571 +
85.2572 + /// \brief Calculate a coloring with at most six colors
85.2573 + ///
85.2574 + /// This function calculates a coloring with at most six colors. The time
85.2575 + /// complexity of this variant is linear in the size of the graph.
85.2576 + /// \return \c true if the algorithm could color the graph with six colors.
85.2577 + /// If the algorithm fails, then the graph is not planar.
85.2578 + /// \note This function can return \c true if the graph is not
85.2579 + /// planar, but it can be colored with at most six colors.
85.2580 + bool runSixColoring() {
85.2581 +
85.2582 + typename Graph::template NodeMap<int> heap_index(_graph, -1);
85.2583 + BucketHeap<typename Graph::template NodeMap<int> > heap(heap_index);
85.2584 +
85.2585 + for (NodeIt n(_graph); n != INVALID; ++n) {
85.2586 + _color_map[n] = -2;
85.2587 + heap.push(n, countOutArcs(_graph, n));
85.2588 + }
85.2589 +
85.2590 + std::vector<Node> order;
85.2591 +
85.2592 + while (!heap.empty()) {
85.2593 + Node n = heap.top();
85.2594 + heap.pop();
85.2595 + _color_map[n] = -1;
85.2596 + order.push_back(n);
85.2597 + for (OutArcIt e(_graph, n); e != INVALID; ++e) {
85.2598 + Node t = _graph.runningNode(e);
85.2599 + if (_color_map[t] == -2) {
85.2600 + heap.decrease(t, heap[t] - 1);
85.2601 + }
85.2602 + }
85.2603 + }
85.2604 +
85.2605 + for (int i = order.size() - 1; i >= 0; --i) {
85.2606 + std::vector<bool> forbidden(6, false);
85.2607 + for (OutArcIt e(_graph, order[i]); e != INVALID; ++e) {
85.2608 + Node t = _graph.runningNode(e);
85.2609 + if (_color_map[t] != -1) {
85.2610 + forbidden[_color_map[t]] = true;
85.2611 + }
85.2612 + }
85.2613 + for (int k = 0; k < 6; ++k) {
85.2614 + if (!forbidden[k]) {
85.2615 + _color_map[order[i]] = k;
85.2616 + break;
85.2617 + }
85.2618 + }
85.2619 + if (_color_map[order[i]] == -1) {
85.2620 + return false;
85.2621 + }
85.2622 + }
85.2623 + return true;
85.2624 + }
85.2625 +
85.2626 + private:
85.2627 +
85.2628 + bool recolor(const Node& u, const Node& v) {
85.2629 + int ucolor = _color_map[u];
85.2630 + int vcolor = _color_map[v];
85.2631 + typedef _planarity_bits::KempeFilter<IndexMap> KempeFilter;
85.2632 + KempeFilter filter(_color_map, ucolor, vcolor);
85.2633 +
85.2634 + typedef FilterNodes<const Graph, const KempeFilter> KempeGraph;
85.2635 + KempeGraph kempe_graph(_graph, filter);
85.2636 +
85.2637 + std::vector<Node> comp;
85.2638 + Bfs<KempeGraph> bfs(kempe_graph);
85.2639 + bfs.init();
85.2640 + bfs.addSource(u);
85.2641 + while (!bfs.emptyQueue()) {
85.2642 + Node n = bfs.nextNode();
85.2643 + if (n == v) return false;
85.2644 + comp.push_back(n);
85.2645 + bfs.processNextNode();
85.2646 + }
85.2647 +
85.2648 + int scolor = ucolor + vcolor;
85.2649 + for (int i = 0; i < static_cast<int>(comp.size()); ++i) {
85.2650 + _color_map[comp[i]] = scolor - _color_map[comp[i]];
85.2651 + }
85.2652 +
85.2653 + return true;
85.2654 + }
85.2655 +
85.2656 + template <typename EmbeddingMap>
85.2657 + void kempeRecoloring(const Node& node, const EmbeddingMap& embedding) {
85.2658 + std::vector<Node> nodes;
85.2659 + nodes.reserve(4);
85.2660 +
85.2661 + for (Arc e = OutArcIt(_graph, node); e != INVALID; e = embedding[e]) {
85.2662 + Node t = _graph.target(e);
85.2663 + if (_color_map[t] != -1) {
85.2664 + nodes.push_back(t);
85.2665 + if (nodes.size() == 4) break;
85.2666 + }
85.2667 + }
85.2668 +
85.2669 + int color = _color_map[nodes[0]];
85.2670 + if (recolor(nodes[0], nodes[2])) {
85.2671 + _color_map[node] = color;
85.2672 + } else {
85.2673 + color = _color_map[nodes[1]];
85.2674 + recolor(nodes[1], nodes[3]);
85.2675 + _color_map[node] = color;
85.2676 + }
85.2677 + }
85.2678 +
85.2679 + public:
85.2680 +
85.2681 + /// \brief Calculate a coloring with at most five colors
85.2682 + ///
85.2683 + /// This function calculates a coloring with at most five
85.2684 + /// colors. The worst case time complexity of this variant is
85.2685 + /// quadratic in the size of the graph.
85.2686 + /// \param embedding This map should contain a valid combinatorical
85.2687 + /// embedding, i.e. a valid cyclic order of the arcs.
85.2688 + /// It can be computed using PlanarEmbedding.
85.2689 + template <typename EmbeddingMap>
85.2690 + void runFiveColoring(const EmbeddingMap& embedding) {
85.2691 +
85.2692 + typename Graph::template NodeMap<int> heap_index(_graph, -1);
85.2693 + BucketHeap<typename Graph::template NodeMap<int> > heap(heap_index);
85.2694 +
85.2695 + for (NodeIt n(_graph); n != INVALID; ++n) {
85.2696 + _color_map[n] = -2;
85.2697 + heap.push(n, countOutArcs(_graph, n));
85.2698 + }
85.2699 +
85.2700 + std::vector<Node> order;
85.2701 +
85.2702 + while (!heap.empty()) {
85.2703 + Node n = heap.top();
85.2704 + heap.pop();
85.2705 + _color_map[n] = -1;
85.2706 + order.push_back(n);
85.2707 + for (OutArcIt e(_graph, n); e != INVALID; ++e) {
85.2708 + Node t = _graph.runningNode(e);
85.2709 + if (_color_map[t] == -2) {
85.2710 + heap.decrease(t, heap[t] - 1);
85.2711 + }
85.2712 + }
85.2713 + }
85.2714 +
85.2715 + for (int i = order.size() - 1; i >= 0; --i) {
85.2716 + std::vector<bool> forbidden(5, false);
85.2717 + for (OutArcIt e(_graph, order[i]); e != INVALID; ++e) {
85.2718 + Node t = _graph.runningNode(e);
85.2719 + if (_color_map[t] != -1) {
85.2720 + forbidden[_color_map[t]] = true;
85.2721 + }
85.2722 + }
85.2723 + for (int k = 0; k < 5; ++k) {
85.2724 + if (!forbidden[k]) {
85.2725 + _color_map[order[i]] = k;
85.2726 + break;
85.2727 + }
85.2728 + }
85.2729 + if (_color_map[order[i]] == -1) {
85.2730 + kempeRecoloring(order[i], embedding);
85.2731 + }
85.2732 + }
85.2733 + }
85.2734 +
85.2735 + /// \brief Calculate a coloring with at most five colors
85.2736 + ///
85.2737 + /// This function calculates a coloring with at most five
85.2738 + /// colors. The worst case time complexity of this variant is
85.2739 + /// quadratic in the size of the graph.
85.2740 + /// \return \c true if the graph is planar.
85.2741 + bool runFiveColoring() {
85.2742 + PlanarEmbedding<Graph> pe(_graph);
85.2743 + if (!pe.run()) return false;
85.2744 +
85.2745 + runFiveColoring(pe.embeddingMap());
85.2746 + return true;
85.2747 + }
85.2748 +
85.2749 + private:
85.2750 +
85.2751 + const Graph& _graph;
85.2752 + IndexMap _color_map;
85.2753 + Palette _palette;
85.2754 + };
85.2755 +
85.2756 +}
85.2757 +
85.2758 +#endif
86.1 --- a/lemon/preflow.h Tue Dec 20 17:44:38 2011 +0100
86.2 +++ b/lemon/preflow.h Tue Dec 20 18:15:14 2011 +0100
86.3 @@ -2,7 +2,7 @@
86.4 *
86.5 * This file is a part of LEMON, a generic C++ optimization library.
86.6 *
86.7 - * Copyright (C) 2003-2009
86.8 + * Copyright (C) 2003-2010
86.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
86.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
86.11 *
86.12 @@ -52,7 +52,11 @@
86.13 ///
86.14 /// The type of the map that stores the flow values.
86.15 /// It must meet the \ref concepts::ReadWriteMap "ReadWriteMap" concept.
86.16 +#ifdef DOXYGEN
86.17 + typedef GR::ArcMap<Value> FlowMap;
86.18 +#else
86.19 typedef typename Digraph::template ArcMap<Value> FlowMap;
86.20 +#endif
86.21
86.22 /// \brief Instantiates a FlowMap.
86.23 ///
86.24 @@ -67,9 +71,12 @@
86.25 ///
86.26 /// The elevator type used by Preflow algorithm.
86.27 ///
86.28 - /// \sa Elevator
86.29 - /// \sa LinkedElevator
86.30 - typedef LinkedElevator<Digraph, typename Digraph::Node> Elevator;
86.31 + /// \sa Elevator, LinkedElevator
86.32 +#ifdef DOXYGEN
86.33 + typedef lemon::Elevator<GR, GR::Node> Elevator;
86.34 +#else
86.35 + typedef lemon::Elevator<Digraph, typename Digraph::Node> Elevator;
86.36 +#endif
86.37
86.38 /// \brief Instantiates an Elevator.
86.39 ///
86.40 @@ -95,9 +102,10 @@
86.41 ///
86.42 /// This class provides an implementation of Goldberg-Tarjan's \e preflow
86.43 /// \e push-relabel algorithm producing a \ref max_flow
86.44 - /// "flow of maximum value" in a digraph.
86.45 + /// "flow of maximum value" in a digraph \ref clrs01algorithms,
86.46 + /// \ref amo93networkflows, \ref goldberg88newapproach.
86.47 /// The preflow algorithms are the fastest known maximum
86.48 - /// flow algorithms. The current implementation use a mixture of the
86.49 + /// flow algorithms. The current implementation uses a mixture of the
86.50 /// \e "highest label" and the \e "bound decrease" heuristics.
86.51 /// The worst case time complexity of the algorithm is \f$O(n^2\sqrt{e})\f$.
86.52 ///
86.53 @@ -105,9 +113,17 @@
86.54 /// the maximum flow value and the minimum cut is obtained. The
86.55 /// second phase constructs a feasible maximum flow on each arc.
86.56 ///
86.57 + /// \warning This implementation cannot handle infinite or very large
86.58 + /// capacities (e.g. the maximum value of \c CAP::Value).
86.59 + ///
86.60 /// \tparam GR The type of the digraph the algorithm runs on.
86.61 /// \tparam CAP The type of the capacity map. The default map
86.62 /// type is \ref concepts::Digraph::ArcMap "GR::ArcMap<int>".
86.63 + /// \tparam TR The traits class that defines various types used by the
86.64 + /// algorithm. By default, it is \ref PreflowDefaultTraits
86.65 + /// "PreflowDefaultTraits<GR, CAP>".
86.66 + /// In most cases, this parameter should not be set directly,
86.67 + /// consider to use the named template parameters instead.
86.68 #ifdef DOXYGEN
86.69 template <typename GR, typename CAP, typename TR>
86.70 #else
86.71 @@ -257,7 +273,7 @@
86.72 /// The Elevator should have standard constructor interface to be
86.73 /// able to automatically created by the algorithm (i.e. the
86.74 /// digraph and the maximum level should be passed to it).
86.75 - /// However an external elevator object could also be passed to the
86.76 + /// However, an external elevator object could also be passed to the
86.77 /// algorithm with the \ref elevator(Elevator&) "elevator()" function
86.78 /// before calling \ref run() or \ref init().
86.79 /// \sa SetElevator
86.80 @@ -371,9 +387,10 @@
86.81 return *_level;
86.82 }
86.83
86.84 - /// \brief Sets the tolerance used by algorithm.
86.85 + /// \brief Sets the tolerance used by the algorithm.
86.86 ///
86.87 - /// Sets the tolerance used by algorithm.
86.88 + /// Sets the tolerance object used by the algorithm.
86.89 + /// \return <tt>(*this)</tt>
86.90 Preflow& tolerance(const Tolerance& tolerance) {
86.91 _tolerance = tolerance;
86.92 return *this;
86.93 @@ -381,7 +398,8 @@
86.94
86.95 /// \brief Returns a const reference to the tolerance.
86.96 ///
86.97 - /// Returns a const reference to the tolerance.
86.98 + /// Returns a const reference to the tolerance object used by
86.99 + /// the algorithm.
86.100 const Tolerance& tolerance() const {
86.101 return _tolerance;
86.102 }
86.103 @@ -389,8 +407,8 @@
86.104 /// \name Execution Control
86.105 /// The simplest way to execute the preflow algorithm is to use
86.106 /// \ref run() or \ref runMinCut().\n
86.107 - /// If you need more control on the initial solution or the execution,
86.108 - /// first you have to call one of the \ref init() functions, then
86.109 + /// If you need better control on the initial solution or the execution,
86.110 + /// you have to call one of the \ref init() functions first, then
86.111 /// \ref startFirstPhase() and if you need it \ref startSecondPhase().
86.112
86.113 ///@{
87.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
87.2 +++ b/lemon/quad_heap.h Tue Dec 20 18:15:14 2011 +0100
87.3 @@ -0,0 +1,343 @@
87.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
87.5 + *
87.6 + * This file is a part of LEMON, a generic C++ optimization library.
87.7 + *
87.8 + * Copyright (C) 2003-2009
87.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
87.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
87.11 + *
87.12 + * Permission to use, modify and distribute this software is granted
87.13 + * provided that this copyright notice appears in all copies. For
87.14 + * precise terms see the accompanying LICENSE file.
87.15 + *
87.16 + * This software is provided "AS IS" with no warranty of any kind,
87.17 + * express or implied, and with no claim as to its suitability for any
87.18 + * purpose.
87.19 + *
87.20 + */
87.21 +
87.22 +#ifndef LEMON_QUAD_HEAP_H
87.23 +#define LEMON_QUAD_HEAP_H
87.24 +
87.25 +///\ingroup heaps
87.26 +///\file
87.27 +///\brief Fourary (quaternary) heap implementation.
87.28 +
87.29 +#include <vector>
87.30 +#include <utility>
87.31 +#include <functional>
87.32 +
87.33 +namespace lemon {
87.34 +
87.35 + /// \ingroup heaps
87.36 + ///
87.37 + ///\brief Fourary (quaternary) heap data structure.
87.38 + ///
87.39 + /// This class implements the \e Fourary (\e quaternary) \e heap
87.40 + /// data structure.
87.41 + /// It fully conforms to the \ref concepts::Heap "heap concept".
87.42 + ///
87.43 + /// The fourary heap is a specialization of the \ref DHeap "D-ary heap"
87.44 + /// for <tt>D=4</tt>. It is similar to the \ref BinHeap "binary heap",
87.45 + /// but its nodes have at most four children, instead of two.
87.46 + ///
87.47 + /// \tparam PR Type of the priorities of the items.
87.48 + /// \tparam IM A read-writable item map with \c int values, used
87.49 + /// internally to handle the cross references.
87.50 + /// \tparam CMP A functor class for comparing the priorities.
87.51 + /// The default is \c std::less<PR>.
87.52 + ///
87.53 + ///\sa BinHeap
87.54 + ///\sa DHeap
87.55 +#ifdef DOXYGEN
87.56 + template <typename PR, typename IM, typename CMP>
87.57 +#else
87.58 + template <typename PR, typename IM, typename CMP = std::less<PR> >
87.59 +#endif
87.60 + class QuadHeap {
87.61 + public:
87.62 + /// Type of the item-int map.
87.63 + typedef IM ItemIntMap;
87.64 + /// Type of the priorities.
87.65 + typedef PR Prio;
87.66 + /// Type of the items stored in the heap.
87.67 + typedef typename ItemIntMap::Key Item;
87.68 + /// Type of the item-priority pairs.
87.69 + typedef std::pair<Item,Prio> Pair;
87.70 + /// Functor type for comparing the priorities.
87.71 + typedef CMP Compare;
87.72 +
87.73 + /// \brief Type to represent the states of the items.
87.74 + ///
87.75 + /// Each item has a state associated to it. It can be "in heap",
87.76 + /// "pre-heap" or "post-heap". The latter two are indifferent from the
87.77 + /// heap's point of view, but may be useful to the user.
87.78 + ///
87.79 + /// The item-int map must be initialized in such way that it assigns
87.80 + /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
87.81 + enum State {
87.82 + IN_HEAP = 0, ///< = 0.
87.83 + PRE_HEAP = -1, ///< = -1.
87.84 + POST_HEAP = -2 ///< = -2.
87.85 + };
87.86 +
87.87 + private:
87.88 + std::vector<Pair> _data;
87.89 + Compare _comp;
87.90 + ItemIntMap &_iim;
87.91 +
87.92 + public:
87.93 + /// \brief Constructor.
87.94 + ///
87.95 + /// Constructor.
87.96 + /// \param map A map that assigns \c int values to the items.
87.97 + /// It is used internally to handle the cross references.
87.98 + /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
87.99 + explicit QuadHeap(ItemIntMap &map) : _iim(map) {}
87.100 +
87.101 + /// \brief Constructor.
87.102 + ///
87.103 + /// Constructor.
87.104 + /// \param map A map that assigns \c int values to the items.
87.105 + /// It is used internally to handle the cross references.
87.106 + /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
87.107 + /// \param comp The function object used for comparing the priorities.
87.108 + QuadHeap(ItemIntMap &map, const Compare &comp)
87.109 + : _iim(map), _comp(comp) {}
87.110 +
87.111 + /// \brief The number of items stored in the heap.
87.112 + ///
87.113 + /// This function returns the number of items stored in the heap.
87.114 + int size() const { return _data.size(); }
87.115 +
87.116 + /// \brief Check if the heap is empty.
87.117 + ///
87.118 + /// This function returns \c true if the heap is empty.
87.119 + bool empty() const { return _data.empty(); }
87.120 +
87.121 + /// \brief Make the heap empty.
87.122 + ///
87.123 + /// This functon makes the heap empty.
87.124 + /// It does not change the cross reference map. If you want to reuse
87.125 + /// a heap that is not surely empty, you should first clear it and
87.126 + /// then you should set the cross reference map to \c PRE_HEAP
87.127 + /// for each item.
87.128 + void clear() { _data.clear(); }
87.129 +
87.130 + private:
87.131 + static int parent(int i) { return (i-1)/4; }
87.132 + static int firstChild(int i) { return 4*i+1; }
87.133 +
87.134 + bool less(const Pair &p1, const Pair &p2) const {
87.135 + return _comp(p1.second, p2.second);
87.136 + }
87.137 +
87.138 + void bubbleUp(int hole, Pair p) {
87.139 + int par = parent(hole);
87.140 + while( hole>0 && less(p,_data[par]) ) {
87.141 + move(_data[par],hole);
87.142 + hole = par;
87.143 + par = parent(hole);
87.144 + }
87.145 + move(p, hole);
87.146 + }
87.147 +
87.148 + void bubbleDown(int hole, Pair p, int length) {
87.149 + if( length>1 ) {
87.150 + int child = firstChild(hole);
87.151 + while( child+3<length ) {
87.152 + int min=child;
87.153 + if( less(_data[++child], _data[min]) ) min=child;
87.154 + if( less(_data[++child], _data[min]) ) min=child;
87.155 + if( less(_data[++child], _data[min]) ) min=child;
87.156 + if( !less(_data[min], p) )
87.157 + goto ok;
87.158 + move(_data[min], hole);
87.159 + hole = min;
87.160 + child = firstChild(hole);
87.161 + }
87.162 + if ( child<length ) {
87.163 + int min = child;
87.164 + if( ++child<length && less(_data[child], _data[min]) ) min=child;
87.165 + if( ++child<length && less(_data[child], _data[min]) ) min=child;
87.166 + if( less(_data[min], p) ) {
87.167 + move(_data[min], hole);
87.168 + hole = min;
87.169 + }
87.170 + }
87.171 + }
87.172 + ok:
87.173 + move(p, hole);
87.174 + }
87.175 +
87.176 + void move(const Pair &p, int i) {
87.177 + _data[i] = p;
87.178 + _iim.set(p.first, i);
87.179 + }
87.180 +
87.181 + public:
87.182 + /// \brief Insert a pair of item and priority into the heap.
87.183 + ///
87.184 + /// This function inserts \c p.first to the heap with priority
87.185 + /// \c p.second.
87.186 + /// \param p The pair to insert.
87.187 + /// \pre \c p.first must not be stored in the heap.
87.188 + void push(const Pair &p) {
87.189 + int n = _data.size();
87.190 + _data.resize(n+1);
87.191 + bubbleUp(n, p);
87.192 + }
87.193 +
87.194 + /// \brief Insert an item into the heap with the given priority.
87.195 + ///
87.196 + /// This function inserts the given item into the heap with the
87.197 + /// given priority.
87.198 + /// \param i The item to insert.
87.199 + /// \param p The priority of the item.
87.200 + /// \pre \e i must not be stored in the heap.
87.201 + void push(const Item &i, const Prio &p) { push(Pair(i,p)); }
87.202 +
87.203 + /// \brief Return the item having minimum priority.
87.204 + ///
87.205 + /// This function returns the item having minimum priority.
87.206 + /// \pre The heap must be non-empty.
87.207 + Item top() const { return _data[0].first; }
87.208 +
87.209 + /// \brief The minimum priority.
87.210 + ///
87.211 + /// This function returns the minimum priority.
87.212 + /// \pre The heap must be non-empty.
87.213 + Prio prio() const { return _data[0].second; }
87.214 +
87.215 + /// \brief Remove the item having minimum priority.
87.216 + ///
87.217 + /// This function removes the item having minimum priority.
87.218 + /// \pre The heap must be non-empty.
87.219 + void pop() {
87.220 + int n = _data.size()-1;
87.221 + _iim.set(_data[0].first, POST_HEAP);
87.222 + if (n>0) bubbleDown(0, _data[n], n);
87.223 + _data.pop_back();
87.224 + }
87.225 +
87.226 + /// \brief Remove the given item from the heap.
87.227 + ///
87.228 + /// This function removes the given item from the heap if it is
87.229 + /// already stored.
87.230 + /// \param i The item to delete.
87.231 + /// \pre \e i must be in the heap.
87.232 + void erase(const Item &i) {
87.233 + int h = _iim[i];
87.234 + int n = _data.size()-1;
87.235 + _iim.set(_data[h].first, POST_HEAP);
87.236 + if( h<n ) {
87.237 + if( less(_data[parent(h)], _data[n]) )
87.238 + bubbleDown(h, _data[n], n);
87.239 + else
87.240 + bubbleUp(h, _data[n]);
87.241 + }
87.242 + _data.pop_back();
87.243 + }
87.244 +
87.245 + /// \brief The priority of the given item.
87.246 + ///
87.247 + /// This function returns the priority of the given item.
87.248 + /// \param i The item.
87.249 + /// \pre \e i must be in the heap.
87.250 + Prio operator[](const Item &i) const {
87.251 + int idx = _iim[i];
87.252 + return _data[idx].second;
87.253 + }
87.254 +
87.255 + /// \brief Set the priority of an item or insert it, if it is
87.256 + /// not stored in the heap.
87.257 + ///
87.258 + /// This method sets the priority of the given item if it is
87.259 + /// already stored in the heap. Otherwise it inserts the given
87.260 + /// item into the heap with the given priority.
87.261 + /// \param i The item.
87.262 + /// \param p The priority.
87.263 + void set(const Item &i, const Prio &p) {
87.264 + int idx = _iim[i];
87.265 + if( idx < 0 )
87.266 + push(i,p);
87.267 + else if( _comp(p, _data[idx].second) )
87.268 + bubbleUp(idx, Pair(i,p));
87.269 + else
87.270 + bubbleDown(idx, Pair(i,p), _data.size());
87.271 + }
87.272 +
87.273 + /// \brief Decrease the priority of an item to the given value.
87.274 + ///
87.275 + /// This function decreases the priority of an item to the given value.
87.276 + /// \param i The item.
87.277 + /// \param p The priority.
87.278 + /// \pre \e i must be stored in the heap with priority at least \e p.
87.279 + void decrease(const Item &i, const Prio &p) {
87.280 + int idx = _iim[i];
87.281 + bubbleUp(idx, Pair(i,p));
87.282 + }
87.283 +
87.284 + /// \brief Increase the priority of an item to the given value.
87.285 + ///
87.286 + /// This function increases the priority of an item to the given value.
87.287 + /// \param i The item.
87.288 + /// \param p The priority.
87.289 + /// \pre \e i must be stored in the heap with priority at most \e p.
87.290 + void increase(const Item &i, const Prio &p) {
87.291 + int idx = _iim[i];
87.292 + bubbleDown(idx, Pair(i,p), _data.size());
87.293 + }
87.294 +
87.295 + /// \brief Return the state of an item.
87.296 + ///
87.297 + /// This method returns \c PRE_HEAP if the given item has never
87.298 + /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
87.299 + /// and \c POST_HEAP otherwise.
87.300 + /// In the latter case it is possible that the item will get back
87.301 + /// to the heap again.
87.302 + /// \param i The item.
87.303 + State state(const Item &i) const {
87.304 + int s = _iim[i];
87.305 + if (s>=0) s=0;
87.306 + return State(s);
87.307 + }
87.308 +
87.309 + /// \brief Set the state of an item in the heap.
87.310 + ///
87.311 + /// This function sets the state of the given item in the heap.
87.312 + /// It can be used to manually clear the heap when it is important
87.313 + /// to achive better time complexity.
87.314 + /// \param i The item.
87.315 + /// \param st The state. It should not be \c IN_HEAP.
87.316 + void state(const Item& i, State st) {
87.317 + switch (st) {
87.318 + case POST_HEAP:
87.319 + case PRE_HEAP:
87.320 + if (state(i) == IN_HEAP) erase(i);
87.321 + _iim[i] = st;
87.322 + break;
87.323 + case IN_HEAP:
87.324 + break;
87.325 + }
87.326 + }
87.327 +
87.328 + /// \brief Replace an item in the heap.
87.329 + ///
87.330 + /// This function replaces item \c i with item \c j.
87.331 + /// Item \c i must be in the heap, while \c j must be out of the heap.
87.332 + /// After calling this method, item \c i will be out of the
87.333 + /// heap and \c j will be in the heap with the same prioriority
87.334 + /// as item \c i had before.
87.335 + void replace(const Item& i, const Item& j) {
87.336 + int idx = _iim[i];
87.337 + _iim.set(i, _iim[j]);
87.338 + _iim.set(j, idx);
87.339 + _data[idx].first = j;
87.340 + }
87.341 +
87.342 + }; // class QuadHeap
87.343 +
87.344 +} // namespace lemon
87.345 +
87.346 +#endif // LEMON_FOURARY_HEAP_H
88.1 --- a/lemon/radix_heap.h Tue Dec 20 17:44:38 2011 +0100
88.2 +++ b/lemon/radix_heap.h Tue Dec 20 18:15:14 2011 +0100
88.3 @@ -19,9 +19,9 @@
88.4 #ifndef LEMON_RADIX_HEAP_H
88.5 #define LEMON_RADIX_HEAP_H
88.6
88.7 -///\ingroup auxdat
88.8 +///\ingroup heaps
88.9 ///\file
88.10 -///\brief Radix Heap implementation.
88.11 +///\brief Radix heap implementation.
88.12
88.13 #include <vector>
88.14 #include <lemon/error.h>
88.15 @@ -29,56 +29,54 @@
88.16 namespace lemon {
88.17
88.18
88.19 - /// \ingroup auxdata
88.20 + /// \ingroup heaps
88.21 ///
88.22 - /// \brief A Radix Heap implementation.
88.23 + /// \brief Radix heap data structure.
88.24 ///
88.25 - /// This class implements the \e radix \e heap data structure. A \e heap
88.26 - /// is a data structure for storing items with specified values called \e
88.27 - /// priorities in such a way that finding the item with minimum priority is
88.28 - /// efficient. This heap type can store only items with \e int priority.
88.29 - /// In a heap one can change the priority of an item, add or erase an
88.30 - /// item, but the priority cannot be decreased under the last removed
88.31 - /// item's priority.
88.32 + /// This class implements the \e radix \e heap data structure.
88.33 + /// It practically conforms to the \ref concepts::Heap "heap concept",
88.34 + /// but it has some limitations due its special implementation.
88.35 + /// The type of the priorities must be \c int and the priority of an
88.36 + /// item cannot be decreased under the priority of the last removed item.
88.37 ///
88.38 - /// \param IM A read and writable Item int map, used internally
88.39 - /// to handle the cross references.
88.40 - ///
88.41 - /// \see BinHeap
88.42 - /// \see Dijkstra
88.43 + /// \tparam IM A read-writable item map with \c int values, used
88.44 + /// internally to handle the cross references.
88.45 template <typename IM>
88.46 class RadixHeap {
88.47
88.48 public:
88.49 - typedef typename IM::Key Item;
88.50 +
88.51 + /// Type of the item-int map.
88.52 + typedef IM ItemIntMap;
88.53 + /// Type of the priorities.
88.54 typedef int Prio;
88.55 - typedef IM ItemIntMap;
88.56 + /// Type of the items stored in the heap.
88.57 + typedef typename ItemIntMap::Key Item;
88.58
88.59 /// \brief Exception thrown by RadixHeap.
88.60 ///
88.61 - /// This Exception is thrown when a smaller priority
88.62 - /// is inserted into the \e RadixHeap then the last time erased.
88.63 + /// This exception is thrown when an item is inserted into a
88.64 + /// RadixHeap with a priority smaller than the last erased one.
88.65 /// \see RadixHeap
88.66 -
88.67 - class UnderFlowPriorityError : public Exception {
88.68 + class PriorityUnderflowError : public Exception {
88.69 public:
88.70 virtual const char* what() const throw() {
88.71 - return "lemon::RadixHeap::UnderFlowPriorityError";
88.72 + return "lemon::RadixHeap::PriorityUnderflowError";
88.73 }
88.74 };
88.75
88.76 - /// \brief Type to represent the items states.
88.77 + /// \brief Type to represent the states of the items.
88.78 ///
88.79 - /// Each Item element have a state associated to it. It may be "in heap",
88.80 - /// "pre heap" or "post heap". The latter two are indifferent from the
88.81 + /// Each item has a state associated to it. It can be "in heap",
88.82 + /// "pre-heap" or "post-heap". The latter two are indifferent from the
88.83 /// heap's point of view, but may be useful to the user.
88.84 ///
88.85 - /// The ItemIntMap \e should be initialized in such way that it maps
88.86 - /// PRE_HEAP (-1) to any element to be put in the heap...
88.87 + /// The item-int map must be initialized in such way that it assigns
88.88 + /// \c PRE_HEAP (<tt>-1</tt>) to any element to be put in the heap.
88.89 enum State {
88.90 - IN_HEAP = 0,
88.91 - PRE_HEAP = -1,
88.92 - POST_HEAP = -2
88.93 + IN_HEAP = 0, ///< = 0.
88.94 + PRE_HEAP = -1, ///< = -1.
88.95 + POST_HEAP = -2 ///< = -2.
88.96 };
88.97
88.98 private:
88.99 @@ -96,52 +94,55 @@
88.100 RadixBox(int _min, int _size) : first(-1), min(_min), size(_size) {}
88.101 };
88.102
88.103 - std::vector<RadixItem> data;
88.104 - std::vector<RadixBox> boxes;
88.105 + std::vector<RadixItem> _data;
88.106 + std::vector<RadixBox> _boxes;
88.107
88.108 ItemIntMap &_iim;
88.109
88.110 + public:
88.111
88.112 - public:
88.113 - /// \brief The constructor.
88.114 + /// \brief Constructor.
88.115 ///
88.116 - /// The constructor.
88.117 - ///
88.118 - /// \param map It should be given to the constructor, since it is used
88.119 - /// internally to handle the cross references. The value of the map
88.120 - /// should be PRE_HEAP (-1) for each element.
88.121 - ///
88.122 - /// \param minimal The initial minimal value of the heap.
88.123 - /// \param capacity It determines the initial capacity of the heap.
88.124 - RadixHeap(ItemIntMap &map, int minimal = 0, int capacity = 0)
88.125 - : _iim(map) {
88.126 - boxes.push_back(RadixBox(minimal, 1));
88.127 - boxes.push_back(RadixBox(minimal + 1, 1));
88.128 - while (lower(boxes.size() - 1, capacity + minimal - 1)) {
88.129 + /// Constructor.
88.130 + /// \param map A map that assigns \c int values to the items.
88.131 + /// It is used internally to handle the cross references.
88.132 + /// The assigned value must be \c PRE_HEAP (<tt>-1</tt>) for each item.
88.133 + /// \param minimum The initial minimum value of the heap.
88.134 + /// \param capacity The initial capacity of the heap.
88.135 + RadixHeap(ItemIntMap &map, int minimum = 0, int capacity = 0)
88.136 + : _iim(map)
88.137 + {
88.138 + _boxes.push_back(RadixBox(minimum, 1));
88.139 + _boxes.push_back(RadixBox(minimum + 1, 1));
88.140 + while (lower(_boxes.size() - 1, capacity + minimum - 1)) {
88.141 extend();
88.142 }
88.143 }
88.144
88.145 - /// The number of items stored in the heap.
88.146 + /// \brief The number of items stored in the heap.
88.147 ///
88.148 - /// \brief Returns the number of items stored in the heap.
88.149 - int size() const { return data.size(); }
88.150 - /// \brief Checks if the heap stores no items.
88.151 + /// This function returns the number of items stored in the heap.
88.152 + int size() const { return _data.size(); }
88.153 +
88.154 + /// \brief Check if the heap is empty.
88.155 ///
88.156 - /// Returns \c true if and only if the heap stores no items.
88.157 - bool empty() const { return data.empty(); }
88.158 + /// This function returns \c true if the heap is empty.
88.159 + bool empty() const { return _data.empty(); }
88.160
88.161 - /// \brief Make empty this heap.
88.162 + /// \brief Make the heap empty.
88.163 ///
88.164 - /// Make empty this heap. It does not change the cross reference
88.165 - /// map. If you want to reuse a heap what is not surely empty you
88.166 - /// should first clear the heap and after that you should set the
88.167 - /// cross reference map for each item to \c PRE_HEAP.
88.168 - void clear(int minimal = 0, int capacity = 0) {
88.169 - data.clear(); boxes.clear();
88.170 - boxes.push_back(RadixBox(minimal, 1));
88.171 - boxes.push_back(RadixBox(minimal + 1, 1));
88.172 - while (lower(boxes.size() - 1, capacity + minimal - 1)) {
88.173 + /// This functon makes the heap empty.
88.174 + /// It does not change the cross reference map. If you want to reuse
88.175 + /// a heap that is not surely empty, you should first clear it and
88.176 + /// then you should set the cross reference map to \c PRE_HEAP
88.177 + /// for each item.
88.178 + /// \param minimum The minimum value of the heap.
88.179 + /// \param capacity The capacity of the heap.
88.180 + void clear(int minimum = 0, int capacity = 0) {
88.181 + _data.clear(); _boxes.clear();
88.182 + _boxes.push_back(RadixBox(minimum, 1));
88.183 + _boxes.push_back(RadixBox(minimum + 1, 1));
88.184 + while (lower(_boxes.size() - 1, capacity + minimum - 1)) {
88.185 extend();
88.186 }
88.187 }
88.188 @@ -149,255 +150,259 @@
88.189 private:
88.190
88.191 bool upper(int box, Prio pr) {
88.192 - return pr < boxes[box].min;
88.193 + return pr < _boxes[box].min;
88.194 }
88.195
88.196 bool lower(int box, Prio pr) {
88.197 - return pr >= boxes[box].min + boxes[box].size;
88.198 + return pr >= _boxes[box].min + _boxes[box].size;
88.199 }
88.200
88.201 - /// \brief Remove item from the box list.
88.202 + // Remove item from the box list
88.203 void remove(int index) {
88.204 - if (data[index].prev >= 0) {
88.205 - data[data[index].prev].next = data[index].next;
88.206 + if (_data[index].prev >= 0) {
88.207 + _data[_data[index].prev].next = _data[index].next;
88.208 } else {
88.209 - boxes[data[index].box].first = data[index].next;
88.210 + _boxes[_data[index].box].first = _data[index].next;
88.211 }
88.212 - if (data[index].next >= 0) {
88.213 - data[data[index].next].prev = data[index].prev;
88.214 + if (_data[index].next >= 0) {
88.215 + _data[_data[index].next].prev = _data[index].prev;
88.216 }
88.217 }
88.218
88.219 - /// \brief Insert item into the box list.
88.220 + // Insert item into the box list
88.221 void insert(int box, int index) {
88.222 - if (boxes[box].first == -1) {
88.223 - boxes[box].first = index;
88.224 - data[index].next = data[index].prev = -1;
88.225 + if (_boxes[box].first == -1) {
88.226 + _boxes[box].first = index;
88.227 + _data[index].next = _data[index].prev = -1;
88.228 } else {
88.229 - data[index].next = boxes[box].first;
88.230 - data[boxes[box].first].prev = index;
88.231 - data[index].prev = -1;
88.232 - boxes[box].first = index;
88.233 + _data[index].next = _boxes[box].first;
88.234 + _data[_boxes[box].first].prev = index;
88.235 + _data[index].prev = -1;
88.236 + _boxes[box].first = index;
88.237 }
88.238 - data[index].box = box;
88.239 + _data[index].box = box;
88.240 }
88.241
88.242 - /// \brief Add a new box to the box list.
88.243 + // Add a new box to the box list
88.244 void extend() {
88.245 - int min = boxes.back().min + boxes.back().size;
88.246 - int bs = 2 * boxes.back().size;
88.247 - boxes.push_back(RadixBox(min, bs));
88.248 + int min = _boxes.back().min + _boxes.back().size;
88.249 + int bs = 2 * _boxes.back().size;
88.250 + _boxes.push_back(RadixBox(min, bs));
88.251 }
88.252
88.253 - /// \brief Move an item up into the proper box.
88.254 - void bubble_up(int index) {
88.255 - if (!lower(data[index].box, data[index].prio)) return;
88.256 + // Move an item up into the proper box.
88.257 + void bubbleUp(int index) {
88.258 + if (!lower(_data[index].box, _data[index].prio)) return;
88.259 remove(index);
88.260 - int box = findUp(data[index].box, data[index].prio);
88.261 + int box = findUp(_data[index].box, _data[index].prio);
88.262 insert(box, index);
88.263 }
88.264
88.265 - /// \brief Find up the proper box for the item with the given prio.
88.266 + // Find up the proper box for the item with the given priority
88.267 int findUp(int start, int pr) {
88.268 while (lower(start, pr)) {
88.269 - if (++start == int(boxes.size())) {
88.270 + if (++start == int(_boxes.size())) {
88.271 extend();
88.272 }
88.273 }
88.274 return start;
88.275 }
88.276
88.277 - /// \brief Move an item down into the proper box.
88.278 - void bubble_down(int index) {
88.279 - if (!upper(data[index].box, data[index].prio)) return;
88.280 + // Move an item down into the proper box
88.281 + void bubbleDown(int index) {
88.282 + if (!upper(_data[index].box, _data[index].prio)) return;
88.283 remove(index);
88.284 - int box = findDown(data[index].box, data[index].prio);
88.285 + int box = findDown(_data[index].box, _data[index].prio);
88.286 insert(box, index);
88.287 }
88.288
88.289 - /// \brief Find up the proper box for the item with the given prio.
88.290 + // Find down the proper box for the item with the given priority
88.291 int findDown(int start, int pr) {
88.292 while (upper(start, pr)) {
88.293 - if (--start < 0) throw UnderFlowPriorityError();
88.294 + if (--start < 0) throw PriorityUnderflowError();
88.295 }
88.296 return start;
88.297 }
88.298
88.299 - /// \brief Find the first not empty box.
88.300 + // Find the first non-empty box
88.301 int findFirst() {
88.302 int first = 0;
88.303 - while (boxes[first].first == -1) ++first;
88.304 + while (_boxes[first].first == -1) ++first;
88.305 return first;
88.306 }
88.307
88.308 - /// \brief Gives back the minimal prio of the box.
88.309 + // Gives back the minimum priority of the given box
88.310 int minValue(int box) {
88.311 - int min = data[boxes[box].first].prio;
88.312 - for (int k = boxes[box].first; k != -1; k = data[k].next) {
88.313 - if (data[k].prio < min) min = data[k].prio;
88.314 + int min = _data[_boxes[box].first].prio;
88.315 + for (int k = _boxes[box].first; k != -1; k = _data[k].next) {
88.316 + if (_data[k].prio < min) min = _data[k].prio;
88.317 }
88.318 return min;
88.319 }
88.320
88.321 - /// \brief Rearrange the items of the heap and makes the
88.322 - /// first box not empty.
88.323 + // Rearrange the items of the heap and make the first box non-empty
88.324 void moveDown() {
88.325 int box = findFirst();
88.326 if (box == 0) return;
88.327 int min = minValue(box);
88.328 for (int i = 0; i <= box; ++i) {
88.329 - boxes[i].min = min;
88.330 - min += boxes[i].size;
88.331 + _boxes[i].min = min;
88.332 + min += _boxes[i].size;
88.333 }
88.334 - int curr = boxes[box].first, next;
88.335 + int curr = _boxes[box].first, next;
88.336 while (curr != -1) {
88.337 - next = data[curr].next;
88.338 - bubble_down(curr);
88.339 + next = _data[curr].next;
88.340 + bubbleDown(curr);
88.341 curr = next;
88.342 }
88.343 }
88.344
88.345 - void relocate_last(int index) {
88.346 - if (index != int(data.size()) - 1) {
88.347 - data[index] = data.back();
88.348 - if (data[index].prev != -1) {
88.349 - data[data[index].prev].next = index;
88.350 + void relocateLast(int index) {
88.351 + if (index != int(_data.size()) - 1) {
88.352 + _data[index] = _data.back();
88.353 + if (_data[index].prev != -1) {
88.354 + _data[_data[index].prev].next = index;
88.355 } else {
88.356 - boxes[data[index].box].first = index;
88.357 + _boxes[_data[index].box].first = index;
88.358 }
88.359 - if (data[index].next != -1) {
88.360 - data[data[index].next].prev = index;
88.361 + if (_data[index].next != -1) {
88.362 + _data[_data[index].next].prev = index;
88.363 }
88.364 - _iim[data[index].item] = index;
88.365 + _iim[_data[index].item] = index;
88.366 }
88.367 - data.pop_back();
88.368 + _data.pop_back();
88.369 }
88.370
88.371 public:
88.372
88.373 /// \brief Insert an item into the heap with the given priority.
88.374 ///
88.375 - /// Adds \c i to the heap with priority \c p.
88.376 + /// This function inserts the given item into the heap with the
88.377 + /// given priority.
88.378 /// \param i The item to insert.
88.379 /// \param p The priority of the item.
88.380 + /// \pre \e i must not be stored in the heap.
88.381 + /// \warning This method may throw an \c UnderFlowPriorityException.
88.382 void push(const Item &i, const Prio &p) {
88.383 - int n = data.size();
88.384 + int n = _data.size();
88.385 _iim.set(i, n);
88.386 - data.push_back(RadixItem(i, p));
88.387 - while (lower(boxes.size() - 1, p)) {
88.388 + _data.push_back(RadixItem(i, p));
88.389 + while (lower(_boxes.size() - 1, p)) {
88.390 extend();
88.391 }
88.392 - int box = findDown(boxes.size() - 1, p);
88.393 + int box = findDown(_boxes.size() - 1, p);
88.394 insert(box, n);
88.395 }
88.396
88.397 - /// \brief Returns the item with minimum priority.
88.398 + /// \brief Return the item having minimum priority.
88.399 ///
88.400 - /// This method returns the item with minimum priority.
88.401 - /// \pre The heap must be nonempty.
88.402 + /// This function returns the item having minimum priority.
88.403 + /// \pre The heap must be non-empty.
88.404 Item top() const {
88.405 const_cast<RadixHeap<ItemIntMap>&>(*this).moveDown();
88.406 - return data[boxes[0].first].item;
88.407 + return _data[_boxes[0].first].item;
88.408 }
88.409
88.410 - /// \brief Returns the minimum priority.
88.411 + /// \brief The minimum priority.
88.412 ///
88.413 - /// It returns the minimum priority.
88.414 - /// \pre The heap must be nonempty.
88.415 + /// This function returns the minimum priority.
88.416 + /// \pre The heap must be non-empty.
88.417 Prio prio() const {
88.418 const_cast<RadixHeap<ItemIntMap>&>(*this).moveDown();
88.419 - return data[boxes[0].first].prio;
88.420 + return _data[_boxes[0].first].prio;
88.421 }
88.422
88.423 - /// \brief Deletes the item with minimum priority.
88.424 + /// \brief Remove the item having minimum priority.
88.425 ///
88.426 - /// This method deletes the item with minimum priority.
88.427 + /// This function removes the item having minimum priority.
88.428 /// \pre The heap must be non-empty.
88.429 void pop() {
88.430 moveDown();
88.431 - int index = boxes[0].first;
88.432 - _iim[data[index].item] = POST_HEAP;
88.433 + int index = _boxes[0].first;
88.434 + _iim[_data[index].item] = POST_HEAP;
88.435 remove(index);
88.436 - relocate_last(index);
88.437 + relocateLast(index);
88.438 }
88.439
88.440 - /// \brief Deletes \c i from the heap.
88.441 + /// \brief Remove the given item from the heap.
88.442 ///
88.443 - /// This method deletes item \c i from the heap, if \c i was
88.444 - /// already stored in the heap.
88.445 - /// \param i The item to erase.
88.446 + /// This function removes the given item from the heap if it is
88.447 + /// already stored.
88.448 + /// \param i The item to delete.
88.449 + /// \pre \e i must be in the heap.
88.450 void erase(const Item &i) {
88.451 int index = _iim[i];
88.452 _iim[i] = POST_HEAP;
88.453 remove(index);
88.454 - relocate_last(index);
88.455 + relocateLast(index);
88.456 }
88.457
88.458 - /// \brief Returns the priority of \c i.
88.459 + /// \brief The priority of the given item.
88.460 ///
88.461 - /// This function returns the priority of item \c i.
88.462 - /// \pre \c i must be in the heap.
88.463 + /// This function returns the priority of the given item.
88.464 /// \param i The item.
88.465 + /// \pre \e i must be in the heap.
88.466 Prio operator[](const Item &i) const {
88.467 int idx = _iim[i];
88.468 - return data[idx].prio;
88.469 + return _data[idx].prio;
88.470 }
88.471
88.472 - /// \brief \c i gets to the heap with priority \c p independently
88.473 - /// if \c i was already there.
88.474 + /// \brief Set the priority of an item or insert it, if it is
88.475 + /// not stored in the heap.
88.476 ///
88.477 - /// This method calls \ref push(\c i, \c p) if \c i is not stored
88.478 - /// in the heap and sets the priority of \c i to \c p otherwise.
88.479 - /// It may throw an \e UnderFlowPriorityException.
88.480 + /// This method sets the priority of the given item if it is
88.481 + /// already stored in the heap. Otherwise it inserts the given
88.482 + /// item into the heap with the given priority.
88.483 /// \param i The item.
88.484 /// \param p The priority.
88.485 + /// \pre \e i must be in the heap.
88.486 + /// \warning This method may throw an \c UnderFlowPriorityException.
88.487 void set(const Item &i, const Prio &p) {
88.488 int idx = _iim[i];
88.489 if( idx < 0 ) {
88.490 push(i, p);
88.491 }
88.492 - else if( p >= data[idx].prio ) {
88.493 - data[idx].prio = p;
88.494 - bubble_up(idx);
88.495 + else if( p >= _data[idx].prio ) {
88.496 + _data[idx].prio = p;
88.497 + bubbleUp(idx);
88.498 } else {
88.499 - data[idx].prio = p;
88.500 - bubble_down(idx);
88.501 + _data[idx].prio = p;
88.502 + bubbleDown(idx);
88.503 }
88.504 }
88.505
88.506 -
88.507 - /// \brief Decreases the priority of \c i to \c p.
88.508 + /// \brief Decrease the priority of an item to the given value.
88.509 ///
88.510 - /// This method decreases the priority of item \c i to \c p.
88.511 - /// \pre \c i must be stored in the heap with priority at least \c p, and
88.512 - /// \c should be greater or equal to the last removed item's priority.
88.513 + /// This function decreases the priority of an item to the given value.
88.514 /// \param i The item.
88.515 /// \param p The priority.
88.516 + /// \pre \e i must be stored in the heap with priority at least \e p.
88.517 + /// \warning This method may throw an \c UnderFlowPriorityException.
88.518 void decrease(const Item &i, const Prio &p) {
88.519 int idx = _iim[i];
88.520 - data[idx].prio = p;
88.521 - bubble_down(idx);
88.522 + _data[idx].prio = p;
88.523 + bubbleDown(idx);
88.524 }
88.525
88.526 - /// \brief Increases the priority of \c i to \c p.
88.527 + /// \brief Increase the priority of an item to the given value.
88.528 ///
88.529 - /// This method sets the priority of item \c i to \c p.
88.530 - /// \pre \c i must be stored in the heap with priority at most \c p
88.531 + /// This function increases the priority of an item to the given value.
88.532 /// \param i The item.
88.533 /// \param p The priority.
88.534 + /// \pre \e i must be stored in the heap with priority at most \e p.
88.535 void increase(const Item &i, const Prio &p) {
88.536 int idx = _iim[i];
88.537 - data[idx].prio = p;
88.538 - bubble_up(idx);
88.539 + _data[idx].prio = p;
88.540 + bubbleUp(idx);
88.541 }
88.542
88.543 - /// \brief Returns if \c item is in, has already been in, or has
88.544 - /// never been in the heap.
88.545 + /// \brief Return the state of an item.
88.546 ///
88.547 - /// This method returns PRE_HEAP if \c item has never been in the
88.548 - /// heap, IN_HEAP if it is in the heap at the moment, and POST_HEAP
88.549 - /// otherwise. In the latter case it is possible that \c item will
88.550 - /// get back to the heap again.
88.551 + /// This method returns \c PRE_HEAP if the given item has never
88.552 + /// been in the heap, \c IN_HEAP if it is in the heap at the moment,
88.553 + /// and \c POST_HEAP otherwise.
88.554 + /// In the latter case it is possible that the item will get back
88.555 + /// to the heap again.
88.556 /// \param i The item.
88.557 State state(const Item &i) const {
88.558 int s = _iim[i];
88.559 @@ -405,11 +410,11 @@
88.560 return State(s);
88.561 }
88.562
88.563 - /// \brief Sets the state of the \c item in the heap.
88.564 + /// \brief Set the state of an item in the heap.
88.565 ///
88.566 - /// Sets the state of the \c item in the heap. It can be used to
88.567 - /// manually clear the heap when it is important to achive the
88.568 - /// better time complexity.
88.569 + /// This function sets the state of the given item in the heap.
88.570 + /// It can be used to manually clear the heap when it is important
88.571 + /// to achive better time complexity.
88.572 /// \param i The item.
88.573 /// \param st The state. It should not be \c IN_HEAP.
88.574 void state(const Item& i, State st) {
89.1 --- a/lemon/smart_graph.h Tue Dec 20 17:44:38 2011 +0100
89.2 +++ b/lemon/smart_graph.h Tue Dec 20 18:15:14 2011 +0100
89.3 @@ -2,7 +2,7 @@
89.4 *
89.5 * This file is a part of LEMON, a generic C++ optimization library.
89.6 *
89.7 - * Copyright (C) 2003-2009
89.8 + * Copyright (C) 2003-2010
89.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
89.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
89.11 *
89.12 @@ -32,10 +32,7 @@
89.13 namespace lemon {
89.14
89.15 class SmartDigraph;
89.16 - ///Base of SmartDigraph
89.17
89.18 - ///Base of SmartDigraph
89.19 - ///
89.20 class SmartDigraphBase {
89.21 protected:
89.22
89.23 @@ -187,28 +184,28 @@
89.24 ///
89.25 ///\brief A smart directed graph class.
89.26 ///
89.27 - ///This is a simple and fast digraph implementation.
89.28 - ///It is also quite memory efficient, but at the price
89.29 - ///that <b> it does support only limited (only stack-like)
89.30 - ///node and arc deletions</b>.
89.31 - ///It fully conforms to the \ref concepts::Digraph "Digraph concept".
89.32 + ///\ref SmartDigraph is a simple and fast digraph implementation.
89.33 + ///It is also quite memory efficient but at the price
89.34 + ///that it does not support node and arc deletion
89.35 + ///(except for the Snapshot feature).
89.36 ///
89.37 - ///\sa concepts::Digraph.
89.38 + ///This type fully conforms to the \ref concepts::Digraph "Digraph concept"
89.39 + ///and it also provides some additional functionalities.
89.40 + ///Most of its member functions and nested classes are documented
89.41 + ///only in the concept class.
89.42 + ///
89.43 + ///This class provides constant time counting for nodes and arcs.
89.44 + ///
89.45 + ///\sa concepts::Digraph
89.46 + ///\sa SmartGraph
89.47 class SmartDigraph : public ExtendedSmartDigraphBase {
89.48 typedef ExtendedSmartDigraphBase Parent;
89.49
89.50 private:
89.51 -
89.52 - ///SmartDigraph is \e not copy constructible. Use DigraphCopy() instead.
89.53 -
89.54 - ///SmartDigraph is \e not copy constructible. Use DigraphCopy() instead.
89.55 - ///
89.56 + /// Digraphs are \e not copy constructible. Use DigraphCopy instead.
89.57 SmartDigraph(const SmartDigraph &) : ExtendedSmartDigraphBase() {};
89.58 - ///\brief Assignment of SmartDigraph to another one is \e not allowed.
89.59 - ///Use DigraphCopy() instead.
89.60 -
89.61 - ///Assignment of SmartDigraph to another one is \e not allowed.
89.62 - ///Use DigraphCopy() instead.
89.63 + /// \brief Assignment of a digraph to another one is \e not allowed.
89.64 + /// Use DigraphCopy instead.
89.65 void operator=(const SmartDigraph &) {}
89.66
89.67 public:
89.68 @@ -221,79 +218,49 @@
89.69
89.70 ///Add a new node to the digraph.
89.71
89.72 - /// Add a new node to the digraph.
89.73 - /// \return The new node.
89.74 + ///This function adds a new node to the digraph.
89.75 + ///\return The new node.
89.76 Node addNode() { return Parent::addNode(); }
89.77
89.78 ///Add a new arc to the digraph.
89.79
89.80 - ///Add a new arc to the digraph with source node \c s
89.81 + ///This function adds a new arc to the digraph with source node \c s
89.82 ///and target node \c t.
89.83 ///\return The new arc.
89.84 - Arc addArc(const Node& s, const Node& t) {
89.85 + Arc addArc(Node s, Node t) {
89.86 return Parent::addArc(s, t);
89.87 }
89.88
89.89 - /// \brief Using this it is possible to avoid the superfluous memory
89.90 - /// allocation.
89.91 -
89.92 - /// Using this it is possible to avoid the superfluous memory
89.93 - /// allocation: if you know that the digraph you want to build will
89.94 - /// be very large (e.g. it will contain millions of nodes and/or arcs)
89.95 - /// then it is worth reserving space for this amount before starting
89.96 - /// to build the digraph.
89.97 - /// \sa reserveArc
89.98 - void reserveNode(int n) { nodes.reserve(n); };
89.99 -
89.100 - /// \brief Using this it is possible to avoid the superfluous memory
89.101 - /// allocation.
89.102 -
89.103 - /// Using this it is possible to avoid the superfluous memory
89.104 - /// allocation: if you know that the digraph you want to build will
89.105 - /// be very large (e.g. it will contain millions of nodes and/or arcs)
89.106 - /// then it is worth reserving space for this amount before starting
89.107 - /// to build the digraph.
89.108 - /// \sa reserveNode
89.109 - void reserveArc(int m) { arcs.reserve(m); };
89.110 -
89.111 /// \brief Node validity check
89.112 ///
89.113 - /// This function gives back true if the given node is valid,
89.114 - /// ie. it is a real node of the graph.
89.115 + /// This function gives back \c true if the given node is valid,
89.116 + /// i.e. it is a real node of the digraph.
89.117 ///
89.118 /// \warning A removed node (using Snapshot) could become valid again
89.119 - /// when new nodes are added to the graph.
89.120 + /// if new nodes are added to the digraph.
89.121 bool valid(Node n) const { return Parent::valid(n); }
89.122
89.123 /// \brief Arc validity check
89.124 ///
89.125 - /// This function gives back true if the given arc is valid,
89.126 - /// ie. it is a real arc of the graph.
89.127 + /// This function gives back \c true if the given arc is valid,
89.128 + /// i.e. it is a real arc of the digraph.
89.129 ///
89.130 /// \warning A removed arc (using Snapshot) could become valid again
89.131 - /// when new arcs are added to the graph.
89.132 + /// if new arcs are added to the graph.
89.133 bool valid(Arc a) const { return Parent::valid(a); }
89.134
89.135 - ///Clear the digraph.
89.136 -
89.137 - ///Erase all the nodes and arcs from the digraph.
89.138 - ///
89.139 - void clear() {
89.140 - Parent::clear();
89.141 - }
89.142 -
89.143 ///Split a node.
89.144
89.145 - ///This function splits a node. First a new node is added to the digraph,
89.146 - ///then the source of each outgoing arc of \c n is moved to this new node.
89.147 - ///If \c connect is \c true (this is the default value), then a new arc
89.148 - ///from \c n to the newly created node is also added.
89.149 + ///This function splits the given node. First, a new node is added
89.150 + ///to the digraph, then the source of each outgoing arc of node \c n
89.151 + ///is moved to this new node.
89.152 + ///If the second parameter \c connect is \c true (this is the default
89.153 + ///value), then a new arc from node \c n to the newly created node
89.154 + ///is also added.
89.155 ///\return The newly created node.
89.156 ///
89.157 - ///\note The <tt>Arc</tt>s
89.158 - ///referencing a moved arc remain
89.159 - ///valid. However <tt>InArc</tt>'s and <tt>OutArc</tt>'s
89.160 - ///may be invalidated.
89.161 + ///\note All iterators remain valid.
89.162 + ///
89.163 ///\warning This functionality cannot be used together with the Snapshot
89.164 ///feature.
89.165 Node split(Node n, bool connect = true)
89.166 @@ -308,6 +275,34 @@
89.167 return b;
89.168 }
89.169
89.170 + ///Clear the digraph.
89.171 +
89.172 + ///This function erases all nodes and arcs from the digraph.
89.173 + ///
89.174 + void clear() {
89.175 + Parent::clear();
89.176 + }
89.177 +
89.178 + /// Reserve memory for nodes.
89.179 +
89.180 + /// Using this function, it is possible to avoid superfluous memory
89.181 + /// allocation: if you know that the digraph you want to build will
89.182 + /// be large (e.g. it will contain millions of nodes and/or arcs),
89.183 + /// then it is worth reserving space for this amount before starting
89.184 + /// to build the digraph.
89.185 + /// \sa reserveArc()
89.186 + void reserveNode(int n) { nodes.reserve(n); };
89.187 +
89.188 + /// Reserve memory for arcs.
89.189 +
89.190 + /// Using this function, it is possible to avoid superfluous memory
89.191 + /// allocation: if you know that the digraph you want to build will
89.192 + /// be large (e.g. it will contain millions of nodes and/or arcs),
89.193 + /// then it is worth reserving space for this amount before starting
89.194 + /// to build the digraph.
89.195 + /// \sa reserveNode()
89.196 + void reserveArc(int m) { arcs.reserve(m); };
89.197 +
89.198 public:
89.199
89.200 class Snapshot;
89.201 @@ -332,20 +327,23 @@
89.202
89.203 public:
89.204
89.205 - ///Class to make a snapshot of the digraph and to restrore to it later.
89.206 + ///Class to make a snapshot of the digraph and to restore it later.
89.207
89.208 - ///Class to make a snapshot of the digraph and to restrore to it later.
89.209 + ///Class to make a snapshot of the digraph and to restore it later.
89.210 ///
89.211 ///The newly added nodes and arcs can be removed using the
89.212 - ///restore() function.
89.213 - ///\note After you restore a state, you cannot restore
89.214 - ///a later state, in other word you cannot add again the arcs deleted
89.215 - ///by restore() using another one Snapshot instance.
89.216 + ///restore() function. This is the only way for deleting nodes and/or
89.217 + ///arcs from a SmartDigraph structure.
89.218 ///
89.219 - ///\warning If you do not use correctly the snapshot that can cause
89.220 - ///either broken program, invalid state of the digraph, valid but
89.221 - ///not the restored digraph or no change. Because the runtime performance
89.222 - ///the validity of the snapshot is not stored.
89.223 + ///\note After a state is restored, you cannot restore a later state,
89.224 + ///i.e. you cannot add the removed nodes and arcs again using
89.225 + ///another Snapshot instance.
89.226 + ///
89.227 + ///\warning Node splitting cannot be restored.
89.228 + ///\warning The validity of the snapshot is not stored due to
89.229 + ///performance reasons. If you do not use the snapshot correctly,
89.230 + ///it can cause broken program, invalid or not restored state of
89.231 + ///the digraph or no change.
89.232 class Snapshot
89.233 {
89.234 SmartDigraph *_graph;
89.235 @@ -357,39 +355,32 @@
89.236 ///Default constructor.
89.237
89.238 ///Default constructor.
89.239 - ///To actually make a snapshot you must call save().
89.240 - ///
89.241 + ///You have to call save() to actually make a snapshot.
89.242 Snapshot() : _graph(0) {}
89.243 ///Constructor that immediately makes a snapshot
89.244
89.245 - ///This constructor immediately makes a snapshot of the digraph.
89.246 - ///\param graph The digraph we make a snapshot of.
89.247 - Snapshot(SmartDigraph &graph) : _graph(&graph) {
89.248 + ///This constructor immediately makes a snapshot of the given digraph.
89.249 + ///
89.250 + Snapshot(SmartDigraph &gr) : _graph(&gr) {
89.251 node_num=_graph->nodes.size();
89.252 arc_num=_graph->arcs.size();
89.253 }
89.254
89.255 ///Make a snapshot.
89.256
89.257 - ///Make a snapshot of the digraph.
89.258 - ///
89.259 - ///This function can be called more than once. In case of a repeated
89.260 + ///This function makes a snapshot of the given digraph.
89.261 + ///It can be called more than once. In case of a repeated
89.262 ///call, the previous snapshot gets lost.
89.263 - ///\param graph The digraph we make the snapshot of.
89.264 - void save(SmartDigraph &graph)
89.265 - {
89.266 - _graph=&graph;
89.267 + void save(SmartDigraph &gr) {
89.268 + _graph=&gr;
89.269 node_num=_graph->nodes.size();
89.270 arc_num=_graph->arcs.size();
89.271 }
89.272
89.273 ///Undo the changes until a snapshot.
89.274
89.275 - ///Undo the changes until a snapshot created by save().
89.276 - ///
89.277 - ///\note After you restored a state, you cannot restore
89.278 - ///a later state, in other word you cannot add again the arcs deleted
89.279 - ///by restore().
89.280 + ///This function undos the changes until the last snapshot
89.281 + ///created by save() or Snapshot(SmartDigraph&).
89.282 void restore()
89.283 {
89.284 _graph->restoreSnapshot(*this);
89.285 @@ -508,7 +499,7 @@
89.286 node._id = nodes.size() - 1;
89.287 }
89.288
89.289 - void next(Node& node) const {
89.290 + static void next(Node& node) {
89.291 --node._id;
89.292 }
89.293
89.294 @@ -516,7 +507,7 @@
89.295 arc._id = arcs.size() - 1;
89.296 }
89.297
89.298 - void next(Arc& arc) const {
89.299 + static void next(Arc& arc) {
89.300 --arc._id;
89.301 }
89.302
89.303 @@ -524,7 +515,7 @@
89.304 arc._id = arcs.size() / 2 - 1;
89.305 }
89.306
89.307 - void next(Edge& arc) const {
89.308 + static void next(Edge& arc) {
89.309 --arc._id;
89.310 }
89.311
89.312 @@ -621,29 +612,28 @@
89.313 ///
89.314 /// \brief A smart undirected graph class.
89.315 ///
89.316 - /// This is a simple and fast graph implementation.
89.317 - /// It is also quite memory efficient, but at the price
89.318 - /// that <b> it does support only limited (only stack-like)
89.319 - /// node and arc deletions</b>.
89.320 - /// It fully conforms to the \ref concepts::Graph "Graph concept".
89.321 + /// \ref SmartGraph is a simple and fast graph implementation.
89.322 + /// It is also quite memory efficient but at the price
89.323 + /// that it does not support node and edge deletion
89.324 + /// (except for the Snapshot feature).
89.325 ///
89.326 - /// \sa concepts::Graph.
89.327 + /// This type fully conforms to the \ref concepts::Graph "Graph concept"
89.328 + /// and it also provides some additional functionalities.
89.329 + /// Most of its member functions and nested classes are documented
89.330 + /// only in the concept class.
89.331 + ///
89.332 + /// This class provides constant time counting for nodes, edges and arcs.
89.333 + ///
89.334 + /// \sa concepts::Graph
89.335 + /// \sa SmartDigraph
89.336 class SmartGraph : public ExtendedSmartGraphBase {
89.337 typedef ExtendedSmartGraphBase Parent;
89.338
89.339 private:
89.340 -
89.341 - ///SmartGraph is \e not copy constructible. Use GraphCopy() instead.
89.342 -
89.343 - ///SmartGraph is \e not copy constructible. Use GraphCopy() instead.
89.344 - ///
89.345 + /// Graphs are \e not copy constructible. Use GraphCopy instead.
89.346 SmartGraph(const SmartGraph &) : ExtendedSmartGraphBase() {};
89.347 -
89.348 - ///\brief Assignment of SmartGraph to another one is \e not allowed.
89.349 - ///Use GraphCopy() instead.
89.350 -
89.351 - ///Assignment of SmartGraph to another one is \e not allowed.
89.352 - ///Use GraphCopy() instead.
89.353 + /// \brief Assignment of a graph to another one is \e not allowed.
89.354 + /// Use GraphCopy instead.
89.355 void operator=(const SmartGraph &) {}
89.356
89.357 public:
89.358 @@ -654,56 +644,77 @@
89.359 ///
89.360 SmartGraph() {}
89.361
89.362 - ///Add a new node to the graph.
89.363 -
89.364 - /// Add a new node to the graph.
89.365 + /// \brief Add a new node to the graph.
89.366 + ///
89.367 + /// This function adds a new node to the graph.
89.368 /// \return The new node.
89.369 Node addNode() { return Parent::addNode(); }
89.370
89.371 - ///Add a new edge to the graph.
89.372 -
89.373 - ///Add a new edge to the graph with node \c s
89.374 - ///and \c t.
89.375 - ///\return The new edge.
89.376 - Edge addEdge(const Node& s, const Node& t) {
89.377 - return Parent::addEdge(s, t);
89.378 + /// \brief Add a new edge to the graph.
89.379 + ///
89.380 + /// This function adds a new edge to the graph between nodes
89.381 + /// \c u and \c v with inherent orientation from node \c u to
89.382 + /// node \c v.
89.383 + /// \return The new edge.
89.384 + Edge addEdge(Node u, Node v) {
89.385 + return Parent::addEdge(u, v);
89.386 }
89.387
89.388 /// \brief Node validity check
89.389 ///
89.390 - /// This function gives back true if the given node is valid,
89.391 - /// ie. it is a real node of the graph.
89.392 + /// This function gives back \c true if the given node is valid,
89.393 + /// i.e. it is a real node of the graph.
89.394 ///
89.395 /// \warning A removed node (using Snapshot) could become valid again
89.396 - /// when new nodes are added to the graph.
89.397 + /// if new nodes are added to the graph.
89.398 bool valid(Node n) const { return Parent::valid(n); }
89.399
89.400 + /// \brief Edge validity check
89.401 + ///
89.402 + /// This function gives back \c true if the given edge is valid,
89.403 + /// i.e. it is a real edge of the graph.
89.404 + ///
89.405 + /// \warning A removed edge (using Snapshot) could become valid again
89.406 + /// if new edges are added to the graph.
89.407 + bool valid(Edge e) const { return Parent::valid(e); }
89.408 +
89.409 /// \brief Arc validity check
89.410 ///
89.411 - /// This function gives back true if the given arc is valid,
89.412 - /// ie. it is a real arc of the graph.
89.413 + /// This function gives back \c true if the given arc is valid,
89.414 + /// i.e. it is a real arc of the graph.
89.415 ///
89.416 /// \warning A removed arc (using Snapshot) could become valid again
89.417 - /// when new edges are added to the graph.
89.418 + /// if new edges are added to the graph.
89.419 bool valid(Arc a) const { return Parent::valid(a); }
89.420
89.421 - /// \brief Edge validity check
89.422 - ///
89.423 - /// This function gives back true if the given edge is valid,
89.424 - /// ie. it is a real edge of the graph.
89.425 - ///
89.426 - /// \warning A removed edge (using Snapshot) could become valid again
89.427 - /// when new edges are added to the graph.
89.428 - bool valid(Edge e) const { return Parent::valid(e); }
89.429 -
89.430 ///Clear the graph.
89.431
89.432 - ///Erase all the nodes and edges from the graph.
89.433 + ///This function erases all nodes and arcs from the graph.
89.434 ///
89.435 void clear() {
89.436 Parent::clear();
89.437 }
89.438
89.439 + /// Reserve memory for nodes.
89.440 +
89.441 + /// Using this function, it is possible to avoid superfluous memory
89.442 + /// allocation: if you know that the graph you want to build will
89.443 + /// be large (e.g. it will contain millions of nodes and/or edges),
89.444 + /// then it is worth reserving space for this amount before starting
89.445 + /// to build the graph.
89.446 + /// \sa reserveEdge()
89.447 + void reserveNode(int n) { nodes.reserve(n); };
89.448 +
89.449 + /// Reserve memory for edges.
89.450 +
89.451 + /// Using this function, it is possible to avoid superfluous memory
89.452 + /// allocation: if you know that the graph you want to build will
89.453 + /// be large (e.g. it will contain millions of nodes and/or edges),
89.454 + /// then it is worth reserving space for this amount before starting
89.455 + /// to build the graph.
89.456 + /// \sa reserveNode()
89.457 + void reserveEdge(int m) { arcs.reserve(2 * m); };
89.458 +
89.459 public:
89.460
89.461 class Snapshot;
89.462 @@ -742,21 +753,22 @@
89.463
89.464 public:
89.465
89.466 - ///Class to make a snapshot of the digraph and to restrore to it later.
89.467 + ///Class to make a snapshot of the graph and to restore it later.
89.468
89.469 - ///Class to make a snapshot of the digraph and to restrore to it later.
89.470 + ///Class to make a snapshot of the graph and to restore it later.
89.471 ///
89.472 - ///The newly added nodes and arcs can be removed using the
89.473 - ///restore() function.
89.474 + ///The newly added nodes and edges can be removed using the
89.475 + ///restore() function. This is the only way for deleting nodes and/or
89.476 + ///edges from a SmartGraph structure.
89.477 ///
89.478 - ///\note After you restore a state, you cannot restore
89.479 - ///a later state, in other word you cannot add again the arcs deleted
89.480 - ///by restore() using another one Snapshot instance.
89.481 + ///\note After a state is restored, you cannot restore a later state,
89.482 + ///i.e. you cannot add the removed nodes and edges again using
89.483 + ///another Snapshot instance.
89.484 ///
89.485 - ///\warning If you do not use correctly the snapshot that can cause
89.486 - ///either broken program, invalid state of the digraph, valid but
89.487 - ///not the restored digraph or no change. Because the runtime performance
89.488 - ///the validity of the snapshot is not stored.
89.489 + ///\warning The validity of the snapshot is not stored due to
89.490 + ///performance reasons. If you do not use the snapshot correctly,
89.491 + ///it can cause broken program, invalid or not restored state of
89.492 + ///the graph or no change.
89.493 class Snapshot
89.494 {
89.495 SmartGraph *_graph;
89.496 @@ -768,36 +780,30 @@
89.497 ///Default constructor.
89.498
89.499 ///Default constructor.
89.500 - ///To actually make a snapshot you must call save().
89.501 - ///
89.502 + ///You have to call save() to actually make a snapshot.
89.503 Snapshot() : _graph(0) {}
89.504 ///Constructor that immediately makes a snapshot
89.505
89.506 - ///This constructor immediately makes a snapshot of the digraph.
89.507 - ///\param graph The digraph we make a snapshot of.
89.508 - Snapshot(SmartGraph &graph) {
89.509 - graph.saveSnapshot(*this);
89.510 + /// This constructor immediately makes a snapshot of the given graph.
89.511 + ///
89.512 + Snapshot(SmartGraph &gr) {
89.513 + gr.saveSnapshot(*this);
89.514 }
89.515
89.516 ///Make a snapshot.
89.517
89.518 - ///Make a snapshot of the graph.
89.519 - ///
89.520 - ///This function can be called more than once. In case of a repeated
89.521 + ///This function makes a snapshot of the given graph.
89.522 + ///It can be called more than once. In case of a repeated
89.523 ///call, the previous snapshot gets lost.
89.524 - ///\param graph The digraph we make the snapshot of.
89.525 - void save(SmartGraph &graph)
89.526 + void save(SmartGraph &gr)
89.527 {
89.528 - graph.saveSnapshot(*this);
89.529 + gr.saveSnapshot(*this);
89.530 }
89.531
89.532 - ///Undo the changes until a snapshot.
89.533 + ///Undo the changes until the last snapshot.
89.534
89.535 - ///Undo the changes until a snapshot created by save().
89.536 - ///
89.537 - ///\note After you restored a state, you cannot restore
89.538 - ///a later state, in other word you cannot add again the arcs deleted
89.539 - ///by restore().
89.540 + ///This function undos the changes until the last snapshot
89.541 + ///created by save() or Snapshot(SmartGraph&).
89.542 void restore()
89.543 {
89.544 _graph->restoreSnapshot(*this);
90.1 --- a/lemon/soplex.cc Tue Dec 20 17:44:38 2011 +0100
90.2 +++ b/lemon/soplex.cc Tue Dec 20 18:15:14 2011 +0100
90.3 @@ -2,7 +2,7 @@
90.4 *
90.5 * This file is a part of LEMON, a generic C++ optimization library.
90.6 *
90.7 - * Copyright (C) 2003-2008
90.8 + * Copyright (C) 2003-2010
90.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
90.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
90.11 *
90.12 @@ -91,6 +91,19 @@
90.13 return soplex->nRows() - 1;
90.14 }
90.15
90.16 + int SoplexLp::_addRow(Value l, ExprIterator b, ExprIterator e, Value u) {
90.17 + soplex::DSVector v;
90.18 + for (ExprIterator it = b; it != e; ++it) {
90.19 + v.add(it->first, it->second);
90.20 + }
90.21 + soplex::LPRow r(l, v, u);
90.22 + soplex->addRow(r);
90.23 +
90.24 + _row_names.push_back(std::string());
90.25 +
90.26 + return soplex->nRows() - 1;
90.27 + }
90.28 +
90.29
90.30 void SoplexLp::_eraseCol(int i) {
90.31 soplex->removeCol(i);
90.32 @@ -274,7 +287,7 @@
90.33 SoplexLp::SolveExitStatus SoplexLp::_solve() {
90.34
90.35 _clear_temporals();
90.36 -
90.37 +
90.38 _applyMessageLevel();
90.39
90.40 soplex::SPxSolver::Status status = soplex->solve();
91.1 --- a/lemon/soplex.h Tue Dec 20 17:44:38 2011 +0100
91.2 +++ b/lemon/soplex.h Tue Dec 20 18:15:14 2011 +0100
91.3 @@ -2,7 +2,7 @@
91.4 *
91.5 * This file is a part of LEMON, a generic C++ optimization library.
91.6 *
91.7 - * Copyright (C) 2003-2008
91.8 + * Copyright (C) 2003-2010
91.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
91.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
91.11 *
91.12 @@ -84,6 +84,7 @@
91.13
91.14 virtual int _addCol();
91.15 virtual int _addRow();
91.16 + virtual int _addRow(Value l, ExprIterator b, ExprIterator e, Value u);
91.17
91.18 virtual void _eraseCol(int i);
91.19 virtual void _eraseRow(int i);
92.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
92.2 +++ b/lemon/static_graph.h Tue Dec 20 18:15:14 2011 +0100
92.3 @@ -0,0 +1,476 @@
92.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
92.5 + *
92.6 + * This file is a part of LEMON, a generic C++ optimization library.
92.7 + *
92.8 + * Copyright (C) 2003-2010
92.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
92.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
92.11 + *
92.12 + * Permission to use, modify and distribute this software is granted
92.13 + * provided that this copyright notice appears in all copies. For
92.14 + * precise terms see the accompanying LICENSE file.
92.15 + *
92.16 + * This software is provided "AS IS" with no warranty of any kind,
92.17 + * express or implied, and with no claim as to its suitability for any
92.18 + * purpose.
92.19 + *
92.20 + */
92.21 +
92.22 +#ifndef LEMON_STATIC_GRAPH_H
92.23 +#define LEMON_STATIC_GRAPH_H
92.24 +
92.25 +///\ingroup graphs
92.26 +///\file
92.27 +///\brief StaticDigraph class.
92.28 +
92.29 +#include <lemon/core.h>
92.30 +#include <lemon/bits/graph_extender.h>
92.31 +
92.32 +namespace lemon {
92.33 +
92.34 + class StaticDigraphBase {
92.35 + public:
92.36 +
92.37 + StaticDigraphBase()
92.38 + : built(false), node_num(0), arc_num(0),
92.39 + node_first_out(NULL), node_first_in(NULL),
92.40 + arc_source(NULL), arc_target(NULL),
92.41 + arc_next_in(NULL), arc_next_out(NULL) {}
92.42 +
92.43 + ~StaticDigraphBase() {
92.44 + if (built) {
92.45 + delete[] node_first_out;
92.46 + delete[] node_first_in;
92.47 + delete[] arc_source;
92.48 + delete[] arc_target;
92.49 + delete[] arc_next_out;
92.50 + delete[] arc_next_in;
92.51 + }
92.52 + }
92.53 +
92.54 + class Node {
92.55 + friend class StaticDigraphBase;
92.56 + protected:
92.57 + int id;
92.58 + Node(int _id) : id(_id) {}
92.59 + public:
92.60 + Node() {}
92.61 + Node (Invalid) : id(-1) {}
92.62 + bool operator==(const Node& node) const { return id == node.id; }
92.63 + bool operator!=(const Node& node) const { return id != node.id; }
92.64 + bool operator<(const Node& node) const { return id < node.id; }
92.65 + };
92.66 +
92.67 + class Arc {
92.68 + friend class StaticDigraphBase;
92.69 + protected:
92.70 + int id;
92.71 + Arc(int _id) : id(_id) {}
92.72 + public:
92.73 + Arc() { }
92.74 + Arc (Invalid) : id(-1) {}
92.75 + bool operator==(const Arc& arc) const { return id == arc.id; }
92.76 + bool operator!=(const Arc& arc) const { return id != arc.id; }
92.77 + bool operator<(const Arc& arc) const { return id < arc.id; }
92.78 + };
92.79 +
92.80 + Node source(const Arc& e) const { return Node(arc_source[e.id]); }
92.81 + Node target(const Arc& e) const { return Node(arc_target[e.id]); }
92.82 +
92.83 + void first(Node& n) const { n.id = node_num - 1; }
92.84 + static void next(Node& n) { --n.id; }
92.85 +
92.86 + void first(Arc& e) const { e.id = arc_num - 1; }
92.87 + static void next(Arc& e) { --e.id; }
92.88 +
92.89 + void firstOut(Arc& e, const Node& n) const {
92.90 + e.id = node_first_out[n.id] != node_first_out[n.id + 1] ?
92.91 + node_first_out[n.id] : -1;
92.92 + }
92.93 + void nextOut(Arc& e) const { e.id = arc_next_out[e.id]; }
92.94 +
92.95 + void firstIn(Arc& e, const Node& n) const { e.id = node_first_in[n.id]; }
92.96 + void nextIn(Arc& e) const { e.id = arc_next_in[e.id]; }
92.97 +
92.98 + static int id(const Node& n) { return n.id; }
92.99 + static Node nodeFromId(int id) { return Node(id); }
92.100 + int maxNodeId() const { return node_num - 1; }
92.101 +
92.102 + static int id(const Arc& e) { return e.id; }
92.103 + static Arc arcFromId(int id) { return Arc(id); }
92.104 + int maxArcId() const { return arc_num - 1; }
92.105 +
92.106 + typedef True NodeNumTag;
92.107 + typedef True ArcNumTag;
92.108 +
92.109 + int nodeNum() const { return node_num; }
92.110 + int arcNum() const { return arc_num; }
92.111 +
92.112 + private:
92.113 +
92.114 + template <typename Digraph, typename NodeRefMap>
92.115 + class ArcLess {
92.116 + public:
92.117 + typedef typename Digraph::Arc Arc;
92.118 +
92.119 + ArcLess(const Digraph &_graph, const NodeRefMap& _nodeRef)
92.120 + : digraph(_graph), nodeRef(_nodeRef) {}
92.121 +
92.122 + bool operator()(const Arc& left, const Arc& right) const {
92.123 + return nodeRef[digraph.target(left)] < nodeRef[digraph.target(right)];
92.124 + }
92.125 + private:
92.126 + const Digraph& digraph;
92.127 + const NodeRefMap& nodeRef;
92.128 + };
92.129 +
92.130 + public:
92.131 +
92.132 + typedef True BuildTag;
92.133 +
92.134 + void clear() {
92.135 + if (built) {
92.136 + delete[] node_first_out;
92.137 + delete[] node_first_in;
92.138 + delete[] arc_source;
92.139 + delete[] arc_target;
92.140 + delete[] arc_next_out;
92.141 + delete[] arc_next_in;
92.142 + }
92.143 + built = false;
92.144 + node_num = 0;
92.145 + arc_num = 0;
92.146 + }
92.147 +
92.148 + template <typename Digraph, typename NodeRefMap, typename ArcRefMap>
92.149 + void build(const Digraph& digraph, NodeRefMap& nodeRef, ArcRefMap& arcRef) {
92.150 + typedef typename Digraph::Node GNode;
92.151 + typedef typename Digraph::Arc GArc;
92.152 +
92.153 + built = true;
92.154 +
92.155 + node_num = countNodes(digraph);
92.156 + arc_num = countArcs(digraph);
92.157 +
92.158 + node_first_out = new int[node_num + 1];
92.159 + node_first_in = new int[node_num];
92.160 +
92.161 + arc_source = new int[arc_num];
92.162 + arc_target = new int[arc_num];
92.163 + arc_next_out = new int[arc_num];
92.164 + arc_next_in = new int[arc_num];
92.165 +
92.166 + int node_index = 0;
92.167 + for (typename Digraph::NodeIt n(digraph); n != INVALID; ++n) {
92.168 + nodeRef[n] = Node(node_index);
92.169 + node_first_in[node_index] = -1;
92.170 + ++node_index;
92.171 + }
92.172 +
92.173 + ArcLess<Digraph, NodeRefMap> arcLess(digraph, nodeRef);
92.174 +
92.175 + int arc_index = 0;
92.176 + for (typename Digraph::NodeIt n(digraph); n != INVALID; ++n) {
92.177 + int source = nodeRef[n].id;
92.178 + std::vector<GArc> arcs;
92.179 + for (typename Digraph::OutArcIt e(digraph, n); e != INVALID; ++e) {
92.180 + arcs.push_back(e);
92.181 + }
92.182 + if (!arcs.empty()) {
92.183 + node_first_out[source] = arc_index;
92.184 + std::sort(arcs.begin(), arcs.end(), arcLess);
92.185 + for (typename std::vector<GArc>::iterator it = arcs.begin();
92.186 + it != arcs.end(); ++it) {
92.187 + int target = nodeRef[digraph.target(*it)].id;
92.188 + arcRef[*it] = Arc(arc_index);
92.189 + arc_source[arc_index] = source;
92.190 + arc_target[arc_index] = target;
92.191 + arc_next_in[arc_index] = node_first_in[target];
92.192 + node_first_in[target] = arc_index;
92.193 + arc_next_out[arc_index] = arc_index + 1;
92.194 + ++arc_index;
92.195 + }
92.196 + arc_next_out[arc_index - 1] = -1;
92.197 + } else {
92.198 + node_first_out[source] = arc_index;
92.199 + }
92.200 + }
92.201 + node_first_out[node_num] = arc_num;
92.202 + }
92.203 +
92.204 + template <typename ArcListIterator>
92.205 + void build(int n, ArcListIterator first, ArcListIterator last) {
92.206 + built = true;
92.207 +
92.208 + node_num = n;
92.209 + arc_num = std::distance(first, last);
92.210 +
92.211 + node_first_out = new int[node_num + 1];
92.212 + node_first_in = new int[node_num];
92.213 +
92.214 + arc_source = new int[arc_num];
92.215 + arc_target = new int[arc_num];
92.216 + arc_next_out = new int[arc_num];
92.217 + arc_next_in = new int[arc_num];
92.218 +
92.219 + for (int i = 0; i != node_num; ++i) {
92.220 + node_first_in[i] = -1;
92.221 + }
92.222 +
92.223 + int arc_index = 0;
92.224 + for (int i = 0; i != node_num; ++i) {
92.225 + node_first_out[i] = arc_index;
92.226 + for ( ; first != last && (*first).first == i; ++first) {
92.227 + int j = (*first).second;
92.228 + LEMON_ASSERT(j >= 0 && j < node_num,
92.229 + "Wrong arc list for StaticDigraph::build()");
92.230 + arc_source[arc_index] = i;
92.231 + arc_target[arc_index] = j;
92.232 + arc_next_in[arc_index] = node_first_in[j];
92.233 + node_first_in[j] = arc_index;
92.234 + arc_next_out[arc_index] = arc_index + 1;
92.235 + ++arc_index;
92.236 + }
92.237 + if (arc_index > node_first_out[i])
92.238 + arc_next_out[arc_index - 1] = -1;
92.239 + }
92.240 + LEMON_ASSERT(first == last,
92.241 + "Wrong arc list for StaticDigraph::build()");
92.242 + node_first_out[node_num] = arc_num;
92.243 + }
92.244 +
92.245 + protected:
92.246 +
92.247 + void fastFirstOut(Arc& e, const Node& n) const {
92.248 + e.id = node_first_out[n.id];
92.249 + }
92.250 +
92.251 + static void fastNextOut(Arc& e) {
92.252 + ++e.id;
92.253 + }
92.254 + void fastLastOut(Arc& e, const Node& n) const {
92.255 + e.id = node_first_out[n.id + 1];
92.256 + }
92.257 +
92.258 + protected:
92.259 + bool built;
92.260 + int node_num;
92.261 + int arc_num;
92.262 + int *node_first_out;
92.263 + int *node_first_in;
92.264 + int *arc_source;
92.265 + int *arc_target;
92.266 + int *arc_next_in;
92.267 + int *arc_next_out;
92.268 + };
92.269 +
92.270 + typedef DigraphExtender<StaticDigraphBase> ExtendedStaticDigraphBase;
92.271 +
92.272 +
92.273 + /// \ingroup graphs
92.274 + ///
92.275 + /// \brief A static directed graph class.
92.276 + ///
92.277 + /// \ref StaticDigraph is a highly efficient digraph implementation,
92.278 + /// but it is fully static.
92.279 + /// It stores only two \c int values for each node and only four \c int
92.280 + /// values for each arc. Moreover it provides faster item iteration than
92.281 + /// \ref ListDigraph and \ref SmartDigraph, especially using \c OutArcIt
92.282 + /// iterators, since its arcs are stored in an appropriate order.
92.283 + /// However it only provides build() and clear() functions and does not
92.284 + /// support any other modification of the digraph.
92.285 + ///
92.286 + /// Since this digraph structure is completely static, its nodes and arcs
92.287 + /// can be indexed with integers from the ranges <tt>[0..nodeNum()-1]</tt>
92.288 + /// and <tt>[0..arcNum()-1]</tt>, respectively.
92.289 + /// The index of an item is the same as its ID, it can be obtained
92.290 + /// using the corresponding \ref index() or \ref concepts::Digraph::id()
92.291 + /// "id()" function. A node or arc with a certain index can be obtained
92.292 + /// using node() or arc().
92.293 + ///
92.294 + /// This type fully conforms to the \ref concepts::Digraph "Digraph concept".
92.295 + /// Most of its member functions and nested classes are documented
92.296 + /// only in the concept class.
92.297 + ///
92.298 + /// This class provides constant time counting for nodes and arcs.
92.299 + ///
92.300 + /// \sa concepts::Digraph
92.301 + class StaticDigraph : public ExtendedStaticDigraphBase {
92.302 + public:
92.303 +
92.304 + typedef ExtendedStaticDigraphBase Parent;
92.305 +
92.306 + public:
92.307 +
92.308 + /// \brief Constructor
92.309 + ///
92.310 + /// Default constructor.
92.311 + StaticDigraph() : Parent() {}
92.312 +
92.313 + /// \brief The node with the given index.
92.314 + ///
92.315 + /// This function returns the node with the given index.
92.316 + /// \sa index()
92.317 + static Node node(int ix) { return Parent::nodeFromId(ix); }
92.318 +
92.319 + /// \brief The arc with the given index.
92.320 + ///
92.321 + /// This function returns the arc with the given index.
92.322 + /// \sa index()
92.323 + static Arc arc(int ix) { return Parent::arcFromId(ix); }
92.324 +
92.325 + /// \brief The index of the given node.
92.326 + ///
92.327 + /// This function returns the index of the the given node.
92.328 + /// \sa node()
92.329 + static int index(Node node) { return Parent::id(node); }
92.330 +
92.331 + /// \brief The index of the given arc.
92.332 + ///
92.333 + /// This function returns the index of the the given arc.
92.334 + /// \sa arc()
92.335 + static int index(Arc arc) { return Parent::id(arc); }
92.336 +
92.337 + /// \brief Number of nodes.
92.338 + ///
92.339 + /// This function returns the number of nodes.
92.340 + int nodeNum() const { return node_num; }
92.341 +
92.342 + /// \brief Number of arcs.
92.343 + ///
92.344 + /// This function returns the number of arcs.
92.345 + int arcNum() const { return arc_num; }
92.346 +
92.347 + /// \brief Build the digraph copying another digraph.
92.348 + ///
92.349 + /// This function builds the digraph copying another digraph of any
92.350 + /// kind. It can be called more than once, but in such case, the whole
92.351 + /// structure and all maps will be cleared and rebuilt.
92.352 + ///
92.353 + /// This method also makes possible to copy a digraph to a StaticDigraph
92.354 + /// structure using \ref DigraphCopy.
92.355 + ///
92.356 + /// \param digraph An existing digraph to be copied.
92.357 + /// \param nodeRef The node references will be copied into this map.
92.358 + /// Its key type must be \c Digraph::Node and its value type must be
92.359 + /// \c StaticDigraph::Node.
92.360 + /// It must conform to the \ref concepts::ReadWriteMap "ReadWriteMap"
92.361 + /// concept.
92.362 + /// \param arcRef The arc references will be copied into this map.
92.363 + /// Its key type must be \c Digraph::Arc and its value type must be
92.364 + /// \c StaticDigraph::Arc.
92.365 + /// It must conform to the \ref concepts::WriteMap "WriteMap" concept.
92.366 + ///
92.367 + /// \note If you do not need the arc references, then you could use
92.368 + /// \ref NullMap for the last parameter. However the node references
92.369 + /// are required by the function itself, thus they must be readable
92.370 + /// from the map.
92.371 + template <typename Digraph, typename NodeRefMap, typename ArcRefMap>
92.372 + void build(const Digraph& digraph, NodeRefMap& nodeRef, ArcRefMap& arcRef) {
92.373 + if (built) Parent::clear();
92.374 + Parent::build(digraph, nodeRef, arcRef);
92.375 + }
92.376 +
92.377 + /// \brief Build the digraph from an arc list.
92.378 + ///
92.379 + /// This function builds the digraph from the given arc list.
92.380 + /// It can be called more than once, but in such case, the whole
92.381 + /// structure and all maps will be cleared and rebuilt.
92.382 + ///
92.383 + /// The list of the arcs must be given in the range <tt>[begin, end)</tt>
92.384 + /// specified by STL compatible itartors whose \c value_type must be
92.385 + /// <tt>std::pair<int,int></tt>.
92.386 + /// Each arc must be specified by a pair of integer indices
92.387 + /// from the range <tt>[0..n-1]</tt>. <i>The pairs must be in a
92.388 + /// non-decreasing order with respect to their first values.</i>
92.389 + /// If the k-th pair in the list is <tt>(i,j)</tt>, then
92.390 + /// <tt>arc(k-1)</tt> will connect <tt>node(i)</tt> to <tt>node(j)</tt>.
92.391 + ///
92.392 + /// \param n The number of nodes.
92.393 + /// \param begin An iterator pointing to the beginning of the arc list.
92.394 + /// \param end An iterator pointing to the end of the arc list.
92.395 + ///
92.396 + /// For example, a simple digraph can be constructed like this.
92.397 + /// \code
92.398 + /// std::vector<std::pair<int,int> > arcs;
92.399 + /// arcs.push_back(std::make_pair(0,1));
92.400 + /// arcs.push_back(std::make_pair(0,2));
92.401 + /// arcs.push_back(std::make_pair(1,3));
92.402 + /// arcs.push_back(std::make_pair(1,2));
92.403 + /// arcs.push_back(std::make_pair(3,0));
92.404 + /// StaticDigraph gr;
92.405 + /// gr.build(4, arcs.begin(), arcs.end());
92.406 + /// \endcode
92.407 + template <typename ArcListIterator>
92.408 + void build(int n, ArcListIterator begin, ArcListIterator end) {
92.409 + if (built) Parent::clear();
92.410 + StaticDigraphBase::build(n, begin, end);
92.411 + notifier(Node()).build();
92.412 + notifier(Arc()).build();
92.413 + }
92.414 +
92.415 + /// \brief Clear the digraph.
92.416 + ///
92.417 + /// This function erases all nodes and arcs from the digraph.
92.418 + void clear() {
92.419 + Parent::clear();
92.420 + }
92.421 +
92.422 + protected:
92.423 +
92.424 + using Parent::fastFirstOut;
92.425 + using Parent::fastNextOut;
92.426 + using Parent::fastLastOut;
92.427 +
92.428 + public:
92.429 +
92.430 + class OutArcIt : public Arc {
92.431 + public:
92.432 +
92.433 + OutArcIt() { }
92.434 +
92.435 + OutArcIt(Invalid i) : Arc(i) { }
92.436 +
92.437 + OutArcIt(const StaticDigraph& digraph, const Node& node) {
92.438 + digraph.fastFirstOut(*this, node);
92.439 + digraph.fastLastOut(last, node);
92.440 + if (last == *this) *this = INVALID;
92.441 + }
92.442 +
92.443 + OutArcIt(const StaticDigraph& digraph, const Arc& arc) : Arc(arc) {
92.444 + if (arc != INVALID) {
92.445 + digraph.fastLastOut(last, digraph.source(arc));
92.446 + }
92.447 + }
92.448 +
92.449 + OutArcIt& operator++() {
92.450 + StaticDigraph::fastNextOut(*this);
92.451 + if (last == *this) *this = INVALID;
92.452 + return *this;
92.453 + }
92.454 +
92.455 + private:
92.456 + Arc last;
92.457 + };
92.458 +
92.459 + Node baseNode(const OutArcIt &arc) const {
92.460 + return Parent::source(static_cast<const Arc&>(arc));
92.461 + }
92.462 +
92.463 + Node runningNode(const OutArcIt &arc) const {
92.464 + return Parent::target(static_cast<const Arc&>(arc));
92.465 + }
92.466 +
92.467 + Node baseNode(const InArcIt &arc) const {
92.468 + return Parent::target(static_cast<const Arc&>(arc));
92.469 + }
92.470 +
92.471 + Node runningNode(const InArcIt &arc) const {
92.472 + return Parent::source(static_cast<const Arc&>(arc));
92.473 + }
92.474 +
92.475 + };
92.476 +
92.477 +}
92.478 +
92.479 +#endif
93.1 --- a/lemon/suurballe.h Tue Dec 20 17:44:38 2011 +0100
93.2 +++ b/lemon/suurballe.h Tue Dec 20 18:15:14 2011 +0100
93.3 @@ -2,7 +2,7 @@
93.4 *
93.5 * This file is a part of LEMON, a generic C++ optimization library.
93.6 *
93.7 - * Copyright (C) 2003-2009
93.8 + * Copyright (C) 2003-2010
93.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
93.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
93.11 *
93.12 @@ -29,10 +29,54 @@
93.13 #include <lemon/bin_heap.h>
93.14 #include <lemon/path.h>
93.15 #include <lemon/list_graph.h>
93.16 +#include <lemon/dijkstra.h>
93.17 #include <lemon/maps.h>
93.18
93.19 namespace lemon {
93.20
93.21 + /// \brief Default traits class of Suurballe algorithm.
93.22 + ///
93.23 + /// Default traits class of Suurballe algorithm.
93.24 + /// \tparam GR The digraph type the algorithm runs on.
93.25 + /// \tparam LEN The type of the length map.
93.26 + /// The default value is <tt>GR::ArcMap<int></tt>.
93.27 +#ifdef DOXYGEN
93.28 + template <typename GR, typename LEN>
93.29 +#else
93.30 + template < typename GR,
93.31 + typename LEN = typename GR::template ArcMap<int> >
93.32 +#endif
93.33 + struct SuurballeDefaultTraits
93.34 + {
93.35 + /// The type of the digraph.
93.36 + typedef GR Digraph;
93.37 + /// The type of the length map.
93.38 + typedef LEN LengthMap;
93.39 + /// The type of the lengths.
93.40 + typedef typename LEN::Value Length;
93.41 + /// The type of the flow map.
93.42 + typedef typename GR::template ArcMap<int> FlowMap;
93.43 + /// The type of the potential map.
93.44 + typedef typename GR::template NodeMap<Length> PotentialMap;
93.45 +
93.46 + /// \brief The path type
93.47 + ///
93.48 + /// The type used for storing the found arc-disjoint paths.
93.49 + /// It must conform to the \ref lemon::concepts::Path "Path" concept
93.50 + /// and it must have an \c addBack() function.
93.51 + typedef lemon::Path<Digraph> Path;
93.52 +
93.53 + /// The cross reference type used for the heap.
93.54 + typedef typename GR::template NodeMap<int> HeapCrossRef;
93.55 +
93.56 + /// \brief The heap type used for internal Dijkstra computations.
93.57 + ///
93.58 + /// The type of the heap used for internal Dijkstra computations.
93.59 + /// It must conform to the \ref lemon::concepts::Heap "Heap" concept
93.60 + /// and its priority type must be \c Length.
93.61 + typedef BinHeap<Length, HeapCrossRef> Heap;
93.62 + };
93.63 +
93.64 /// \addtogroup shortest_path
93.65 /// @{
93.66
93.67 @@ -46,7 +90,7 @@
93.68 /// Note that this problem is a special case of the \ref min_cost_flow
93.69 /// "minimum cost flow problem". This implementation is actually an
93.70 /// efficient specialized version of the \ref CapacityScaling
93.71 - /// "Successive Shortest Path" algorithm directly for this problem.
93.72 + /// "successive shortest path" algorithm directly for this problem.
93.73 /// Therefore this class provides query functions for flow values and
93.74 /// node potentials (the dual solution) just like the minimum cost flow
93.75 /// algorithms.
93.76 @@ -57,13 +101,14 @@
93.77 ///
93.78 /// \warning Length values should be \e non-negative.
93.79 ///
93.80 - /// \note For finding node-disjoint paths this algorithm can be used
93.81 + /// \note For finding \e node-disjoint paths, this algorithm can be used
93.82 /// along with the \ref SplitNodes adaptor.
93.83 #ifdef DOXYGEN
93.84 - template <typename GR, typename LEN>
93.85 + template <typename GR, typename LEN, typename TR>
93.86 #else
93.87 template < typename GR,
93.88 - typename LEN = typename GR::template ArcMap<int> >
93.89 + typename LEN = typename GR::template ArcMap<int>,
93.90 + typename TR = SuurballeDefaultTraits<GR, LEN> >
93.91 #endif
93.92 class Suurballe
93.93 {
93.94 @@ -74,26 +119,26 @@
93.95
93.96 public:
93.97
93.98 - /// The type of the digraph the algorithm runs on.
93.99 - typedef GR Digraph;
93.100 + /// The type of the digraph.
93.101 + typedef typename TR::Digraph Digraph;
93.102 /// The type of the length map.
93.103 - typedef LEN LengthMap;
93.104 + typedef typename TR::LengthMap LengthMap;
93.105 /// The type of the lengths.
93.106 - typedef typename LengthMap::Value Length;
93.107 -#ifdef DOXYGEN
93.108 + typedef typename TR::Length Length;
93.109 +
93.110 /// The type of the flow map.
93.111 - typedef GR::ArcMap<int> FlowMap;
93.112 + typedef typename TR::FlowMap FlowMap;
93.113 /// The type of the potential map.
93.114 - typedef GR::NodeMap<Length> PotentialMap;
93.115 -#else
93.116 - /// The type of the flow map.
93.117 - typedef typename Digraph::template ArcMap<int> FlowMap;
93.118 - /// The type of the potential map.
93.119 - typedef typename Digraph::template NodeMap<Length> PotentialMap;
93.120 -#endif
93.121 + typedef typename TR::PotentialMap PotentialMap;
93.122 + /// The type of the path structures.
93.123 + typedef typename TR::Path Path;
93.124 + /// The cross reference type used for the heap.
93.125 + typedef typename TR::HeapCrossRef HeapCrossRef;
93.126 + /// The heap type used for internal Dijkstra computations.
93.127 + typedef typename TR::Heap Heap;
93.128
93.129 - /// The type of the path structures.
93.130 - typedef SimplePath<GR> Path;
93.131 + /// The \ref SuurballeDefaultTraits "traits class" of the algorithm.
93.132 + typedef TR Traits;
93.133
93.134 private:
93.135
93.136 @@ -104,44 +149,38 @@
93.137 // distance of the nodes.
93.138 class ResidualDijkstra
93.139 {
93.140 - typedef typename Digraph::template NodeMap<int> HeapCrossRef;
93.141 - typedef BinHeap<Length, HeapCrossRef> Heap;
93.142 + private:
93.143 +
93.144 + const Digraph &_graph;
93.145 + const LengthMap &_length;
93.146 + const FlowMap &_flow;
93.147 + PotentialMap &_pi;
93.148 + PredMap &_pred;
93.149 + Node _s;
93.150 + Node _t;
93.151 +
93.152 + PotentialMap _dist;
93.153 + std::vector<Node> _proc_nodes;
93.154 +
93.155 + public:
93.156 +
93.157 + // Constructor
93.158 + ResidualDijkstra(Suurballe &srb) :
93.159 + _graph(srb._graph), _length(srb._length),
93.160 + _flow(*srb._flow), _pi(*srb._potential), _pred(srb._pred),
93.161 + _s(srb._s), _t(srb._t), _dist(_graph) {}
93.162 +
93.163 + // Run the algorithm and return true if a path is found
93.164 + // from the source node to the target node.
93.165 + bool run(int cnt) {
93.166 + return cnt == 0 ? startFirst() : start();
93.167 + }
93.168
93.169 private:
93.170
93.171 - // The digraph the algorithm runs on
93.172 - const Digraph &_graph;
93.173 -
93.174 - // The main maps
93.175 - const FlowMap &_flow;
93.176 - const LengthMap &_length;
93.177 - PotentialMap &_potential;
93.178 -
93.179 - // The distance map
93.180 - PotentialMap _dist;
93.181 - // The pred arc map
93.182 - PredMap &_pred;
93.183 - // The processed (i.e. permanently labeled) nodes
93.184 - std::vector<Node> _proc_nodes;
93.185 -
93.186 - Node _s;
93.187 - Node _t;
93.188 -
93.189 - public:
93.190 -
93.191 - /// Constructor.
93.192 - ResidualDijkstra( const Digraph &graph,
93.193 - const FlowMap &flow,
93.194 - const LengthMap &length,
93.195 - PotentialMap &potential,
93.196 - PredMap &pred,
93.197 - Node s, Node t ) :
93.198 - _graph(graph), _flow(flow), _length(length), _potential(potential),
93.199 - _dist(graph), _pred(pred), _s(s), _t(t) {}
93.200 -
93.201 - /// \brief Run the algorithm. It returns \c true if a path is found
93.202 - /// from the source node to the target node.
93.203 - bool run() {
93.204 + // Execute the algorithm for the first time (the flow and potential
93.205 + // functions have to be identically zero).
93.206 + bool startFirst() {
93.207 HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
93.208 Heap heap(heap_cross_ref);
93.209 heap.push(_s, 0);
93.210 @@ -151,29 +190,74 @@
93.211 // Process nodes
93.212 while (!heap.empty() && heap.top() != _t) {
93.213 Node u = heap.top(), v;
93.214 - Length d = heap.prio() + _potential[u], nd;
93.215 + Length d = heap.prio(), dn;
93.216 _dist[u] = heap.prio();
93.217 + _proc_nodes.push_back(u);
93.218 heap.pop();
93.219 +
93.220 + // Traverse outgoing arcs
93.221 + for (OutArcIt e(_graph, u); e != INVALID; ++e) {
93.222 + v = _graph.target(e);
93.223 + switch(heap.state(v)) {
93.224 + case Heap::PRE_HEAP:
93.225 + heap.push(v, d + _length[e]);
93.226 + _pred[v] = e;
93.227 + break;
93.228 + case Heap::IN_HEAP:
93.229 + dn = d + _length[e];
93.230 + if (dn < heap[v]) {
93.231 + heap.decrease(v, dn);
93.232 + _pred[v] = e;
93.233 + }
93.234 + break;
93.235 + case Heap::POST_HEAP:
93.236 + break;
93.237 + }
93.238 + }
93.239 + }
93.240 + if (heap.empty()) return false;
93.241 +
93.242 + // Update potentials of processed nodes
93.243 + Length t_dist = heap.prio();
93.244 + for (int i = 0; i < int(_proc_nodes.size()); ++i)
93.245 + _pi[_proc_nodes[i]] = _dist[_proc_nodes[i]] - t_dist;
93.246 + return true;
93.247 + }
93.248 +
93.249 + // Execute the algorithm.
93.250 + bool start() {
93.251 + HeapCrossRef heap_cross_ref(_graph, Heap::PRE_HEAP);
93.252 + Heap heap(heap_cross_ref);
93.253 + heap.push(_s, 0);
93.254 + _pred[_s] = INVALID;
93.255 + _proc_nodes.clear();
93.256 +
93.257 + // Process nodes
93.258 + while (!heap.empty() && heap.top() != _t) {
93.259 + Node u = heap.top(), v;
93.260 + Length d = heap.prio() + _pi[u], dn;
93.261 + _dist[u] = heap.prio();
93.262 _proc_nodes.push_back(u);
93.263 + heap.pop();
93.264
93.265 // Traverse outgoing arcs
93.266 for (OutArcIt e(_graph, u); e != INVALID; ++e) {
93.267 if (_flow[e] == 0) {
93.268 v = _graph.target(e);
93.269 switch(heap.state(v)) {
93.270 - case Heap::PRE_HEAP:
93.271 - heap.push(v, d + _length[e] - _potential[v]);
93.272 - _pred[v] = e;
93.273 - break;
93.274 - case Heap::IN_HEAP:
93.275 - nd = d + _length[e] - _potential[v];
93.276 - if (nd < heap[v]) {
93.277 - heap.decrease(v, nd);
93.278 + case Heap::PRE_HEAP:
93.279 + heap.push(v, d + _length[e] - _pi[v]);
93.280 _pred[v] = e;
93.281 - }
93.282 - break;
93.283 - case Heap::POST_HEAP:
93.284 - break;
93.285 + break;
93.286 + case Heap::IN_HEAP:
93.287 + dn = d + _length[e] - _pi[v];
93.288 + if (dn < heap[v]) {
93.289 + heap.decrease(v, dn);
93.290 + _pred[v] = e;
93.291 + }
93.292 + break;
93.293 + case Heap::POST_HEAP:
93.294 + break;
93.295 }
93.296 }
93.297 }
93.298 @@ -183,19 +267,19 @@
93.299 if (_flow[e] == 1) {
93.300 v = _graph.source(e);
93.301 switch(heap.state(v)) {
93.302 - case Heap::PRE_HEAP:
93.303 - heap.push(v, d - _length[e] - _potential[v]);
93.304 - _pred[v] = e;
93.305 - break;
93.306 - case Heap::IN_HEAP:
93.307 - nd = d - _length[e] - _potential[v];
93.308 - if (nd < heap[v]) {
93.309 - heap.decrease(v, nd);
93.310 + case Heap::PRE_HEAP:
93.311 + heap.push(v, d - _length[e] - _pi[v]);
93.312 _pred[v] = e;
93.313 - }
93.314 - break;
93.315 - case Heap::POST_HEAP:
93.316 - break;
93.317 + break;
93.318 + case Heap::IN_HEAP:
93.319 + dn = d - _length[e] - _pi[v];
93.320 + if (dn < heap[v]) {
93.321 + heap.decrease(v, dn);
93.322 + _pred[v] = e;
93.323 + }
93.324 + break;
93.325 + case Heap::POST_HEAP:
93.326 + break;
93.327 }
93.328 }
93.329 }
93.330 @@ -205,12 +289,89 @@
93.331 // Update potentials of processed nodes
93.332 Length t_dist = heap.prio();
93.333 for (int i = 0; i < int(_proc_nodes.size()); ++i)
93.334 - _potential[_proc_nodes[i]] += _dist[_proc_nodes[i]] - t_dist;
93.335 + _pi[_proc_nodes[i]] += _dist[_proc_nodes[i]] - t_dist;
93.336 return true;
93.337 }
93.338
93.339 }; //class ResidualDijkstra
93.340
93.341 + public:
93.342 +
93.343 + /// \name Named Template Parameters
93.344 + /// @{
93.345 +
93.346 + template <typename T>
93.347 + struct SetFlowMapTraits : public Traits {
93.348 + typedef T FlowMap;
93.349 + };
93.350 +
93.351 + /// \brief \ref named-templ-param "Named parameter" for setting
93.352 + /// \c FlowMap type.
93.353 + ///
93.354 + /// \ref named-templ-param "Named parameter" for setting
93.355 + /// \c FlowMap type.
93.356 + template <typename T>
93.357 + struct SetFlowMap
93.358 + : public Suurballe<GR, LEN, SetFlowMapTraits<T> > {
93.359 + typedef Suurballe<GR, LEN, SetFlowMapTraits<T> > Create;
93.360 + };
93.361 +
93.362 + template <typename T>
93.363 + struct SetPotentialMapTraits : public Traits {
93.364 + typedef T PotentialMap;
93.365 + };
93.366 +
93.367 + /// \brief \ref named-templ-param "Named parameter" for setting
93.368 + /// \c PotentialMap type.
93.369 + ///
93.370 + /// \ref named-templ-param "Named parameter" for setting
93.371 + /// \c PotentialMap type.
93.372 + template <typename T>
93.373 + struct SetPotentialMap
93.374 + : public Suurballe<GR, LEN, SetPotentialMapTraits<T> > {
93.375 + typedef Suurballe<GR, LEN, SetPotentialMapTraits<T> > Create;
93.376 + };
93.377 +
93.378 + template <typename T>
93.379 + struct SetPathTraits : public Traits {
93.380 + typedef T Path;
93.381 + };
93.382 +
93.383 + /// \brief \ref named-templ-param "Named parameter" for setting
93.384 + /// \c %Path type.
93.385 + ///
93.386 + /// \ref named-templ-param "Named parameter" for setting \c %Path type.
93.387 + /// It must conform to the \ref lemon::concepts::Path "Path" concept
93.388 + /// and it must have an \c addBack() function.
93.389 + template <typename T>
93.390 + struct SetPath
93.391 + : public Suurballe<GR, LEN, SetPathTraits<T> > {
93.392 + typedef Suurballe<GR, LEN, SetPathTraits<T> > Create;
93.393 + };
93.394 +
93.395 + template <typename H, typename CR>
93.396 + struct SetHeapTraits : public Traits {
93.397 + typedef H Heap;
93.398 + typedef CR HeapCrossRef;
93.399 + };
93.400 +
93.401 + /// \brief \ref named-templ-param "Named parameter" for setting
93.402 + /// \c Heap and \c HeapCrossRef types.
93.403 + ///
93.404 + /// \ref named-templ-param "Named parameter" for setting \c Heap
93.405 + /// and \c HeapCrossRef types with automatic allocation.
93.406 + /// They will be used for internal Dijkstra computations.
93.407 + /// The heap type must conform to the \ref lemon::concepts::Heap "Heap"
93.408 + /// concept and its priority type must be \c Length.
93.409 + template <typename H,
93.410 + typename CR = typename Digraph::template NodeMap<int> >
93.411 + struct SetHeap
93.412 + : public Suurballe<GR, LEN, SetHeapTraits<H, CR> > {
93.413 + typedef Suurballe<GR, LEN, SetHeapTraits<H, CR> > Create;
93.414 + };
93.415 +
93.416 + /// @}
93.417 +
93.418 private:
93.419
93.420 // The digraph the algorithm runs on
93.421 @@ -226,19 +387,25 @@
93.422 bool _local_potential;
93.423
93.424 // The source node
93.425 - Node _source;
93.426 + Node _s;
93.427 // The target node
93.428 - Node _target;
93.429 + Node _t;
93.430
93.431 // Container to store the found paths
93.432 - std::vector< SimplePath<Digraph> > paths;
93.433 + std::vector<Path> _paths;
93.434 int _path_num;
93.435
93.436 // The pred arc map
93.437 PredMap _pred;
93.438 - // Implementation of the Dijkstra algorithm for finding augmenting
93.439 - // shortest paths in the residual network
93.440 - ResidualDijkstra *_dijkstra;
93.441 +
93.442 + // Data for full init
93.443 + PotentialMap *_init_dist;
93.444 + PredMap *_init_pred;
93.445 + bool _full_init;
93.446 +
93.447 + protected:
93.448 +
93.449 + Suurballe() {}
93.450
93.451 public:
93.452
93.453 @@ -251,14 +418,16 @@
93.454 Suurballe( const Digraph &graph,
93.455 const LengthMap &length ) :
93.456 _graph(graph), _length(length), _flow(0), _local_flow(false),
93.457 - _potential(0), _local_potential(false), _pred(graph)
93.458 + _potential(0), _local_potential(false), _pred(graph),
93.459 + _init_dist(0), _init_pred(0)
93.460 {}
93.461
93.462 /// Destructor.
93.463 ~Suurballe() {
93.464 if (_local_flow) delete _flow;
93.465 if (_local_potential) delete _potential;
93.466 - delete _dijkstra;
93.467 + delete _init_dist;
93.468 + delete _init_pred;
93.469 }
93.470
93.471 /// \brief Set the flow map.
93.472 @@ -303,10 +472,13 @@
93.473
93.474 /// \name Execution Control
93.475 /// The simplest way to execute the algorithm is to call the run()
93.476 - /// function.
93.477 - /// \n
93.478 + /// function.\n
93.479 + /// If you need to execute the algorithm many times using the same
93.480 + /// source node, then you may call fullInit() once and start()
93.481 + /// for each target node.\n
93.482 /// If you only need the flow that is the union of the found
93.483 - /// arc-disjoint paths, you may call init() and findFlow().
93.484 + /// arc-disjoint paths, then you may call findFlow() instead of
93.485 + /// start().
93.486
93.487 /// @{
93.488
93.489 @@ -326,23 +498,21 @@
93.490 /// just a shortcut of the following code.
93.491 /// \code
93.492 /// s.init(s);
93.493 - /// s.findFlow(t, k);
93.494 - /// s.findPaths();
93.495 + /// s.start(t, k);
93.496 /// \endcode
93.497 int run(const Node& s, const Node& t, int k = 2) {
93.498 init(s);
93.499 - findFlow(t, k);
93.500 - findPaths();
93.501 + start(t, k);
93.502 return _path_num;
93.503 }
93.504
93.505 /// \brief Initialize the algorithm.
93.506 ///
93.507 - /// This function initializes the algorithm.
93.508 + /// This function initializes the algorithm with the given source node.
93.509 ///
93.510 /// \param s The source node.
93.511 void init(const Node& s) {
93.512 - _source = s;
93.513 + _s = s;
93.514
93.515 // Initialize maps
93.516 if (!_flow) {
93.517 @@ -353,8 +523,63 @@
93.518 _potential = new PotentialMap(_graph);
93.519 _local_potential = true;
93.520 }
93.521 - for (ArcIt e(_graph); e != INVALID; ++e) (*_flow)[e] = 0;
93.522 - for (NodeIt n(_graph); n != INVALID; ++n) (*_potential)[n] = 0;
93.523 + _full_init = false;
93.524 + }
93.525 +
93.526 + /// \brief Initialize the algorithm and perform Dijkstra.
93.527 + ///
93.528 + /// This function initializes the algorithm and performs a full
93.529 + /// Dijkstra search from the given source node. It makes consecutive
93.530 + /// executions of \ref start() "start(t, k)" faster, since they
93.531 + /// have to perform %Dijkstra only k-1 times.
93.532 + ///
93.533 + /// This initialization is usually worth using instead of \ref init()
93.534 + /// if the algorithm is executed many times using the same source node.
93.535 + ///
93.536 + /// \param s The source node.
93.537 + void fullInit(const Node& s) {
93.538 + // Initialize maps
93.539 + init(s);
93.540 + if (!_init_dist) {
93.541 + _init_dist = new PotentialMap(_graph);
93.542 + }
93.543 + if (!_init_pred) {
93.544 + _init_pred = new PredMap(_graph);
93.545 + }
93.546 +
93.547 + // Run a full Dijkstra
93.548 + typename Dijkstra<Digraph, LengthMap>
93.549 + ::template SetStandardHeap<Heap>
93.550 + ::template SetDistMap<PotentialMap>
93.551 + ::template SetPredMap<PredMap>
93.552 + ::Create dijk(_graph, _length);
93.553 + dijk.distMap(*_init_dist).predMap(*_init_pred);
93.554 + dijk.run(s);
93.555 +
93.556 + _full_init = true;
93.557 + }
93.558 +
93.559 + /// \brief Execute the algorithm.
93.560 + ///
93.561 + /// This function executes the algorithm.
93.562 + ///
93.563 + /// \param t The target node.
93.564 + /// \param k The number of paths to be found.
93.565 + ///
93.566 + /// \return \c k if there are at least \c k arc-disjoint paths from
93.567 + /// \c s to \c t in the digraph. Otherwise it returns the number of
93.568 + /// arc-disjoint paths found.
93.569 + ///
93.570 + /// \note Apart from the return value, <tt>s.start(t, k)</tt> is
93.571 + /// just a shortcut of the following code.
93.572 + /// \code
93.573 + /// s.findFlow(t, k);
93.574 + /// s.findPaths();
93.575 + /// \endcode
93.576 + int start(const Node& t, int k = 2) {
93.577 + findFlow(t, k);
93.578 + findPaths();
93.579 + return _path_num;
93.580 }
93.581
93.582 /// \brief Execute the algorithm to find an optimal flow.
93.583 @@ -372,20 +597,39 @@
93.584 ///
93.585 /// \pre \ref init() must be called before using this function.
93.586 int findFlow(const Node& t, int k = 2) {
93.587 - _target = t;
93.588 - _dijkstra =
93.589 - new ResidualDijkstra( _graph, *_flow, _length, *_potential, _pred,
93.590 - _source, _target );
93.591 + _t = t;
93.592 + ResidualDijkstra dijkstra(*this);
93.593 +
93.594 + // Initialization
93.595 + for (ArcIt e(_graph); e != INVALID; ++e) {
93.596 + (*_flow)[e] = 0;
93.597 + }
93.598 + if (_full_init) {
93.599 + for (NodeIt n(_graph); n != INVALID; ++n) {
93.600 + (*_potential)[n] = (*_init_dist)[n];
93.601 + }
93.602 + Node u = _t;
93.603 + Arc e;
93.604 + while ((e = (*_init_pred)[u]) != INVALID) {
93.605 + (*_flow)[e] = 1;
93.606 + u = _graph.source(e);
93.607 + }
93.608 + _path_num = 1;
93.609 + } else {
93.610 + for (NodeIt n(_graph); n != INVALID; ++n) {
93.611 + (*_potential)[n] = 0;
93.612 + }
93.613 + _path_num = 0;
93.614 + }
93.615
93.616 // Find shortest paths
93.617 - _path_num = 0;
93.618 while (_path_num < k) {
93.619 // Run Dijkstra
93.620 - if (!_dijkstra->run()) break;
93.621 + if (!dijkstra.run(_path_num)) break;
93.622 ++_path_num;
93.623
93.624 // Set the flow along the found shortest path
93.625 - Node u = _target;
93.626 + Node u = _t;
93.627 Arc e;
93.628 while ((e = _pred[u]) != INVALID) {
93.629 if (u == _graph.target(e)) {
93.630 @@ -402,8 +646,8 @@
93.631
93.632 /// \brief Compute the paths from the flow.
93.633 ///
93.634 - /// This function computes the paths from the found minimum cost flow,
93.635 - /// which is the union of some arc-disjoint paths.
93.636 + /// This function computes arc-disjoint paths from the found minimum
93.637 + /// cost flow, which is the union of them.
93.638 ///
93.639 /// \pre \ref init() and \ref findFlow() must be called before using
93.640 /// this function.
93.641 @@ -411,15 +655,15 @@
93.642 FlowMap res_flow(_graph);
93.643 for(ArcIt a(_graph); a != INVALID; ++a) res_flow[a] = (*_flow)[a];
93.644
93.645 - paths.clear();
93.646 - paths.resize(_path_num);
93.647 + _paths.clear();
93.648 + _paths.resize(_path_num);
93.649 for (int i = 0; i < _path_num; ++i) {
93.650 - Node n = _source;
93.651 - while (n != _target) {
93.652 + Node n = _s;
93.653 + while (n != _t) {
93.654 OutArcIt e(_graph, n);
93.655 for ( ; res_flow[e] == 0; ++e) ;
93.656 n = _graph.target(e);
93.657 - paths[i].addBack(e);
93.658 + _paths[i].addBack(e);
93.659 res_flow[e] = 0;
93.660 }
93.661 }
93.662 @@ -518,7 +762,7 @@
93.663 /// \pre \ref run() or \ref findPaths() must be called before using
93.664 /// this function.
93.665 const Path& path(int i) const {
93.666 - return paths[i];
93.667 + return _paths[i];
93.668 }
93.669
93.670 /// @}
94.1 --- a/lemon/time_measure.h Tue Dec 20 17:44:38 2011 +0100
94.2 +++ b/lemon/time_measure.h Tue Dec 20 18:15:14 2011 +0100
94.3 @@ -375,7 +375,7 @@
94.4
94.5 ///This function returns the number of stop() exections that is
94.6 ///necessary to really stop the timer.
94.7 - ///For example the timer
94.8 + ///For example, the timer
94.9 ///is running if and only if the return value is \c true
94.10 ///(i.e. greater than
94.11 ///zero).
95.1 --- a/lemon/unionfind.h Tue Dec 20 17:44:38 2011 +0100
95.2 +++ b/lemon/unionfind.h Tue Dec 20 18:15:14 2011 +0100
95.3 @@ -2,7 +2,7 @@
95.4 *
95.5 * This file is a part of LEMON, a generic C++ optimization library.
95.6 *
95.7 - * Copyright (C) 2003-2009
95.8 + * Copyright (C) 2003-2010
95.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
95.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
95.11 *
95.12 @@ -43,7 +43,7 @@
95.13 /// the find operation uses path compression.
95.14 /// This is a very simple but efficient implementation, providing
95.15 /// only four methods: join (union), find, insert and size.
95.16 - /// For more features see the \ref UnionFindEnum class.
95.17 + /// For more features, see the \ref UnionFindEnum class.
95.18 ///
95.19 /// It is primarily used in Kruskal algorithm for finding minimal
95.20 /// cost spanning tree in a graph.
96.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
96.2 +++ b/scripts/Makefile.am Tue Dec 20 18:15:14 2011 +0100
96.3 @@ -0,0 +1,7 @@
96.4 +EXTRA_DIST += \
96.5 + scripts/bib2dox.py \
96.6 + scripts/bootstrap.sh \
96.7 + scripts/chg-len.py \
96.8 + scripts/mk-release.sh \
96.9 + scripts/unify-sources.sh \
96.10 + scripts/valgrind-wrapper.sh
97.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
97.2 +++ b/scripts/bib2dox.py Tue Dec 20 18:15:14 2011 +0100
97.3 @@ -0,0 +1,816 @@
97.4 +#! /usr/bin/env python
97.5 +"""
97.6 + BibTeX to Doxygen converter
97.7 + Usage: python bib2dox.py bibfile.bib > bibfile.dox
97.8 +
97.9 + This file is a part of LEMON, a generic C++ optimization library.
97.10 +
97.11 + **********************************************************************
97.12 +
97.13 + This code is the modification of the BibTeX to XML converter
97.14 + by Vidar Bronken Gundersen et al.
97.15 + See the original copyright notices below.
97.16 +
97.17 + **********************************************************************
97.18 +
97.19 + Decoder for bibliographic data, BibTeX
97.20 + Usage: python bibtex2xml.py bibfile.bib > bibfile.xml
97.21 +
97.22 + v.8
97.23 + (c)2002-06-23 Vidar Bronken Gundersen
97.24 + http://bibtexml.sf.net/
97.25 + Reuse approved as long as this notification is kept.
97.26 + Licence: GPL.
97.27 +
97.28 + Contributions/thanks to:
97.29 + Egon Willighagen, http://sf.net/projects/jreferences/
97.30 + Richard Mahoney (for providing a test case)
97.31 +
97.32 + Editted by Sara Sprenkle to be more robust and handle more bibtex features.
97.33 + (c) 2003-01-15
97.34 +
97.35 + 1. Changed bibtex: tags to bibxml: tags.
97.36 + 2. Use xmlns:bibxml="http://bibtexml.sf.net/"
97.37 + 3. Allow spaces between @type and first {
97.38 + 4. "author" fields with multiple authors split by " and "
97.39 + are put in separate xml "bibxml:author" tags.
97.40 + 5. Option for Titles: words are capitalized
97.41 + only if first letter in title or capitalized inside braces
97.42 + 6. Removes braces from within field values
97.43 + 7. Ignores comments in bibtex file (including @comment{ or % )
97.44 + 8. Replaces some special latex tags, e.g., replaces ~ with ' '
97.45 + 9. Handles bibtex @string abbreviations
97.46 + --> includes bibtex's default abbreviations for months
97.47 + --> does concatenation of abbr # " more " and " more " # abbr
97.48 + 10. Handles @type( ... ) or @type{ ... }
97.49 + 11. The keywords field is split on , or ; and put into separate xml
97.50 + "bibxml:keywords" tags
97.51 + 12. Ignores @preamble
97.52 +
97.53 + Known Limitations
97.54 + 1. Does not transform Latex encoding like math mode and special
97.55 + latex symbols.
97.56 + 2. Does not parse author fields into first and last names.
97.57 + E.g., It does not do anything special to an author whose name is
97.58 + in the form LAST_NAME, FIRST_NAME
97.59 + In "author" tag, will show up as
97.60 + <bibxml:author>LAST_NAME, FIRST_NAME</bibxml:author>
97.61 + 3. Does not handle "crossref" fields other than to print
97.62 + <bibxml:crossref>...</bibxml:crossref>
97.63 + 4. Does not inform user of the input's format errors. You just won't
97.64 + be able to transform the file later with XSL
97.65 +
97.66 + You will have to manually edit the XML output if you need to handle
97.67 + these (and unknown) limitations.
97.68 +
97.69 +"""
97.70 +
97.71 +import string, re
97.72 +
97.73 +# set of valid name characters
97.74 +valid_name_chars = '[\w\-:]'
97.75 +
97.76 +#
97.77 +# define global regular expression variables
97.78 +#
97.79 +author_rex = re.compile('\s+and\s+')
97.80 +rembraces_rex = re.compile('[{}]')
97.81 +capitalize_rex = re.compile('({[^}]*})')
97.82 +
97.83 +# used by bibtexkeywords(data)
97.84 +keywords_rex = re.compile('[,;]')
97.85 +
97.86 +# used by concat_line(line)
97.87 +concatsplit_rex = re.compile('\s*#\s*')
97.88 +
97.89 +# split on {, }, or " in verify_out_of_braces
97.90 +delimiter_rex = re.compile('([{}"])',re.I)
97.91 +
97.92 +field_rex = re.compile('\s*(\w*)\s*=\s*(.*)')
97.93 +data_rex = re.compile('\s*(\w*)\s*=\s*([^,]*),?')
97.94 +
97.95 +url_rex = re.compile('\\\url\{([^}]*)\}')
97.96 +
97.97 +#
97.98 +# styles for html formatting
97.99 +#
97.100 +divstyle = 'margin-top: -4ex; margin-left: 8em;'
97.101 +
97.102 +#
97.103 +# return the string parameter without braces
97.104 +#
97.105 +def transformurls(str):
97.106 + return url_rex.sub(r'<a href="\1">\1</a>', str)
97.107 +
97.108 +#
97.109 +# return the string parameter without braces
97.110 +#
97.111 +def removebraces(str):
97.112 + return rembraces_rex.sub('', str)
97.113 +
97.114 +#
97.115 +# latex-specific replacements
97.116 +# (do this after braces were removed)
97.117 +#
97.118 +def latexreplacements(line):
97.119 + line = string.replace(line, '~', ' ')
97.120 + line = string.replace(line, '\\\'a', 'á')
97.121 + line = string.replace(line, '\\"a', 'ä')
97.122 + line = string.replace(line, '\\\'e', 'é')
97.123 + line = string.replace(line, '\\"e', 'ë')
97.124 + line = string.replace(line, '\\\'i', 'í')
97.125 + line = string.replace(line, '\\"i', 'ï')
97.126 + line = string.replace(line, '\\\'o', 'ó')
97.127 + line = string.replace(line, '\\"o', 'ö')
97.128 + line = string.replace(line, '\\\'u', 'ú')
97.129 + line = string.replace(line, '\\"u', 'ü')
97.130 + line = string.replace(line, '\\H o', 'õ')
97.131 + line = string.replace(line, '\\H u', 'ü') # ũ does not exist
97.132 + line = string.replace(line, '\\\'A', 'Á')
97.133 + line = string.replace(line, '\\"A', 'Ä')
97.134 + line = string.replace(line, '\\\'E', 'É')
97.135 + line = string.replace(line, '\\"E', 'Ë')
97.136 + line = string.replace(line, '\\\'I', 'Í')
97.137 + line = string.replace(line, '\\"I', 'Ï')
97.138 + line = string.replace(line, '\\\'O', 'Ó')
97.139 + line = string.replace(line, '\\"O', 'Ö')
97.140 + line = string.replace(line, '\\\'U', 'Ú')
97.141 + line = string.replace(line, '\\"U', 'Ü')
97.142 + line = string.replace(line, '\\H O', 'Õ')
97.143 + line = string.replace(line, '\\H U', 'Ü') # Ũ does not exist
97.144 +
97.145 + return line
97.146 +
97.147 +#
97.148 +# copy characters form a string decoding html expressions (&xyz;)
97.149 +#
97.150 +def copychars(str, ifrom, count):
97.151 + result = ''
97.152 + i = ifrom
97.153 + c = 0
97.154 + html_spec = False
97.155 + while (i < len(str)) and (c < count):
97.156 + if str[i] == '&':
97.157 + html_spec = True;
97.158 + if i+1 < len(str):
97.159 + result += str[i+1]
97.160 + c += 1
97.161 + i += 2
97.162 + else:
97.163 + if not html_spec:
97.164 + if ((str[i] >= 'A') and (str[i] <= 'Z')) or \
97.165 + ((str[i] >= 'a') and (str[i] <= 'z')):
97.166 + result += str[i]
97.167 + c += 1
97.168 + elif str[i] == ';':
97.169 + html_spec = False;
97.170 + i += 1
97.171 +
97.172 + return result
97.173 +
97.174 +
97.175 +#
97.176 +# Handle a list of authors (separated by 'and').
97.177 +# It gives back an array of the follwing values:
97.178 +# - num: the number of authors,
97.179 +# - list: the list of the author names,
97.180 +# - text: the bibtex text (separated by commas and/or 'and')
97.181 +# - abbrev: abbreviation that can be used for indicate the
97.182 +# bibliography entries
97.183 +#
97.184 +def bibtexauthor(data):
97.185 + result = {}
97.186 + bibtex = ''
97.187 + result['list'] = author_rex.split(data)
97.188 + result['num'] = len(result['list'])
97.189 + for i, author in enumerate(result['list']):
97.190 + # general transformations
97.191 + author = latexreplacements(removebraces(author.strip()))
97.192 + # transform "Xyz, A. B." to "A. B. Xyz"
97.193 + pos = author.find(',')
97.194 + if pos != -1:
97.195 + author = author[pos+1:].strip() + ' ' + author[:pos].strip()
97.196 + result['list'][i] = author
97.197 + bibtex += author + '#'
97.198 + bibtex = bibtex[:-1]
97.199 + if result['num'] > 1:
97.200 + ix = bibtex.rfind('#')
97.201 + if result['num'] == 2:
97.202 + bibtex = bibtex[:ix] + ' and ' + bibtex[ix+1:]
97.203 + else:
97.204 + bibtex = bibtex[:ix] + ', and ' + bibtex[ix+1:]
97.205 + bibtex = bibtex.replace('#', ', ')
97.206 + result['text'] = bibtex
97.207 +
97.208 + result['abbrev'] = ''
97.209 + for author in result['list']:
97.210 + pos = author.rfind(' ') + 1
97.211 + count = 1
97.212 + if result['num'] == 1:
97.213 + count = 3
97.214 + result['abbrev'] += copychars(author, pos, count)
97.215 +
97.216 + return result
97.217 +
97.218 +
97.219 +#
97.220 +# data = title string
97.221 +# @return the capitalized title (first letter is capitalized), rest are capitalized
97.222 +# only if capitalized inside braces
97.223 +#
97.224 +def capitalizetitle(data):
97.225 + title_list = capitalize_rex.split(data)
97.226 + title = ''
97.227 + count = 0
97.228 + for phrase in title_list:
97.229 + check = string.lstrip(phrase)
97.230 +
97.231 + # keep phrase's capitalization the same
97.232 + if check.find('{') == 0:
97.233 + title += removebraces(phrase)
97.234 + else:
97.235 + # first word --> capitalize first letter (after spaces)
97.236 + if count == 0:
97.237 + title += check.capitalize()
97.238 + else:
97.239 + title += phrase.lower()
97.240 + count = count + 1
97.241 +
97.242 + return title
97.243 +
97.244 +
97.245 +#
97.246 +# @return the bibtex for the title
97.247 +# @param data --> title string
97.248 +# braces are removed from title
97.249 +#
97.250 +def bibtextitle(data, entrytype):
97.251 + if entrytype in ('book', 'inbook'):
97.252 + title = removebraces(data.strip())
97.253 + else:
97.254 + title = removebraces(capitalizetitle(data.strip()))
97.255 + bibtex = title
97.256 + return bibtex
97.257 +
97.258 +
97.259 +#
97.260 +# function to compare entry lists
97.261 +#
97.262 +def entry_cmp(x, y):
97.263 + return cmp(x[0], y[0])
97.264 +
97.265 +
97.266 +#
97.267 +# print the XML for the transformed "filecont_source"
97.268 +#
97.269 +def bibtexdecoder(filecont_source):
97.270 + filecont = []
97.271 + file = []
97.272 +
97.273 + # want @<alphanumeric chars><spaces>{<spaces><any chars>,
97.274 + pubtype_rex = re.compile('@(\w*)\s*{\s*(.*),')
97.275 + endtype_rex = re.compile('}\s*$')
97.276 + endtag_rex = re.compile('^\s*}\s*$')
97.277 +
97.278 + bracefield_rex = re.compile('\s*(\w*)\s*=\s*(.*)')
97.279 + bracedata_rex = re.compile('\s*(\w*)\s*=\s*{(.*)},?')
97.280 +
97.281 + quotefield_rex = re.compile('\s*(\w*)\s*=\s*(.*)')
97.282 + quotedata_rex = re.compile('\s*(\w*)\s*=\s*"(.*)",?')
97.283 +
97.284 + for line in filecont_source:
97.285 + line = line[:-1]
97.286 +
97.287 + # encode character entities
97.288 + line = string.replace(line, '&', '&')
97.289 + line = string.replace(line, '<', '<')
97.290 + line = string.replace(line, '>', '>')
97.291 +
97.292 + # start entry: publication type (store for later use)
97.293 + if pubtype_rex.match(line):
97.294 + # want @<alphanumeric chars><spaces>{<spaces><any chars>,
97.295 + entrycont = {}
97.296 + entry = []
97.297 + entrytype = pubtype_rex.sub('\g<1>',line)
97.298 + entrytype = string.lower(entrytype)
97.299 + entryid = pubtype_rex.sub('\g<2>', line)
97.300 +
97.301 + # end entry if just a }
97.302 + elif endtype_rex.match(line):
97.303 + # generate doxygen code for the entry
97.304 +
97.305 + # enty type related formattings
97.306 + if entrytype in ('book', 'inbook'):
97.307 + entrycont['title'] = '<em>' + entrycont['title'] + '</em>'
97.308 + if not entrycont.has_key('author'):
97.309 + entrycont['author'] = entrycont['editor']
97.310 + entrycont['author']['text'] += ', editors'
97.311 + elif entrytype == 'article':
97.312 + entrycont['journal'] = '<em>' + entrycont['journal'] + '</em>'
97.313 + elif entrytype in ('inproceedings', 'incollection', 'conference'):
97.314 + entrycont['booktitle'] = '<em>' + entrycont['booktitle'] + '</em>'
97.315 + elif entrytype == 'techreport':
97.316 + if not entrycont.has_key('type'):
97.317 + entrycont['type'] = 'Technical report'
97.318 + elif entrytype == 'mastersthesis':
97.319 + entrycont['type'] = 'Master\'s thesis'
97.320 + elif entrytype == 'phdthesis':
97.321 + entrycont['type'] = 'PhD thesis'
97.322 +
97.323 + for eline in entrycont:
97.324 + if eline != '':
97.325 + eline = latexreplacements(eline)
97.326 +
97.327 + if entrycont.has_key('pages') and (entrycont['pages'] != ''):
97.328 + entrycont['pages'] = string.replace(entrycont['pages'], '--', '-')
97.329 +
97.330 + if entrycont.has_key('author') and (entrycont['author'] != ''):
97.331 + entry.append(entrycont['author']['text'] + '.')
97.332 + if entrycont.has_key('title') and (entrycont['title'] != ''):
97.333 + entry.append(entrycont['title'] + '.')
97.334 + if entrycont.has_key('journal') and (entrycont['journal'] != ''):
97.335 + entry.append(entrycont['journal'] + ',')
97.336 + if entrycont.has_key('booktitle') and (entrycont['booktitle'] != ''):
97.337 + entry.append('In ' + entrycont['booktitle'] + ',')
97.338 + if entrycont.has_key('type') and (entrycont['type'] != ''):
97.339 + eline = entrycont['type']
97.340 + if entrycont.has_key('number') and (entrycont['number'] != ''):
97.341 + eline += ' ' + entrycont['number']
97.342 + eline += ','
97.343 + entry.append(eline)
97.344 + if entrycont.has_key('institution') and (entrycont['institution'] != ''):
97.345 + entry.append(entrycont['institution'] + ',')
97.346 + if entrycont.has_key('publisher') and (entrycont['publisher'] != ''):
97.347 + entry.append(entrycont['publisher'] + ',')
97.348 + if entrycont.has_key('school') and (entrycont['school'] != ''):
97.349 + entry.append(entrycont['school'] + ',')
97.350 + if entrycont.has_key('address') and (entrycont['address'] != ''):
97.351 + entry.append(entrycont['address'] + ',')
97.352 + if entrycont.has_key('edition') and (entrycont['edition'] != ''):
97.353 + entry.append(entrycont['edition'] + ' edition,')
97.354 + if entrycont.has_key('howpublished') and (entrycont['howpublished'] != ''):
97.355 + entry.append(entrycont['howpublished'] + ',')
97.356 + if entrycont.has_key('volume') and (entrycont['volume'] != ''):
97.357 + eline = entrycont['volume'];
97.358 + if entrycont.has_key('number') and (entrycont['number'] != ''):
97.359 + eline += '(' + entrycont['number'] + ')'
97.360 + if entrycont.has_key('pages') and (entrycont['pages'] != ''):
97.361 + eline += ':' + entrycont['pages']
97.362 + eline += ','
97.363 + entry.append(eline)
97.364 + else:
97.365 + if entrycont.has_key('pages') and (entrycont['pages'] != ''):
97.366 + entry.append('pages ' + entrycont['pages'] + ',')
97.367 + if entrycont.has_key('year') and (entrycont['year'] != ''):
97.368 + if entrycont.has_key('month') and (entrycont['month'] != ''):
97.369 + entry.append(entrycont['month'] + ' ' + entrycont['year'] + '.')
97.370 + else:
97.371 + entry.append(entrycont['year'] + '.')
97.372 + if entrycont.has_key('note') and (entrycont['note'] != ''):
97.373 + entry.append(entrycont['note'] + '.')
97.374 + if entrycont.has_key('url') and (entrycont['url'] != ''):
97.375 + entry.append(entrycont['url'] + '.')
97.376 +
97.377 + # generate keys for sorting and for the output
97.378 + sortkey = ''
97.379 + bibkey = ''
97.380 + if entrycont.has_key('author'):
97.381 + for author in entrycont['author']['list']:
97.382 + sortkey += copychars(author, author.rfind(' ')+1, len(author))
97.383 + bibkey = entrycont['author']['abbrev']
97.384 + else:
97.385 + bibkey = 'x'
97.386 + if entrycont.has_key('year'):
97.387 + sortkey += entrycont['year']
97.388 + bibkey += entrycont['year'][-2:]
97.389 + if entrycont.has_key('title'):
97.390 + sortkey += entrycont['title']
97.391 + if entrycont.has_key('key'):
97.392 + sortkey = entrycont['key'] + sortkey
97.393 + bibkey = entrycont['key']
97.394 + entry.insert(0, sortkey)
97.395 + entry.insert(1, bibkey)
97.396 + entry.insert(2, entryid)
97.397 +
97.398 + # add the entry to the file contents
97.399 + filecont.append(entry)
97.400 +
97.401 + else:
97.402 + # field, publication info
97.403 + field = ''
97.404 + data = ''
97.405 +
97.406 + # field = {data} entries
97.407 + if bracedata_rex.match(line):
97.408 + field = bracefield_rex.sub('\g<1>', line)
97.409 + field = string.lower(field)
97.410 + data = bracedata_rex.sub('\g<2>', line)
97.411 +
97.412 + # field = "data" entries
97.413 + elif quotedata_rex.match(line):
97.414 + field = quotefield_rex.sub('\g<1>', line)
97.415 + field = string.lower(field)
97.416 + data = quotedata_rex.sub('\g<2>', line)
97.417 +
97.418 + # field = data entries
97.419 + elif data_rex.match(line):
97.420 + field = field_rex.sub('\g<1>', line)
97.421 + field = string.lower(field)
97.422 + data = data_rex.sub('\g<2>', line)
97.423 +
97.424 + if field == 'url':
97.425 + data = '\\url{' + data.strip() + '}'
97.426 +
97.427 + if field in ('author', 'editor'):
97.428 + entrycont[field] = bibtexauthor(data)
97.429 + line = ''
97.430 + elif field == 'title':
97.431 + line = bibtextitle(data, entrytype)
97.432 + elif field != '':
97.433 + line = removebraces(transformurls(data.strip()))
97.434 +
97.435 + if line != '':
97.436 + line = latexreplacements(line)
97.437 + entrycont[field] = line
97.438 +
97.439 +
97.440 + # sort entries
97.441 + filecont.sort(entry_cmp)
97.442 +
97.443 + # count the bibtex keys
97.444 + keytable = {}
97.445 + counttable = {}
97.446 + for entry in filecont:
97.447 + bibkey = entry[1]
97.448 + if not keytable.has_key(bibkey):
97.449 + keytable[bibkey] = 1
97.450 + else:
97.451 + keytable[bibkey] += 1
97.452 +
97.453 + for bibkey in keytable.keys():
97.454 + counttable[bibkey] = 0
97.455 +
97.456 + # generate output
97.457 + for entry in filecont:
97.458 + # generate output key form the bibtex key
97.459 + bibkey = entry[1]
97.460 + entryid = entry[2]
97.461 + if keytable[bibkey] == 1:
97.462 + outkey = bibkey
97.463 + else:
97.464 + outkey = bibkey + chr(97 + counttable[bibkey])
97.465 + counttable[bibkey] += 1
97.466 +
97.467 + # append the entry code to the output
97.468 + file.append('\\section ' + entryid + ' [' + outkey + ']')
97.469 + file.append('<div style="' + divstyle + '">')
97.470 + for line in entry[3:]:
97.471 + file.append(line)
97.472 + file.append('</div>')
97.473 + file.append('')
97.474 +
97.475 + return file
97.476 +
97.477 +
97.478 +#
97.479 +# return 1 iff abbr is in line but not inside braces or quotes
97.480 +# assumes that abbr appears only once on the line (out of braces and quotes)
97.481 +#
97.482 +def verify_out_of_braces(line, abbr):
97.483 +
97.484 + phrase_split = delimiter_rex.split(line)
97.485 +
97.486 + abbr_rex = re.compile( '\\b' + abbr + '\\b', re.I)
97.487 +
97.488 + open_brace = 0
97.489 + open_quote = 0
97.490 +
97.491 + for phrase in phrase_split:
97.492 + if phrase == "{":
97.493 + open_brace = open_brace + 1
97.494 + elif phrase == "}":
97.495 + open_brace = open_brace - 1
97.496 + elif phrase == '"':
97.497 + if open_quote == 1:
97.498 + open_quote = 0
97.499 + else:
97.500 + open_quote = 1
97.501 + elif abbr_rex.search(phrase):
97.502 + if open_brace == 0 and open_quote == 0:
97.503 + return 1
97.504 +
97.505 + return 0
97.506 +
97.507 +
97.508 +#
97.509 +# a line in the form phrase1 # phrase2 # ... # phrasen
97.510 +# is returned as phrase1 phrase2 ... phrasen
97.511 +# with the correct punctuation
97.512 +# Bug: Doesn't always work with multiple abbreviations plugged in
97.513 +#
97.514 +def concat_line(line):
97.515 + # only look at part after equals
97.516 + field = field_rex.sub('\g<1>',line)
97.517 + rest = field_rex.sub('\g<2>',line)
97.518 +
97.519 + concat_line = field + ' ='
97.520 +
97.521 + pound_split = concatsplit_rex.split(rest)
97.522 +
97.523 + phrase_count = 0
97.524 + length = len(pound_split)
97.525 +
97.526 + for phrase in pound_split:
97.527 + phrase = phrase.strip()
97.528 + if phrase_count != 0:
97.529 + if phrase.startswith('"') or phrase.startswith('{'):
97.530 + phrase = phrase[1:]
97.531 + elif phrase.startswith('"'):
97.532 + phrase = phrase.replace('"','{',1)
97.533 +
97.534 + if phrase_count != length-1:
97.535 + if phrase.endswith('"') or phrase.endswith('}'):
97.536 + phrase = phrase[:-1]
97.537 + else:
97.538 + if phrase.endswith('"'):
97.539 + phrase = phrase[:-1]
97.540 + phrase = phrase + "}"
97.541 + elif phrase.endswith('",'):
97.542 + phrase = phrase[:-2]
97.543 + phrase = phrase + "},"
97.544 +
97.545 + # if phrase did have \#, add the \# back
97.546 + if phrase.endswith('\\'):
97.547 + phrase = phrase + "#"
97.548 + concat_line = concat_line + ' ' + phrase
97.549 +
97.550 + phrase_count = phrase_count + 1
97.551 +
97.552 + return concat_line
97.553 +
97.554 +
97.555 +#
97.556 +# substitute abbreviations into filecont
97.557 +# @param filecont_source - string of data from file
97.558 +#
97.559 +def bibtex_replace_abbreviations(filecont_source):
97.560 + filecont = filecont_source.splitlines()
97.561 +
97.562 + # These are defined in bibtex, so we'll define them too
97.563 + abbr_list = ['jan','feb','mar','apr','may','jun',
97.564 + 'jul','aug','sep','oct','nov','dec']
97.565 + value_list = ['January','February','March','April',
97.566 + 'May','June','July','August','September',
97.567 + 'October','November','December']
97.568 +
97.569 + abbr_rex = []
97.570 + total_abbr_count = 0
97.571 +
97.572 + front = '\\b'
97.573 + back = '(,?)\\b'
97.574 +
97.575 + for x in abbr_list:
97.576 + abbr_rex.append( re.compile( front + abbr_list[total_abbr_count] + back, re.I ) )
97.577 + total_abbr_count = total_abbr_count + 1
97.578 +
97.579 +
97.580 + abbrdef_rex = re.compile('\s*@string\s*{\s*('+ valid_name_chars +'*)\s*=(.*)',
97.581 + re.I)
97.582 +
97.583 + comment_rex = re.compile('@comment\s*{',re.I)
97.584 + preamble_rex = re.compile('@preamble\s*{',re.I)
97.585 +
97.586 + waiting_for_end_string = 0
97.587 + i = 0
97.588 + filecont2 = ''
97.589 +
97.590 + for line in filecont:
97.591 + if line == ' ' or line == '':
97.592 + continue
97.593 +
97.594 + if waiting_for_end_string:
97.595 + if re.search('}',line):
97.596 + waiting_for_end_string = 0
97.597 + continue
97.598 +
97.599 + if abbrdef_rex.search(line):
97.600 + abbr = abbrdef_rex.sub('\g<1>', line)
97.601 +
97.602 + if abbr_list.count(abbr) == 0:
97.603 + val = abbrdef_rex.sub('\g<2>', line)
97.604 + abbr_list.append(abbr)
97.605 + value_list.append(string.strip(val))
97.606 + abbr_rex.append( re.compile( front + abbr_list[total_abbr_count] + back, re.I ) )
97.607 + total_abbr_count = total_abbr_count + 1
97.608 + waiting_for_end_string = 1
97.609 + continue
97.610 +
97.611 + if comment_rex.search(line):
97.612 + waiting_for_end_string = 1
97.613 + continue
97.614 +
97.615 + if preamble_rex.search(line):
97.616 + waiting_for_end_string = 1
97.617 + continue
97.618 +
97.619 +
97.620 + # replace subsequent abbreviations with the value
97.621 + abbr_count = 0
97.622 +
97.623 + for x in abbr_list:
97.624 +
97.625 + if abbr_rex[abbr_count].search(line):
97.626 + if verify_out_of_braces(line,abbr_list[abbr_count]) == 1:
97.627 + line = abbr_rex[abbr_count].sub( value_list[abbr_count] + '\g<1>', line)
97.628 + # Check for # concatenations
97.629 + if concatsplit_rex.search(line):
97.630 + line = concat_line(line)
97.631 + abbr_count = abbr_count + 1
97.632 +
97.633 +
97.634 + filecont2 = filecont2 + line + '\n'
97.635 + i = i+1
97.636 +
97.637 +
97.638 + # Do one final pass over file
97.639 +
97.640 + # make sure that didn't end up with {" or }" after the substitution
97.641 + filecont2 = filecont2.replace('{"','{{')
97.642 + filecont2 = filecont2.replace('"}','}}')
97.643 +
97.644 + afterquotevalue_rex = re.compile('"\s*,\s*')
97.645 + afterbrace_rex = re.compile('"\s*}')
97.646 + afterbracevalue_rex = re.compile('(=\s*{[^=]*)},\s*')
97.647 +
97.648 + # add new lines to data that changed because of abbreviation substitutions
97.649 + filecont2 = afterquotevalue_rex.sub('",\n', filecont2)
97.650 + filecont2 = afterbrace_rex.sub('"\n}', filecont2)
97.651 + filecont2 = afterbracevalue_rex.sub('\g<1>},\n', filecont2)
97.652 +
97.653 + return filecont2
97.654 +
97.655 +#
97.656 +# convert @type( ... ) to @type{ ... }
97.657 +#
97.658 +def no_outer_parens(filecont):
97.659 +
97.660 + # do checking for open parens
97.661 + # will convert to braces
97.662 + paren_split = re.split('([(){}])',filecont)
97.663 +
97.664 + open_paren_count = 0
97.665 + open_type = 0
97.666 + look_next = 0
97.667 +
97.668 + # rebuild filecont
97.669 + filecont = ''
97.670 +
97.671 + at_rex = re.compile('@\w*')
97.672 +
97.673 + for phrase in paren_split:
97.674 + if look_next == 1:
97.675 + if phrase == '(':
97.676 + phrase = '{'
97.677 + open_paren_count = open_paren_count + 1
97.678 + else:
97.679 + open_type = 0
97.680 + look_next = 0
97.681 +
97.682 + if phrase == '(':
97.683 + open_paren_count = open_paren_count + 1
97.684 +
97.685 + elif phrase == ')':
97.686 + open_paren_count = open_paren_count - 1
97.687 + if open_type == 1 and open_paren_count == 0:
97.688 + phrase = '}'
97.689 + open_type = 0
97.690 +
97.691 + elif at_rex.search( phrase ):
97.692 + open_type = 1
97.693 + look_next = 1
97.694 +
97.695 + filecont = filecont + phrase
97.696 +
97.697 + return filecont
97.698 +
97.699 +
97.700 +#
97.701 +# make all whitespace into just one space
97.702 +# format the bibtex file into a usable form.
97.703 +#
97.704 +def bibtexwasher(filecont_source):
97.705 +
97.706 + space_rex = re.compile('\s+')
97.707 + comment_rex = re.compile('\s*%')
97.708 +
97.709 + filecont = []
97.710 +
97.711 + # remove trailing and excessive whitespace
97.712 + # ignore comments
97.713 + for line in filecont_source:
97.714 + line = string.strip(line)
97.715 + line = space_rex.sub(' ', line)
97.716 + # ignore comments
97.717 + if not comment_rex.match(line) and line != '':
97.718 + filecont.append(' '+ line)
97.719 +
97.720 + filecont = string.join(filecont, '')
97.721 +
97.722 + # the file is in one long string
97.723 +
97.724 + filecont = no_outer_parens(filecont)
97.725 +
97.726 + #
97.727 + # split lines according to preferred syntax scheme
97.728 + #
97.729 + filecont = re.sub('(=\s*{[^=]*)},', '\g<1>},\n', filecont)
97.730 +
97.731 + # add new lines after commas that are after values
97.732 + filecont = re.sub('"\s*,', '",\n', filecont)
97.733 + filecont = re.sub('=\s*([\w\d]+)\s*,', '= \g<1>,\n', filecont)
97.734 + filecont = re.sub('(@\w*)\s*({(\s*)[^,\s]*)\s*,',
97.735 + '\n\n\g<1>\g<2>,\n', filecont)
97.736 +
97.737 + # add new lines after }
97.738 + filecont = re.sub('"\s*}','"\n}\n', filecont)
97.739 + filecont = re.sub('}\s*,','},\n', filecont)
97.740 +
97.741 +
97.742 + filecont = re.sub('@(\w*)', '\n@\g<1>', filecont)
97.743 +
97.744 + # character encoding, reserved latex characters
97.745 + filecont = re.sub('{\\\&}', '&', filecont)
97.746 + filecont = re.sub('\\\&', '&', filecont)
97.747 +
97.748 + # do checking for open braces to get format correct
97.749 + open_brace_count = 0
97.750 + brace_split = re.split('([{}])',filecont)
97.751 +
97.752 + # rebuild filecont
97.753 + filecont = ''
97.754 +
97.755 + for phrase in brace_split:
97.756 + if phrase == '{':
97.757 + open_brace_count = open_brace_count + 1
97.758 + elif phrase == '}':
97.759 + open_brace_count = open_brace_count - 1
97.760 + if open_brace_count == 0:
97.761 + filecont = filecont + '\n'
97.762 +
97.763 + filecont = filecont + phrase
97.764 +
97.765 + filecont2 = bibtex_replace_abbreviations(filecont)
97.766 +
97.767 + # gather
97.768 + filecont = filecont2.splitlines()
97.769 + i=0
97.770 + j=0 # count the number of blank lines
97.771 + for line in filecont:
97.772 + # ignore blank lines
97.773 + if line == '' or line == ' ':
97.774 + j = j+1
97.775 + continue
97.776 + filecont[i] = line + '\n'
97.777 + i = i+1
97.778 +
97.779 + # get rid of the extra stuff at the end of the array
97.780 + # (The extra stuff are duplicates that are in the array because
97.781 + # blank lines were removed.)
97.782 + length = len( filecont)
97.783 + filecont[length-j:length] = []
97.784 +
97.785 + return filecont
97.786 +
97.787 +
97.788 +def filehandler(filepath):
97.789 + try:
97.790 + fd = open(filepath, 'r')
97.791 + filecont_source = fd.readlines()
97.792 + fd.close()
97.793 + except:
97.794 + print 'Could not open file:', filepath
97.795 + washeddata = bibtexwasher(filecont_source)
97.796 + outdata = bibtexdecoder(washeddata)
97.797 + print '/**'
97.798 + print '\page references References'
97.799 + print
97.800 + for line in outdata:
97.801 + print line
97.802 + print '*/'
97.803 +
97.804 +
97.805 +# main program
97.806 +
97.807 +def main():
97.808 + import sys
97.809 + if sys.argv[1:]:
97.810 + filepath = sys.argv[1]
97.811 + else:
97.812 + print "No input file"
97.813 + sys.exit()
97.814 + filehandler(filepath)
97.815 +
97.816 +if __name__ == "__main__": main()
97.817 +
97.818 +
97.819 +# end python script
98.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
98.2 +++ b/scripts/bootstrap.sh Tue Dec 20 18:15:14 2011 +0100
98.3 @@ -0,0 +1,157 @@
98.4 +#!/bin/bash
98.5 +#
98.6 +# This file is a part of LEMON, a generic C++ optimization library.
98.7 +#
98.8 +# Copyright (C) 2003-2009
98.9 +# Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
98.10 +# (Egervary Research Group on Combinatorial Optimization, EGRES).
98.11 +#
98.12 +# Permission to use, modify and distribute this software is granted
98.13 +# provided that this copyright notice appears in all copies. For
98.14 +# precise terms see the accompanying LICENSE file.
98.15 +#
98.16 +# This software is provided "AS IS" with no warranty of any kind,
98.17 +# express or implied, and with no claim as to its suitability for any
98.18 +# purpose.
98.19 +
98.20 +
98.21 +if [ ! -f ~/.lemon-bootstrap ]; then
98.22 + echo 'Create ~/.lemon-bootstrap'.
98.23 + cat >~/.lemon-bootstrap <<EOF
98.24 +#
98.25 +# Default settings for bootstraping the LEMON source code repository
98.26 +#
98.27 +EOF
98.28 +fi
98.29 +
98.30 +source ~/.lemon-bootstrap
98.31 +if [ -f ../../../.lemon-bootstrap ]; then source ../../../.lemon-bootstrap; fi
98.32 +if [ -f ../../.lemon-bootstrap ]; then source ../../.lemon-bootstrap; fi
98.33 +if [ -f ../.lemon-bootstrap ]; then source ../.lemon-bootstrap; fi
98.34 +if [ -f ./.lemon-bootstrap ]; then source ./.lemon-bootstrap; fi
98.35 +
98.36 +
98.37 +function augment_config() {
98.38 + if [ "x${!1}" == "x" ]; then
98.39 + eval $1=$2
98.40 + echo Add "'$1'" to '~/.lemon-bootstrap'.
98.41 + echo >>~/.lemon-bootstrap
98.42 + echo $3 >>~/.lemon-bootstrap
98.43 + echo $1=$2 >>~/.lemon-bootstrap
98.44 + fi
98.45 +}
98.46 +
98.47 +augment_config LEMON_INSTALL_PREFIX /usr/local \
98.48 + "# LEMON installation prefix"
98.49 +
98.50 +augment_config GLPK_PREFIX /usr/local/ \
98.51 + "# GLPK installation root prefix"
98.52 +
98.53 +augment_config COIN_OR_PREFIX /usr/local/coin-or \
98.54 + "# COIN-OR installation root prefix (used for CLP/CBC)"
98.55 +
98.56 +augment_config SOPLEX_PREFIX /usr/local/soplex \
98.57 + "# Soplex build prefix"
98.58 +
98.59 +
98.60 +function ask() {
98.61 +echo -n "$1 [$2]? "
98.62 +read _an
98.63 +if [ "x$_an" == "x" ]; then
98.64 + ret="$2"
98.65 +else
98.66 + ret=$_an
98.67 +fi
98.68 +}
98.69 +
98.70 +function yesorno() {
98.71 + ret='rossz'
98.72 + while [ "$ret" != "y" -a "$ret" != "n" -a "$ret" != "yes" -a "$ret" != "no" ]; do
98.73 + ask "$1" "$2"
98.74 + done
98.75 + if [ "$ret" != "y" -a "$ret" != "yes" ]; then
98.76 + return 1
98.77 + else
98.78 + return 0
98.79 + fi
98.80 +}
98.81 +
98.82 +if yesorno "External build" "n"
98.83 +then
98.84 + CONFIGURE_PATH=".."
98.85 +else
98.86 + CONFIGURE_PATH="."
98.87 + if yesorno "Autoreconf" "y"
98.88 + then
98.89 + AUTORE=yes
98.90 + else
98.91 + AUTORE=no
98.92 + fi
98.93 +fi
98.94 +
98.95 +if yesorno "Optimize" "n"
98.96 +then
98.97 + opt_flags=' -O2'
98.98 +else
98.99 + opt_flags=''
98.100 +fi
98.101 +
98.102 +if yesorno "Stop on warning" "y"
98.103 +then
98.104 + werror_flags=' -Werror'
98.105 +else
98.106 + werror_flags=''
98.107 +fi
98.108 +
98.109 +cxx_flags="CXXFLAGS=-ggdb$opt_flags$werror_flags"
98.110 +
98.111 +if yesorno "Check with valgrind" "n"
98.112 +then
98.113 + valgrind_flags=' --enable-valgrind'
98.114 +else
98.115 + valgrind_flags=''
98.116 +fi
98.117 +
98.118 +if [ -f ${GLPK_PREFIX}/include/glpk.h ]; then
98.119 + if yesorno "Use GLPK" "y"
98.120 + then
98.121 + glpk_flag="--with-glpk=$GLPK_PREFIX"
98.122 + else
98.123 + glpk_flag="--without-glpk"
98.124 + fi
98.125 +else
98.126 + glpk_flag="--without-glpk"
98.127 +fi
98.128 +
98.129 +if [ -f ${COIN_OR_PREFIX}/include/coin/config_coinutils.h ]; then
98.130 + if yesorno "Use COIN-OR (CBC/CLP)" "n"
98.131 + then
98.132 + coin_flag="--with-coin=$COIN_OR_PREFIX"
98.133 + else
98.134 + coin_flag="--without-coin"
98.135 + fi
98.136 +else
98.137 + coin_flag="--without-coin"
98.138 +fi
98.139 +
98.140 +if [ -f ${SOPLEX_PREFIX}/src/soplex.h ]; then
98.141 + if yesorno "Use Soplex" "n"
98.142 + then
98.143 + soplex_flag="--with-soplex=$SOPLEX_PREFIX"
98.144 + else
98.145 + soplex_flag="--without-soplex"
98.146 + fi
98.147 +else
98.148 + soplex_flag="--without-soplex"
98.149 +fi
98.150 +
98.151 +if [ "x$AUTORE" == "xyes" ]; then
98.152 + autoreconf -vif;
98.153 +fi
98.154 +${CONFIGURE_PATH}/configure --prefix=$LEMON_INSTALL_PREFIX \
98.155 +$valgrind_flags \
98.156 +"$cxx_flags" \
98.157 +$glpk_flag \
98.158 +$coin_flag \
98.159 +$soplex_flag \
98.160 +$*
99.1 --- a/scripts/chg-len.py Tue Dec 20 17:44:38 2011 +0100
99.2 +++ b/scripts/chg-len.py Tue Dec 20 18:15:14 2011 +0100
99.3 @@ -1,4 +1,18 @@
99.4 #! /usr/bin/env python
99.5 +#
99.6 +# This file is a part of LEMON, a generic C++ optimization library.
99.7 +#
99.8 +# Copyright (C) 2003-2009
99.9 +# Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
99.10 +# (Egervary Research Group on Combinatorial Optimization, EGRES).
99.11 +#
99.12 +# Permission to use, modify and distribute this software is granted
99.13 +# provided that this copyright notice appears in all copies. For
99.14 +# precise terms see the accompanying LICENSE file.
99.15 +#
99.16 +# This software is provided "AS IS" with no warranty of any kind,
99.17 +# express or implied, and with no claim as to its suitability for any
99.18 +# purpose.
99.19
99.20 import sys
99.21
100.1 --- a/scripts/mk-release.sh Tue Dec 20 17:44:38 2011 +0100
100.2 +++ b/scripts/mk-release.sh Tue Dec 20 18:15:14 2011 +0100
100.3 @@ -1,4 +1,18 @@
100.4 #!/bin/bash
100.5 +#
100.6 +# This file is a part of LEMON, a generic C++ optimization library.
100.7 +#
100.8 +# Copyright (C) 2003-2009
100.9 +# Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
100.10 +# (Egervary Research Group on Combinatorial Optimization, EGRES).
100.11 +#
100.12 +# Permission to use, modify and distribute this software is granted
100.13 +# provided that this copyright notice appears in all copies. For
100.14 +# precise terms see the accompanying LICENSE file.
100.15 +#
100.16 +# This software is provided "AS IS" with no warranty of any kind,
100.17 +# express or implied, and with no claim as to its suitability for any
100.18 +# purpose.
100.19
100.20 set -e
100.21
101.1 --- a/scripts/unify-sources.sh Tue Dec 20 17:44:38 2011 +0100
101.2 +++ b/scripts/unify-sources.sh Tue Dec 20 18:15:14 2011 +0100
101.3 @@ -1,4 +1,18 @@
101.4 #!/bin/bash
101.5 +#
101.6 +# This file is a part of LEMON, a generic C++ optimization library.
101.7 +#
101.8 +# Copyright (C) 2003-2009
101.9 +# Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
101.10 +# (Egervary Research Group on Combinatorial Optimization, EGRES).
101.11 +#
101.12 +# Permission to use, modify and distribute this software is granted
101.13 +# provided that this copyright notice appears in all copies. For
101.14 +# precise terms see the accompanying LICENSE file.
101.15 +#
101.16 +# This software is provided "AS IS" with no warranty of any kind,
101.17 +# express or implied, and with no claim as to its suitability for any
101.18 +# purpose.
101.19
101.20 YEAR=`date +%Y`
101.21 HGROOT=`hg root`
102.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
102.2 +++ b/scripts/valgrind-wrapper.sh Tue Dec 20 18:15:14 2011 +0100
102.3 @@ -0,0 +1,22 @@
102.4 +#!/bin/sh
102.5 +
102.6 +# Run in valgrind, with leak checking enabled
102.7 +
102.8 +valgrind -q --leak-check=full "$@" 2> .valgrind-log
102.9 +
102.10 +# Save the test result
102.11 +
102.12 +result="$?"
102.13 +
102.14 +# Valgrind should generate no error messages
102.15 +
102.16 +log_contents="`cat .valgrind-log`"
102.17 +
102.18 +if [ "$log_contents" != "" ]; then
102.19 + cat .valgrind-log >&2
102.20 + result=1
102.21 +fi
102.22 +
102.23 +rm -f .valgrind-log
102.24 +
102.25 +exit $result
103.1 --- a/test/CMakeLists.txt Tue Dec 20 17:44:38 2011 +0100
103.2 +++ b/test/CMakeLists.txt Tue Dec 20 18:15:14 2011 +0100
103.3 @@ -13,6 +13,7 @@
103.4
103.5 SET(TESTS
103.6 adaptors_test
103.7 + bellman_ford_test
103.8 bfs_test
103.9 circulation_test
103.10 connectivity_test
103.11 @@ -24,6 +25,7 @@
103.12 edge_set_test
103.13 error_test
103.14 euler_test
103.15 + fractional_matching_test
103.16 gomory_hu_test
103.17 graph_copy_test
103.18 graph_test
103.19 @@ -36,7 +38,9 @@
103.20 matching_test
103.21 min_cost_arborescence_test
103.22 min_cost_flow_test
103.23 + min_mean_cycle_test
103.24 path_test
103.25 + planarity_test
103.26 preflow_test
103.27 radix_sort_test
103.28 random_test
104.1 --- a/test/Makefile.am Tue Dec 20 17:44:38 2011 +0100
104.2 +++ b/test/Makefile.am Tue Dec 20 18:15:14 2011 +0100
104.3 @@ -1,3 +1,7 @@
104.4 +if USE_VALGRIND
104.5 +TESTS_ENVIRONMENT=$(top_srcdir)/scripts/valgrind-wrapper.sh
104.6 +endif
104.7 +
104.8 EXTRA_DIST += \
104.9 test/CMakeLists.txt
104.10
104.11 @@ -7,6 +11,7 @@
104.12
104.13 check_PROGRAMS += \
104.14 test/adaptors_test \
104.15 + test/bellman_ford_test \
104.16 test/bfs_test \
104.17 test/circulation_test \
104.18 test/connectivity_test \
104.19 @@ -18,6 +23,7 @@
104.20 test/edge_set_test \
104.21 test/error_test \
104.22 test/euler_test \
104.23 + test/fractional_matching_test \
104.24 test/gomory_hu_test \
104.25 test/graph_copy_test \
104.26 test/graph_test \
104.27 @@ -30,7 +36,9 @@
104.28 test/matching_test \
104.29 test/min_cost_arborescence_test \
104.30 test/min_cost_flow_test \
104.31 + test/min_mean_cycle_test \
104.32 test/path_test \
104.33 + test/planarity_test \
104.34 test/preflow_test \
104.35 test/radix_sort_test \
104.36 test/random_test \
104.37 @@ -53,6 +61,7 @@
104.38 XFAIL_TESTS += test/test_tools_fail$(EXEEXT)
104.39
104.40 test_adaptors_test_SOURCES = test/adaptors_test.cc
104.41 +test_bellman_ford_test_SOURCES = test/bellman_ford_test.cc
104.42 test_bfs_test_SOURCES = test/bfs_test.cc
104.43 test_circulation_test_SOURCES = test/circulation_test.cc
104.44 test_counter_test_SOURCES = test/counter_test.cc
104.45 @@ -64,6 +73,7 @@
104.46 test_edge_set_test_SOURCES = test/edge_set_test.cc
104.47 test_error_test_SOURCES = test/error_test.cc
104.48 test_euler_test_SOURCES = test/euler_test.cc
104.49 +test_fractional_matching_test_SOURCES = test/fractional_matching_test.cc
104.50 test_gomory_hu_test_SOURCES = test/gomory_hu_test.cc
104.51 test_graph_copy_test_SOURCES = test/graph_copy_test.cc
104.52 test_graph_test_SOURCES = test/graph_test.cc
104.53 @@ -78,7 +88,9 @@
104.54 test_matching_test_SOURCES = test/matching_test.cc
104.55 test_min_cost_arborescence_test_SOURCES = test/min_cost_arborescence_test.cc
104.56 test_min_cost_flow_test_SOURCES = test/min_cost_flow_test.cc
104.57 +test_min_mean_cycle_test_SOURCES = test/min_mean_cycle_test.cc
104.58 test_path_test_SOURCES = test/path_test.cc
104.59 +test_planarity_test_SOURCES = test/planarity_test.cc
104.60 test_preflow_test_SOURCES = test/preflow_test.cc
104.61 test_radix_sort_test_SOURCES = test/radix_sort_test.cc
104.62 test_suurballe_test_SOURCES = test/suurballe_test.cc
105.1 --- a/test/adaptors_test.cc Tue Dec 20 17:44:38 2011 +0100
105.2 +++ b/test/adaptors_test.cc Tue Dec 20 18:15:14 2011 +0100
105.3 @@ -1371,51 +1371,43 @@
105.4 GridGraph::Node n4 = graph(1,1);
105.5
105.6 GridGraph::EdgeMap<bool> dir_map(graph);
105.7 - dir_map[graph.right(n1)] = graph.u(graph.right(n1)) == n1;
105.8 - dir_map[graph.up(n1)] = graph.u(graph.up(n1)) != n1;
105.9 - dir_map[graph.left(n4)] = graph.u(graph.left(n4)) != n4;
105.10 - dir_map[graph.down(n4)] = graph.u(graph.down(n4)) != n4;
105.11 + dir_map[graph.right(n1)] = graph.u(graph.right(n1)) != n1;
105.12 + dir_map[graph.up(n1)] = graph.u(graph.up(n1)) == n1;
105.13 + dir_map[graph.left(n4)] = graph.u(graph.left(n4)) == n4;
105.14 + dir_map[graph.down(n4)] = graph.u(graph.down(n4)) == n4;
105.15
105.16 // Apply several adaptors on the grid graph
105.17 - typedef SplitNodes< ReverseDigraph< const Orienter<
105.18 - const GridGraph, GridGraph::EdgeMap<bool> > > >
105.19 - RevSplitGridGraph;
105.20 - typedef ReverseDigraph<const RevSplitGridGraph> SplitGridGraph;
105.21 + typedef SplitNodes<Orienter< const GridGraph, GridGraph::EdgeMap<bool> > >
105.22 + SplitGridGraph;
105.23 typedef Undirector<const SplitGridGraph> USplitGridGraph;
105.24 - typedef Undirector<const USplitGridGraph> UUSplitGridGraph;
105.25 - checkConcept<concepts::Digraph, RevSplitGridGraph>();
105.26 checkConcept<concepts::Digraph, SplitGridGraph>();
105.27 checkConcept<concepts::Graph, USplitGridGraph>();
105.28 - checkConcept<concepts::Graph, UUSplitGridGraph>();
105.29
105.30 - RevSplitGridGraph rev_adaptor =
105.31 - splitNodes(reverseDigraph(orienter(graph, dir_map)));
105.32 - SplitGridGraph adaptor = reverseDigraph(rev_adaptor);
105.33 + SplitGridGraph adaptor = splitNodes(orienter(graph, dir_map));
105.34 USplitGridGraph uadaptor = undirector(adaptor);
105.35 - UUSplitGridGraph uuadaptor = undirector(uadaptor);
105.36
105.37 // Check adaptor
105.38 checkGraphNodeList(adaptor, 8);
105.39 checkGraphArcList(adaptor, 8);
105.40 checkGraphConArcList(adaptor, 8);
105.41
105.42 - checkGraphOutArcList(adaptor, rev_adaptor.inNode(n1), 1);
105.43 - checkGraphOutArcList(adaptor, rev_adaptor.outNode(n1), 1);
105.44 - checkGraphOutArcList(adaptor, rev_adaptor.inNode(n2), 2);
105.45 - checkGraphOutArcList(adaptor, rev_adaptor.outNode(n2), 1);
105.46 - checkGraphOutArcList(adaptor, rev_adaptor.inNode(n3), 1);
105.47 - checkGraphOutArcList(adaptor, rev_adaptor.outNode(n3), 1);
105.48 - checkGraphOutArcList(adaptor, rev_adaptor.inNode(n4), 0);
105.49 - checkGraphOutArcList(adaptor, rev_adaptor.outNode(n4), 1);
105.50 + checkGraphOutArcList(adaptor, adaptor.inNode(n1), 1);
105.51 + checkGraphOutArcList(adaptor, adaptor.outNode(n1), 1);
105.52 + checkGraphOutArcList(adaptor, adaptor.inNode(n2), 1);
105.53 + checkGraphOutArcList(adaptor, adaptor.outNode(n2), 0);
105.54 + checkGraphOutArcList(adaptor, adaptor.inNode(n3), 1);
105.55 + checkGraphOutArcList(adaptor, adaptor.outNode(n3), 1);
105.56 + checkGraphOutArcList(adaptor, adaptor.inNode(n4), 1);
105.57 + checkGraphOutArcList(adaptor, adaptor.outNode(n4), 2);
105.58
105.59 - checkGraphInArcList(adaptor, rev_adaptor.inNode(n1), 1);
105.60 - checkGraphInArcList(adaptor, rev_adaptor.outNode(n1), 1);
105.61 - checkGraphInArcList(adaptor, rev_adaptor.inNode(n2), 1);
105.62 - checkGraphInArcList(adaptor, rev_adaptor.outNode(n2), 0);
105.63 - checkGraphInArcList(adaptor, rev_adaptor.inNode(n3), 1);
105.64 - checkGraphInArcList(adaptor, rev_adaptor.outNode(n3), 1);
105.65 - checkGraphInArcList(adaptor, rev_adaptor.inNode(n4), 1);
105.66 - checkGraphInArcList(adaptor, rev_adaptor.outNode(n4), 2);
105.67 + checkGraphInArcList(adaptor, adaptor.inNode(n1), 1);
105.68 + checkGraphInArcList(adaptor, adaptor.outNode(n1), 1);
105.69 + checkGraphInArcList(adaptor, adaptor.inNode(n2), 2);
105.70 + checkGraphInArcList(adaptor, adaptor.outNode(n2), 1);
105.71 + checkGraphInArcList(adaptor, adaptor.inNode(n3), 1);
105.72 + checkGraphInArcList(adaptor, adaptor.outNode(n3), 1);
105.73 + checkGraphInArcList(adaptor, adaptor.inNode(n4), 0);
105.74 + checkGraphInArcList(adaptor, adaptor.outNode(n4), 1);
105.75
105.76 checkNodeIds(adaptor);
105.77 checkArcIds(adaptor);
105.78 @@ -1438,29 +1430,14 @@
105.79 checkGraphEdgeMap(uadaptor);
105.80 checkGraphArcMap(uadaptor);
105.81
105.82 - checkGraphIncEdgeArcLists(uadaptor, rev_adaptor.inNode(n1), 2);
105.83 - checkGraphIncEdgeArcLists(uadaptor, rev_adaptor.outNode(n1), 2);
105.84 - checkGraphIncEdgeArcLists(uadaptor, rev_adaptor.inNode(n2), 3);
105.85 - checkGraphIncEdgeArcLists(uadaptor, rev_adaptor.outNode(n2), 1);
105.86 - checkGraphIncEdgeArcLists(uadaptor, rev_adaptor.inNode(n3), 2);
105.87 - checkGraphIncEdgeArcLists(uadaptor, rev_adaptor.outNode(n3), 2);
105.88 - checkGraphIncEdgeArcLists(uadaptor, rev_adaptor.inNode(n4), 1);
105.89 - checkGraphIncEdgeArcLists(uadaptor, rev_adaptor.outNode(n4), 3);
105.90 -
105.91 - // Check uuadaptor
105.92 - checkGraphNodeList(uuadaptor, 8);
105.93 - checkGraphEdgeList(uuadaptor, 16);
105.94 - checkGraphArcList(uuadaptor, 32);
105.95 - checkGraphConEdgeList(uuadaptor, 16);
105.96 - checkGraphConArcList(uuadaptor, 32);
105.97 -
105.98 - checkNodeIds(uuadaptor);
105.99 - checkEdgeIds(uuadaptor);
105.100 - checkArcIds(uuadaptor);
105.101 -
105.102 - checkGraphNodeMap(uuadaptor);
105.103 - checkGraphEdgeMap(uuadaptor);
105.104 - checkGraphArcMap(uuadaptor);
105.105 + checkGraphIncEdgeArcLists(uadaptor, adaptor.inNode(n1), 2);
105.106 + checkGraphIncEdgeArcLists(uadaptor, adaptor.outNode(n1), 2);
105.107 + checkGraphIncEdgeArcLists(uadaptor, adaptor.inNode(n2), 3);
105.108 + checkGraphIncEdgeArcLists(uadaptor, adaptor.outNode(n2), 1);
105.109 + checkGraphIncEdgeArcLists(uadaptor, adaptor.inNode(n3), 2);
105.110 + checkGraphIncEdgeArcLists(uadaptor, adaptor.outNode(n3), 2);
105.111 + checkGraphIncEdgeArcLists(uadaptor, adaptor.inNode(n4), 1);
105.112 + checkGraphIncEdgeArcLists(uadaptor, adaptor.outNode(n4), 3);
105.113 }
105.114
105.115 int main(int, const char **) {
106.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
106.2 +++ b/test/bellman_ford_test.cc Tue Dec 20 18:15:14 2011 +0100
106.3 @@ -0,0 +1,286 @@
106.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
106.5 + *
106.6 + * This file is a part of LEMON, a generic C++ optimization library.
106.7 + *
106.8 + * Copyright (C) 2003-2010
106.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
106.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
106.11 + *
106.12 + * Permission to use, modify and distribute this software is granted
106.13 + * provided that this copyright notice appears in all copies. For
106.14 + * precise terms see the accompanying LICENSE file.
106.15 + *
106.16 + * This software is provided "AS IS" with no warranty of any kind,
106.17 + * express or implied, and with no claim as to its suitability for any
106.18 + * purpose.
106.19 + *
106.20 + */
106.21 +
106.22 +#include <lemon/concepts/digraph.h>
106.23 +#include <lemon/smart_graph.h>
106.24 +#include <lemon/list_graph.h>
106.25 +#include <lemon/lgf_reader.h>
106.26 +#include <lemon/bellman_ford.h>
106.27 +#include <lemon/path.h>
106.28 +
106.29 +#include "graph_test.h"
106.30 +#include "test_tools.h"
106.31 +
106.32 +using namespace lemon;
106.33 +
106.34 +char test_lgf[] =
106.35 + "@nodes\n"
106.36 + "label\n"
106.37 + "0\n"
106.38 + "1\n"
106.39 + "2\n"
106.40 + "3\n"
106.41 + "4\n"
106.42 + "@arcs\n"
106.43 + " length\n"
106.44 + "0 1 3\n"
106.45 + "1 2 -3\n"
106.46 + "1 2 -5\n"
106.47 + "1 3 -2\n"
106.48 + "0 2 -1\n"
106.49 + "1 2 -4\n"
106.50 + "0 3 2\n"
106.51 + "4 2 -5\n"
106.52 + "2 3 1\n"
106.53 + "@attributes\n"
106.54 + "source 0\n"
106.55 + "target 3\n";
106.56 +
106.57 +
106.58 +void checkBellmanFordCompile()
106.59 +{
106.60 + typedef int Value;
106.61 + typedef concepts::Digraph Digraph;
106.62 + typedef concepts::ReadMap<Digraph::Arc,Value> LengthMap;
106.63 + typedef BellmanFord<Digraph, LengthMap> BF;
106.64 + typedef Digraph::Node Node;
106.65 + typedef Digraph::Arc Arc;
106.66 +
106.67 + Digraph gr;
106.68 + Node s, t, n;
106.69 + Arc e;
106.70 + Value l;
106.71 + int k=3;
106.72 + bool b;
106.73 + BF::DistMap d(gr);
106.74 + BF::PredMap p(gr);
106.75 + LengthMap length;
106.76 + concepts::Path<Digraph> pp;
106.77 +
106.78 + {
106.79 + BF bf_test(gr,length);
106.80 + const BF& const_bf_test = bf_test;
106.81 +
106.82 + bf_test.run(s);
106.83 + bf_test.run(s,k);
106.84 +
106.85 + bf_test.init();
106.86 + bf_test.addSource(s);
106.87 + bf_test.addSource(s, 1);
106.88 + b = bf_test.processNextRound();
106.89 + b = bf_test.processNextWeakRound();
106.90 +
106.91 + bf_test.start();
106.92 + bf_test.checkedStart();
106.93 + bf_test.limitedStart(k);
106.94 +
106.95 + l = const_bf_test.dist(t);
106.96 + e = const_bf_test.predArc(t);
106.97 + s = const_bf_test.predNode(t);
106.98 + b = const_bf_test.reached(t);
106.99 + d = const_bf_test.distMap();
106.100 + p = const_bf_test.predMap();
106.101 + pp = const_bf_test.path(t);
106.102 + pp = const_bf_test.negativeCycle();
106.103 +
106.104 + for (BF::ActiveIt it(const_bf_test); it != INVALID; ++it) {}
106.105 + }
106.106 + {
106.107 + BF::SetPredMap<concepts::ReadWriteMap<Node,Arc> >
106.108 + ::SetDistMap<concepts::ReadWriteMap<Node,Value> >
106.109 + ::SetOperationTraits<BellmanFordDefaultOperationTraits<Value> >
106.110 + ::SetOperationTraits<BellmanFordToleranceOperationTraits<Value, 0> >
106.111 + ::Create bf_test(gr,length);
106.112 +
106.113 + LengthMap length_map;
106.114 + concepts::ReadWriteMap<Node,Arc> pred_map;
106.115 + concepts::ReadWriteMap<Node,Value> dist_map;
106.116 +
106.117 + bf_test
106.118 + .lengthMap(length_map)
106.119 + .predMap(pred_map)
106.120 + .distMap(dist_map);
106.121 +
106.122 + bf_test.run(s);
106.123 + bf_test.run(s,k);
106.124 +
106.125 + bf_test.init();
106.126 + bf_test.addSource(s);
106.127 + bf_test.addSource(s, 1);
106.128 + b = bf_test.processNextRound();
106.129 + b = bf_test.processNextWeakRound();
106.130 +
106.131 + bf_test.start();
106.132 + bf_test.checkedStart();
106.133 + bf_test.limitedStart(k);
106.134 +
106.135 + l = bf_test.dist(t);
106.136 + e = bf_test.predArc(t);
106.137 + s = bf_test.predNode(t);
106.138 + b = bf_test.reached(t);
106.139 + pp = bf_test.path(t);
106.140 + pp = bf_test.negativeCycle();
106.141 + }
106.142 +}
106.143 +
106.144 +void checkBellmanFordFunctionCompile()
106.145 +{
106.146 + typedef int Value;
106.147 + typedef concepts::Digraph Digraph;
106.148 + typedef Digraph::Arc Arc;
106.149 + typedef Digraph::Node Node;
106.150 + typedef concepts::ReadMap<Digraph::Arc,Value> LengthMap;
106.151 +
106.152 + Digraph g;
106.153 + bool b;
106.154 + bellmanFord(g,LengthMap()).run(Node());
106.155 + b = bellmanFord(g,LengthMap()).run(Node(),Node());
106.156 + bellmanFord(g,LengthMap())
106.157 + .predMap(concepts::ReadWriteMap<Node,Arc>())
106.158 + .distMap(concepts::ReadWriteMap<Node,Value>())
106.159 + .run(Node());
106.160 + b=bellmanFord(g,LengthMap())
106.161 + .predMap(concepts::ReadWriteMap<Node,Arc>())
106.162 + .distMap(concepts::ReadWriteMap<Node,Value>())
106.163 + .path(concepts::Path<Digraph>())
106.164 + .dist(Value())
106.165 + .run(Node(),Node());
106.166 +}
106.167 +
106.168 +
106.169 +template <typename Digraph, typename Value>
106.170 +void checkBellmanFord() {
106.171 + TEMPLATE_DIGRAPH_TYPEDEFS(Digraph);
106.172 + typedef typename Digraph::template ArcMap<Value> LengthMap;
106.173 +
106.174 + Digraph gr;
106.175 + Node s, t;
106.176 + LengthMap length(gr);
106.177 +
106.178 + std::istringstream input(test_lgf);
106.179 + digraphReader(gr, input).
106.180 + arcMap("length", length).
106.181 + node("source", s).
106.182 + node("target", t).
106.183 + run();
106.184 +
106.185 + BellmanFord<Digraph, LengthMap>
106.186 + bf(gr, length);
106.187 + bf.run(s);
106.188 + Path<Digraph> p = bf.path(t);
106.189 +
106.190 + check(bf.reached(t) && bf.dist(t) == -1, "Bellman-Ford found a wrong path.");
106.191 + check(p.length() == 3, "path() found a wrong path.");
106.192 + check(checkPath(gr, p), "path() found a wrong path.");
106.193 + check(pathSource(gr, p) == s, "path() found a wrong path.");
106.194 + check(pathTarget(gr, p) == t, "path() found a wrong path.");
106.195 +
106.196 + ListPath<Digraph> path;
106.197 + Value dist;
106.198 + bool reached = bellmanFord(gr,length).path(path).dist(dist).run(s,t);
106.199 +
106.200 + check(reached && dist == -1, "Bellman-Ford found a wrong path.");
106.201 + check(path.length() == 3, "path() found a wrong path.");
106.202 + check(checkPath(gr, path), "path() found a wrong path.");
106.203 + check(pathSource(gr, path) == s, "path() found a wrong path.");
106.204 + check(pathTarget(gr, path) == t, "path() found a wrong path.");
106.205 +
106.206 + for(ArcIt e(gr); e!=INVALID; ++e) {
106.207 + Node u=gr.source(e);
106.208 + Node v=gr.target(e);
106.209 + check(!bf.reached(u) || (bf.dist(v) - bf.dist(u) <= length[e]),
106.210 + "Wrong output. dist(target)-dist(source)-arc_length=" <<
106.211 + bf.dist(v) - bf.dist(u) - length[e]);
106.212 + }
106.213 +
106.214 + for(NodeIt v(gr); v!=INVALID; ++v) {
106.215 + if (bf.reached(v)) {
106.216 + check(v==s || bf.predArc(v)!=INVALID, "Wrong tree.");
106.217 + if (bf.predArc(v)!=INVALID ) {
106.218 + Arc e=bf.predArc(v);
106.219 + Node u=gr.source(e);
106.220 + check(u==bf.predNode(v),"Wrong tree.");
106.221 + check(bf.dist(v) - bf.dist(u) == length[e],
106.222 + "Wrong distance! Difference: " <<
106.223 + bf.dist(v) - bf.dist(u) - length[e]);
106.224 + }
106.225 + }
106.226 + }
106.227 +}
106.228 +
106.229 +void checkBellmanFordNegativeCycle() {
106.230 + DIGRAPH_TYPEDEFS(SmartDigraph);
106.231 +
106.232 + SmartDigraph gr;
106.233 + IntArcMap length(gr);
106.234 +
106.235 + Node n1 = gr.addNode();
106.236 + Node n2 = gr.addNode();
106.237 + Node n3 = gr.addNode();
106.238 + Node n4 = gr.addNode();
106.239 +
106.240 + Arc a1 = gr.addArc(n1, n2);
106.241 + Arc a2 = gr.addArc(n2, n2);
106.242 +
106.243 + length[a1] = 2;
106.244 + length[a2] = -1;
106.245 +
106.246 + {
106.247 + BellmanFord<SmartDigraph, IntArcMap> bf(gr, length);
106.248 + bf.run(n1);
106.249 + StaticPath<SmartDigraph> p = bf.negativeCycle();
106.250 + check(p.length() == 1 && p.front() == p.back() && p.front() == a2,
106.251 + "Wrong negative cycle.");
106.252 + }
106.253 +
106.254 + length[a2] = 0;
106.255 +
106.256 + {
106.257 + BellmanFord<SmartDigraph, IntArcMap> bf(gr, length);
106.258 + bf.run(n1);
106.259 + check(bf.negativeCycle().empty(),
106.260 + "Negative cycle should not be found.");
106.261 + }
106.262 +
106.263 + length[gr.addArc(n1, n3)] = 5;
106.264 + length[gr.addArc(n4, n3)] = 1;
106.265 + length[gr.addArc(n2, n4)] = 2;
106.266 + length[gr.addArc(n3, n2)] = -4;
106.267 +
106.268 + {
106.269 + BellmanFord<SmartDigraph, IntArcMap> bf(gr, length);
106.270 + bf.init();
106.271 + bf.addSource(n1);
106.272 + for (int i = 0; i < 4; ++i) {
106.273 + check(bf.negativeCycle().empty(),
106.274 + "Negative cycle should not be found.");
106.275 + bf.processNextRound();
106.276 + }
106.277 + StaticPath<SmartDigraph> p = bf.negativeCycle();
106.278 + check(p.length() == 3, "Wrong negative cycle.");
106.279 + check(length[p.nth(0)] + length[p.nth(1)] + length[p.nth(2)] == -1,
106.280 + "Wrong negative cycle.");
106.281 + }
106.282 +}
106.283 +
106.284 +int main() {
106.285 + checkBellmanFord<ListDigraph, int>();
106.286 + checkBellmanFord<SmartDigraph, double>();
106.287 + checkBellmanFordNegativeCycle();
106.288 + return 0;
106.289 +}
107.1 --- a/test/bfs_test.cc Tue Dec 20 17:44:38 2011 +0100
107.2 +++ b/test/bfs_test.cc Tue Dec 20 18:15:14 2011 +0100
107.3 @@ -2,7 +2,7 @@
107.4 *
107.5 * This file is a part of LEMON, a generic C++ optimization library.
107.6 *
107.7 - * Copyright (C) 2003-2009
107.8 + * Copyright (C) 2003-2010
107.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
107.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
107.11 *
107.12 @@ -83,7 +83,7 @@
107.13 n = const_bfs_test.nextNode();
107.14 b = const_bfs_test.emptyQueue();
107.15 i = const_bfs_test.queueSize();
107.16 -
107.17 +
107.18 bfs_test.start();
107.19 bfs_test.start(t);
107.20 bfs_test.start(nm);
107.21 @@ -104,12 +104,12 @@
107.22 ::SetStandardProcessedMap
107.23 ::SetProcessedMap<concepts::WriteMap<Node,bool> >
107.24 ::Create bfs_test(G);
107.25 -
107.26 +
107.27 concepts::ReadWriteMap<Node,Arc> pred_map;
107.28 concepts::ReadWriteMap<Node,int> dist_map;
107.29 concepts::ReadWriteMap<Node,bool> reached_map;
107.30 concepts::WriteMap<Node,bool> processed_map;
107.31 -
107.32 +
107.33 bfs_test
107.34 .predMap(pred_map)
107.35 .distMap(dist_map)
107.36 @@ -119,7 +119,7 @@
107.37 bfs_test.run(s);
107.38 bfs_test.run(s,t);
107.39 bfs_test.run();
107.40 -
107.41 +
107.42 bfs_test.init();
107.43 bfs_test.addSource(s);
107.44 n = bfs_test.processNextNode();
107.45 @@ -128,7 +128,7 @@
107.46 n = bfs_test.nextNode();
107.47 b = bfs_test.emptyQueue();
107.48 i = bfs_test.queueSize();
107.49 -
107.50 +
107.51 bfs_test.start();
107.52 bfs_test.start(t);
107.53 bfs_test.start(nm);
108.1 --- a/test/circulation_test.cc Tue Dec 20 17:44:38 2011 +0100
108.2 +++ b/test/circulation_test.cc Tue Dec 20 18:15:14 2011 +0100
108.3 @@ -2,7 +2,7 @@
108.4 *
108.5 * This file is a part of LEMON, a generic C++ optimization library.
108.6 *
108.7 - * Copyright (C) 2003-2009
108.8 + * Copyright (C) 2003-2010
108.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
108.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
108.11 *
108.12 @@ -81,13 +81,18 @@
108.13 ::Create CirculationType;
108.14 CirculationType circ_test(g, lcap, ucap, supply);
108.15 const CirculationType& const_circ_test = circ_test;
108.16 -
108.17 +
108.18 circ_test
108.19 .lowerMap(lcap)
108.20 .upperMap(ucap)
108.21 .supplyMap(supply)
108.22 .flowMap(flow);
108.23
108.24 + const CirculationType::Elevator& elev = const_circ_test.elevator();
108.25 + circ_test.elevator(const_cast<CirculationType::Elevator&>(elev));
108.26 + CirculationType::Tolerance tol = const_circ_test.tolerance();
108.27 + circ_test.tolerance(tol);
108.28 +
108.29 circ_test.init();
108.30 circ_test.greedyInit();
108.31 circ_test.start();
108.32 @@ -97,7 +102,7 @@
108.33 const FlowMap& fm = const_circ_test.flowMap();
108.34 b = const_circ_test.barrier(n);
108.35 const_circ_test.barrierMap(bar);
108.36 -
108.37 +
108.38 ignore_unused_variable_warning(fm);
108.39 }
108.40
109.1 --- a/test/connectivity_test.cc Tue Dec 20 17:44:38 2011 +0100
109.2 +++ b/test/connectivity_test.cc Tue Dec 20 18:15:14 2011 +0100
109.3 @@ -2,7 +2,7 @@
109.4 *
109.5 * This file is a part of LEMON, a generic C++ optimization library.
109.6 *
109.7 - * Copyright (C) 2003-2009
109.8 + * Copyright (C) 2003-2010
109.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
109.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
109.11 *
109.12 @@ -29,12 +29,12 @@
109.13 {
109.14 typedef ListDigraph Digraph;
109.15 typedef Undirector<Digraph> Graph;
109.16 -
109.17 +
109.18 {
109.19 Digraph d;
109.20 Digraph::NodeMap<int> order(d);
109.21 Graph g(d);
109.22 -
109.23 +
109.24 check(stronglyConnected(d), "The empty digraph is strongly connected");
109.25 check(countStronglyConnectedComponents(d) == 0,
109.26 "The empty digraph has 0 strongly connected component");
109.27 @@ -48,7 +48,7 @@
109.28 check(biEdgeConnected(g), "The empty graph is bi-edge-connected");
109.29 check(countBiEdgeConnectedComponents(g) == 0,
109.30 "The empty graph has 0 bi-edge-connected component");
109.31 -
109.32 +
109.33 check(dag(d), "The empty digraph is DAG.");
109.34 check(checkedTopologicalSort(d, order), "The empty digraph is DAG.");
109.35 check(loopFree(d), "The empty digraph is loop-free.");
109.36 @@ -82,7 +82,7 @@
109.37 check(biEdgeConnected(g), "This graph is bi-edge-connected");
109.38 check(countBiEdgeConnectedComponents(g) == 1,
109.39 "This graph has 1 bi-edge-connected component");
109.40 -
109.41 +
109.42 check(dag(d), "This digraph is DAG.");
109.43 check(checkedTopologicalSort(d, order), "This digraph is DAG.");
109.44 check(loopFree(d), "This digraph is loop-free.");
109.45 @@ -101,14 +101,14 @@
109.46 Digraph d;
109.47 Digraph::NodeMap<int> order(d);
109.48 Graph g(d);
109.49 -
109.50 +
109.51 Digraph::Node n1 = d.addNode();
109.52 Digraph::Node n2 = d.addNode();
109.53 Digraph::Node n3 = d.addNode();
109.54 Digraph::Node n4 = d.addNode();
109.55 Digraph::Node n5 = d.addNode();
109.56 Digraph::Node n6 = d.addNode();
109.57 -
109.58 +
109.59 d.addArc(n1, n3);
109.60 d.addArc(n3, n2);
109.61 d.addArc(n2, n1);
109.62 @@ -136,23 +136,23 @@
109.63 check(loopFree(g), "This graph is loop-free.");
109.64 check(!parallelFree(g), "This graph is not parallel-free.");
109.65 check(!simpleGraph(g), "This graph is not simple.");
109.66 -
109.67 +
109.68 d.addArc(n3, n3);
109.69 -
109.70 +
109.71 check(!loopFree(d), "This digraph is not loop-free.");
109.72 check(!loopFree(g), "This graph is not loop-free.");
109.73 check(!simpleGraph(d), "This digraph is not simple.");
109.74 -
109.75 +
109.76 d.addArc(n3, n2);
109.77 -
109.78 +
109.79 check(!parallelFree(d), "This digraph is not parallel-free.");
109.80 }
109.81 -
109.82 +
109.83 {
109.84 Digraph d;
109.85 Digraph::ArcMap<bool> cutarcs(d, false);
109.86 Graph g(d);
109.87 -
109.88 +
109.89 Digraph::Node n1 = d.addNode();
109.90 Digraph::Node n2 = d.addNode();
109.91 Digraph::Node n3 = d.addNode();
109.92 @@ -172,7 +172,7 @@
109.93 d.addArc(n1, n8);
109.94 d.addArc(n6, n7);
109.95 d.addArc(n7, n6);
109.96 -
109.97 +
109.98 check(!stronglyConnected(d), "This digraph is not strongly connected");
109.99 check(countStronglyConnectedComponents(d) == 3,
109.100 "This digraph has 3 strongly connected components");
109.101 @@ -235,7 +235,7 @@
109.102 // (T. H. Cormen, C. E. Leiserson, R. L. Rivest, C. Stein)
109.103 Digraph d;
109.104 Digraph::NodeMap<int> order(d);
109.105 -
109.106 +
109.107 Digraph::Node belt = d.addNode();
109.108 Digraph::Node trousers = d.addNode();
109.109 Digraph::Node necktie = d.addNode();
109.110 @@ -255,7 +255,7 @@
109.111 d.addArc(shirt, belt);
109.112 d.addArc(shirt, necktie);
109.113 d.addArc(necktie, coat);
109.114 -
109.115 +
109.116 check(dag(d), "This digraph is DAG.");
109.117 topologicalSort(d, order);
109.118 for (Digraph::ArcIt a(d); a != INVALID; ++a) {
109.119 @@ -267,7 +267,7 @@
109.120 {
109.121 ListGraph g;
109.122 ListGraph::NodeMap<bool> map(g);
109.123 -
109.124 +
109.125 ListGraph::Node n1 = g.addNode();
109.126 ListGraph::Node n2 = g.addNode();
109.127 ListGraph::Node n3 = g.addNode();
109.128 @@ -283,10 +283,10 @@
109.129 g.addEdge(n4, n6);
109.130 g.addEdge(n4, n7);
109.131 g.addEdge(n5, n7);
109.132 -
109.133 +
109.134 check(bipartite(g), "This graph is bipartite");
109.135 check(bipartitePartitions(g, map), "This graph is bipartite");
109.136 -
109.137 +
109.138 check(map[n1] == map[n2] && map[n1] == map[n6] && map[n1] == map[n7],
109.139 "Wrong bipartitePartitions()");
109.140 check(map[n3] == map[n4] && map[n3] == map[n5],
110.1 --- a/test/dfs_test.cc Tue Dec 20 17:44:38 2011 +0100
110.2 +++ b/test/dfs_test.cc Tue Dec 20 18:15:14 2011 +0100
110.3 @@ -2,7 +2,7 @@
110.4 *
110.5 * This file is a part of LEMON, a generic C++ optimization library.
110.6 *
110.7 - * Copyright (C) 2003-2009
110.8 + * Copyright (C) 2003-2010
110.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
110.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
110.11 *
110.12 @@ -86,7 +86,7 @@
110.13 e = const_dfs_test.nextArc();
110.14 b = const_dfs_test.emptyQueue();
110.15 i = const_dfs_test.queueSize();
110.16 -
110.17 +
110.18 dfs_test.start();
110.19 dfs_test.start(t);
110.20 dfs_test.start(am);
110.21 @@ -112,7 +112,7 @@
110.22 concepts::ReadWriteMap<Node,int> dist_map;
110.23 concepts::ReadWriteMap<Node,bool> reached_map;
110.24 concepts::WriteMap<Node,bool> processed_map;
110.25 -
110.26 +
110.27 dfs_test
110.28 .predMap(pred_map)
110.29 .distMap(dist_map)
110.30 @@ -129,7 +129,7 @@
110.31 e = dfs_test.nextArc();
110.32 b = dfs_test.emptyQueue();
110.33 i = dfs_test.queueSize();
110.34 -
110.35 +
110.36 dfs_test.start();
110.37 dfs_test.start(t);
110.38 dfs_test.start(am);
111.1 --- a/test/digraph_test.cc Tue Dec 20 17:44:38 2011 +0100
111.2 +++ b/test/digraph_test.cc Tue Dec 20 18:15:14 2011 +0100
111.3 @@ -2,7 +2,7 @@
111.4 *
111.5 * This file is a part of LEMON, a generic C++ optimization library.
111.6 *
111.7 - * Copyright (C) 2003-2009
111.8 + * Copyright (C) 2003-2010
111.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
111.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
111.11 *
111.12 @@ -19,6 +19,7 @@
111.13 #include <lemon/concepts/digraph.h>
111.14 #include <lemon/list_graph.h>
111.15 #include <lemon/smart_graph.h>
111.16 +#include <lemon/static_graph.h>
111.17 #include <lemon/full_graph.h>
111.18
111.19 #include "test_tools.h"
111.20 @@ -35,6 +36,9 @@
111.21 checkGraphNodeList(G, 0);
111.22 checkGraphArcList(G, 0);
111.23
111.24 + G.reserveNode(3);
111.25 + G.reserveArc(4);
111.26 +
111.27 Node
111.28 n1 = G.addNode(),
111.29 n2 = G.addNode(),
111.30 @@ -283,6 +287,14 @@
111.31 G.addArc(G.addNode(), G.addNode());
111.32
111.33 snapshot.restore();
111.34 + snapshot.save(G);
111.35 +
111.36 + checkGraphNodeList(G, 4);
111.37 + checkGraphArcList(G, 4);
111.38 +
111.39 + G.addArc(G.addNode(), G.addNode());
111.40 +
111.41 + snapshot.restore();
111.42
111.43 checkGraphNodeList(G, 4);
111.44 checkGraphArcList(G, 4);
111.45 @@ -317,6 +329,10 @@
111.46 checkConcept<ExtendableDigraphComponent<>, SmartDigraph>();
111.47 checkConcept<ClearableDigraphComponent<>, SmartDigraph>();
111.48 }
111.49 + { // Checking StaticDigraph
111.50 + checkConcept<Digraph, StaticDigraph>();
111.51 + checkConcept<ClearableDigraphComponent<>, StaticDigraph>();
111.52 + }
111.53 { // Checking FullDigraph
111.54 checkConcept<Digraph, FullDigraph>();
111.55 }
111.56 @@ -372,10 +388,122 @@
111.57 check(!g.valid(g.arcFromId(-1)), "Wrong validity check");
111.58 }
111.59
111.60 +void checkStaticDigraph() {
111.61 + SmartDigraph g;
111.62 + SmartDigraph::NodeMap<StaticDigraph::Node> nref(g);
111.63 + SmartDigraph::ArcMap<StaticDigraph::Arc> aref(g);
111.64 +
111.65 + StaticDigraph G;
111.66 +
111.67 + checkGraphNodeList(G, 0);
111.68 + checkGraphArcList(G, 0);
111.69 +
111.70 + G.build(g, nref, aref);
111.71 +
111.72 + checkGraphNodeList(G, 0);
111.73 + checkGraphArcList(G, 0);
111.74 +
111.75 + SmartDigraph::Node
111.76 + n1 = g.addNode(),
111.77 + n2 = g.addNode(),
111.78 + n3 = g.addNode();
111.79 +
111.80 + G.build(g, nref, aref);
111.81 +
111.82 + checkGraphNodeList(G, 3);
111.83 + checkGraphArcList(G, 0);
111.84 +
111.85 + SmartDigraph::Arc a1 = g.addArc(n1, n2);
111.86 +
111.87 + G.build(g, nref, aref);
111.88 +
111.89 + check(G.source(aref[a1]) == nref[n1] && G.target(aref[a1]) == nref[n2],
111.90 + "Wrong arc or wrong references");
111.91 + checkGraphNodeList(G, 3);
111.92 + checkGraphArcList(G, 1);
111.93 +
111.94 + checkGraphOutArcList(G, nref[n1], 1);
111.95 + checkGraphOutArcList(G, nref[n2], 0);
111.96 + checkGraphOutArcList(G, nref[n3], 0);
111.97 +
111.98 + checkGraphInArcList(G, nref[n1], 0);
111.99 + checkGraphInArcList(G, nref[n2], 1);
111.100 + checkGraphInArcList(G, nref[n3], 0);
111.101 +
111.102 + checkGraphConArcList(G, 1);
111.103 +
111.104 + SmartDigraph::Arc
111.105 + a2 = g.addArc(n2, n1),
111.106 + a3 = g.addArc(n2, n3),
111.107 + a4 = g.addArc(n2, n3);
111.108 +
111.109 + digraphCopy(g, G).nodeRef(nref).run();
111.110 +
111.111 + checkGraphNodeList(G, 3);
111.112 + checkGraphArcList(G, 4);
111.113 +
111.114 + checkGraphOutArcList(G, nref[n1], 1);
111.115 + checkGraphOutArcList(G, nref[n2], 3);
111.116 + checkGraphOutArcList(G, nref[n3], 0);
111.117 +
111.118 + checkGraphInArcList(G, nref[n1], 1);
111.119 + checkGraphInArcList(G, nref[n2], 1);
111.120 + checkGraphInArcList(G, nref[n3], 2);
111.121 +
111.122 + checkGraphConArcList(G, 4);
111.123 +
111.124 + std::vector<std::pair<int,int> > arcs;
111.125 + arcs.push_back(std::make_pair(0,1));
111.126 + arcs.push_back(std::make_pair(0,2));
111.127 + arcs.push_back(std::make_pair(1,3));
111.128 + arcs.push_back(std::make_pair(1,2));
111.129 + arcs.push_back(std::make_pair(3,0));
111.130 + arcs.push_back(std::make_pair(3,3));
111.131 + arcs.push_back(std::make_pair(4,2));
111.132 + arcs.push_back(std::make_pair(4,3));
111.133 + arcs.push_back(std::make_pair(4,1));
111.134 +
111.135 + G.build(6, arcs.begin(), arcs.end());
111.136 +
111.137 + checkGraphNodeList(G, 6);
111.138 + checkGraphArcList(G, 9);
111.139 +
111.140 + checkGraphOutArcList(G, G.node(0), 2);
111.141 + checkGraphOutArcList(G, G.node(1), 2);
111.142 + checkGraphOutArcList(G, G.node(2), 0);
111.143 + checkGraphOutArcList(G, G.node(3), 2);
111.144 + checkGraphOutArcList(G, G.node(4), 3);
111.145 + checkGraphOutArcList(G, G.node(5), 0);
111.146 +
111.147 + checkGraphInArcList(G, G.node(0), 1);
111.148 + checkGraphInArcList(G, G.node(1), 2);
111.149 + checkGraphInArcList(G, G.node(2), 3);
111.150 + checkGraphInArcList(G, G.node(3), 3);
111.151 + checkGraphInArcList(G, G.node(4), 0);
111.152 + checkGraphInArcList(G, G.node(5), 0);
111.153 +
111.154 + checkGraphConArcList(G, 9);
111.155 +
111.156 + checkNodeIds(G);
111.157 + checkArcIds(G);
111.158 + checkGraphNodeMap(G);
111.159 + checkGraphArcMap(G);
111.160 +
111.161 + int n = G.nodeNum();
111.162 + int m = G.arcNum();
111.163 + check(G.index(G.node(n-1)) == n-1, "Wrong index.");
111.164 + check(G.index(G.arc(m-1)) == m-1, "Wrong index.");
111.165 +}
111.166 +
111.167 void checkFullDigraph(int num) {
111.168 typedef FullDigraph Digraph;
111.169 DIGRAPH_TYPEDEFS(Digraph);
111.170 +
111.171 Digraph G(num);
111.172 + check(G.nodeNum() == num && G.arcNum() == num * num, "Wrong size");
111.173 +
111.174 + G.resize(num);
111.175 + check(G.nodeNum() == num && G.arcNum() == num * num, "Wrong size");
111.176
111.177 checkGraphNodeList(G, num);
111.178 checkGraphArcList(G, num * num);
111.179 @@ -419,6 +547,9 @@
111.180 checkDigraphSnapshot<SmartDigraph>();
111.181 checkDigraphValidity<SmartDigraph>();
111.182 }
111.183 + { // Checking StaticDigraph
111.184 + checkStaticDigraph();
111.185 + }
111.186 { // Checking FullDigraph
111.187 checkFullDigraph(8);
111.188 }
112.1 --- a/test/dijkstra_test.cc Tue Dec 20 17:44:38 2011 +0100
112.2 +++ b/test/dijkstra_test.cc Tue Dec 20 18:15:14 2011 +0100
112.3 @@ -2,7 +2,7 @@
112.4 *
112.5 * This file is a part of LEMON, a generic C++ optimization library.
112.6 *
112.7 - * Copyright (C) 2003-2009
112.8 + * Copyright (C) 2003-2010
112.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
112.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
112.11 *
112.12 @@ -85,7 +85,7 @@
112.13 n = const_dijkstra_test.nextNode();
112.14 b = const_dijkstra_test.emptyQueue();
112.15 i = const_dijkstra_test.queueSize();
112.16 -
112.17 +
112.18 dijkstra_test.start();
112.19 dijkstra_test.start(t);
112.20 dijkstra_test.start(nm);
112.21 @@ -109,7 +109,7 @@
112.22 ::SetOperationTraits<DijkstraDefaultOperationTraits<VType> >
112.23 ::SetHeap<BinHeap<VType, concepts::ReadWriteMap<Node,int> > >
112.24 ::SetStandardHeap<BinHeap<VType, concepts::ReadWriteMap<Node,int> > >
112.25 - ::SetHeap<BinHeap<VType, concepts::ReadWriteMap<Node,int> >,
112.26 + ::SetHeap<BinHeap<VType, concepts::ReadWriteMap<Node,int> >,
112.27 concepts::ReadWriteMap<Node,int> >
112.28 ::Create dijkstra_test(G,length);
112.29
112.30 @@ -119,7 +119,7 @@
112.31 concepts::WriteMap<Node,bool> processed_map;
112.32 concepts::ReadWriteMap<Node,int> heap_cross_ref;
112.33 BinHeap<VType, concepts::ReadWriteMap<Node,int> > heap(heap_cross_ref);
112.34 -
112.35 +
112.36 dijkstra_test
112.37 .lengthMap(length_map)
112.38 .predMap(pred_map)
112.39 @@ -136,7 +136,7 @@
112.40 n = dijkstra_test.nextNode();
112.41 b = dijkstra_test.emptyQueue();
112.42 i = dijkstra_test.queueSize();
112.43 -
112.44 +
112.45 dijkstra_test.start();
112.46 dijkstra_test.start(t);
112.47 dijkstra_test.start(nm);
113.1 --- a/test/edge_set_test.cc Tue Dec 20 17:44:38 2011 +0100
113.2 +++ b/test/edge_set_test.cc Tue Dec 20 18:15:14 2011 +0100
113.3 @@ -2,7 +2,7 @@
113.4 *
113.5 * This file is a part of LEMON, a generic C++ optimization library.
113.6 *
113.7 - * Copyright (C) 2003-2008
113.8 + * Copyright (C) 2003-2010
113.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
113.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
113.11 *
114.1 --- a/test/euler_test.cc Tue Dec 20 17:44:38 2011 +0100
114.2 +++ b/test/euler_test.cc Tue Dec 20 18:15:14 2011 +0100
114.3 @@ -2,7 +2,7 @@
114.4 *
114.5 * This file is a part of LEMON, a generic C++ optimization library.
114.6 *
114.7 - * Copyright (C) 2003-2009
114.8 + * Copyright (C) 2003-2010
114.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
114.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
114.11 *
114.12 @@ -85,11 +85,11 @@
114.13 {
114.14 typedef ListDigraph Digraph;
114.15 typedef Undirector<Digraph> Graph;
114.16 -
114.17 +
114.18 {
114.19 Digraph d;
114.20 Graph g(d);
114.21 -
114.22 +
114.23 checkDiEulerIt(d);
114.24 checkDiEulerIt(g);
114.25 checkEulerIt(g);
114.26 @@ -128,7 +128,7 @@
114.27 Digraph::Node n1 = d.addNode();
114.28 Digraph::Node n2 = d.addNode();
114.29 Digraph::Node n3 = d.addNode();
114.30 -
114.31 +
114.32 d.addArc(n1, n2);
114.33 d.addArc(n2, n1);
114.34 d.addArc(n2, n3);
114.35 @@ -153,7 +153,7 @@
114.36 Digraph::Node n4 = d.addNode();
114.37 Digraph::Node n5 = d.addNode();
114.38 Digraph::Node n6 = d.addNode();
114.39 -
114.40 +
114.41 d.addArc(n1, n2);
114.42 d.addArc(n2, n4);
114.43 d.addArc(n1, n3);
114.44 @@ -189,7 +189,7 @@
114.45 Digraph::Node n3 = d.addNode();
114.46 Digraph::Node n4 = d.addNode();
114.47 Digraph::Node n5 = d.addNode();
114.48 -
114.49 +
114.50 d.addArc(n1, n2);
114.51 d.addArc(n2, n3);
114.52 d.addArc(n3, n1);
114.53 @@ -211,7 +211,7 @@
114.54 Digraph::Node n1 = d.addNode();
114.55 Digraph::Node n2 = d.addNode();
114.56 Digraph::Node n3 = d.addNode();
114.57 -
114.58 +
114.59 d.addArc(n1, n2);
114.60 d.addArc(n2, n3);
114.61
115.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
115.2 +++ b/test/fractional_matching_test.cc Tue Dec 20 18:15:14 2011 +0100
115.3 @@ -0,0 +1,525 @@
115.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
115.5 + *
115.6 + * This file is a part of LEMON, a generic C++ optimization library.
115.7 + *
115.8 + * Copyright (C) 2003-2010
115.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
115.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
115.11 + *
115.12 + * Permission to use, modify and distribute this software is granted
115.13 + * provided that this copyright notice appears in all copies. For
115.14 + * precise terms see the accompanying LICENSE file.
115.15 + *
115.16 + * This software is provided "AS IS" with no warranty of any kind,
115.17 + * express or implied, and with no claim as to its suitability for any
115.18 + * purpose.
115.19 + *
115.20 + */
115.21 +
115.22 +#include <iostream>
115.23 +#include <sstream>
115.24 +#include <vector>
115.25 +#include <queue>
115.26 +#include <cstdlib>
115.27 +
115.28 +#include <lemon/fractional_matching.h>
115.29 +#include <lemon/smart_graph.h>
115.30 +#include <lemon/concepts/graph.h>
115.31 +#include <lemon/concepts/maps.h>
115.32 +#include <lemon/lgf_reader.h>
115.33 +#include <lemon/math.h>
115.34 +
115.35 +#include "test_tools.h"
115.36 +
115.37 +using namespace std;
115.38 +using namespace lemon;
115.39 +
115.40 +GRAPH_TYPEDEFS(SmartGraph);
115.41 +
115.42 +
115.43 +const int lgfn = 4;
115.44 +const std::string lgf[lgfn] = {
115.45 + "@nodes\n"
115.46 + "label\n"
115.47 + "0\n"
115.48 + "1\n"
115.49 + "2\n"
115.50 + "3\n"
115.51 + "4\n"
115.52 + "5\n"
115.53 + "6\n"
115.54 + "7\n"
115.55 + "@edges\n"
115.56 + " label weight\n"
115.57 + "7 4 0 984\n"
115.58 + "0 7 1 73\n"
115.59 + "7 1 2 204\n"
115.60 + "2 3 3 583\n"
115.61 + "2 7 4 565\n"
115.62 + "2 1 5 582\n"
115.63 + "0 4 6 551\n"
115.64 + "2 5 7 385\n"
115.65 + "1 5 8 561\n"
115.66 + "5 3 9 484\n"
115.67 + "7 5 10 904\n"
115.68 + "3 6 11 47\n"
115.69 + "7 6 12 888\n"
115.70 + "3 0 13 747\n"
115.71 + "6 1 14 310\n",
115.72 +
115.73 + "@nodes\n"
115.74 + "label\n"
115.75 + "0\n"
115.76 + "1\n"
115.77 + "2\n"
115.78 + "3\n"
115.79 + "4\n"
115.80 + "5\n"
115.81 + "6\n"
115.82 + "7\n"
115.83 + "@edges\n"
115.84 + " label weight\n"
115.85 + "2 5 0 710\n"
115.86 + "0 5 1 241\n"
115.87 + "2 4 2 856\n"
115.88 + "2 6 3 762\n"
115.89 + "4 1 4 747\n"
115.90 + "6 1 5 962\n"
115.91 + "4 7 6 723\n"
115.92 + "1 7 7 661\n"
115.93 + "2 3 8 376\n"
115.94 + "1 0 9 416\n"
115.95 + "6 7 10 391\n",
115.96 +
115.97 + "@nodes\n"
115.98 + "label\n"
115.99 + "0\n"
115.100 + "1\n"
115.101 + "2\n"
115.102 + "3\n"
115.103 + "4\n"
115.104 + "5\n"
115.105 + "6\n"
115.106 + "7\n"
115.107 + "@edges\n"
115.108 + " label weight\n"
115.109 + "6 2 0 553\n"
115.110 + "0 7 1 653\n"
115.111 + "6 3 2 22\n"
115.112 + "4 7 3 846\n"
115.113 + "7 2 4 981\n"
115.114 + "7 6 5 250\n"
115.115 + "5 2 6 539\n",
115.116 +
115.117 + "@nodes\n"
115.118 + "label\n"
115.119 + "0\n"
115.120 + "@edges\n"
115.121 + " label weight\n"
115.122 + "0 0 0 100\n"
115.123 +};
115.124 +
115.125 +void checkMaxFractionalMatchingCompile()
115.126 +{
115.127 + typedef concepts::Graph Graph;
115.128 + typedef Graph::Node Node;
115.129 + typedef Graph::Edge Edge;
115.130 +
115.131 + Graph g;
115.132 + Node n;
115.133 + Edge e;
115.134 +
115.135 + MaxFractionalMatching<Graph> mat_test(g);
115.136 + const MaxFractionalMatching<Graph>&
115.137 + const_mat_test = mat_test;
115.138 +
115.139 + mat_test.init();
115.140 + mat_test.start();
115.141 + mat_test.start(true);
115.142 + mat_test.startPerfect();
115.143 + mat_test.startPerfect(true);
115.144 + mat_test.run();
115.145 + mat_test.run(true);
115.146 + mat_test.runPerfect();
115.147 + mat_test.runPerfect(true);
115.148 +
115.149 + const_mat_test.matchingSize();
115.150 + const_mat_test.matching(e);
115.151 + const_mat_test.matching(n);
115.152 + const MaxFractionalMatching<Graph>::MatchingMap& mmap =
115.153 + const_mat_test.matchingMap();
115.154 + e = mmap[n];
115.155 +
115.156 + const_mat_test.barrier(n);
115.157 +}
115.158 +
115.159 +void checkMaxWeightedFractionalMatchingCompile()
115.160 +{
115.161 + typedef concepts::Graph Graph;
115.162 + typedef Graph::Node Node;
115.163 + typedef Graph::Edge Edge;
115.164 + typedef Graph::EdgeMap<int> WeightMap;
115.165 +
115.166 + Graph g;
115.167 + Node n;
115.168 + Edge e;
115.169 + WeightMap w(g);
115.170 +
115.171 + MaxWeightedFractionalMatching<Graph> mat_test(g, w);
115.172 + const MaxWeightedFractionalMatching<Graph>&
115.173 + const_mat_test = mat_test;
115.174 +
115.175 + mat_test.init();
115.176 + mat_test.start();
115.177 + mat_test.run();
115.178 +
115.179 + const_mat_test.matchingWeight();
115.180 + const_mat_test.matchingSize();
115.181 + const_mat_test.matching(e);
115.182 + const_mat_test.matching(n);
115.183 + const MaxWeightedFractionalMatching<Graph>::MatchingMap& mmap =
115.184 + const_mat_test.matchingMap();
115.185 + e = mmap[n];
115.186 +
115.187 + const_mat_test.dualValue();
115.188 + const_mat_test.nodeValue(n);
115.189 +}
115.190 +
115.191 +void checkMaxWeightedPerfectFractionalMatchingCompile()
115.192 +{
115.193 + typedef concepts::Graph Graph;
115.194 + typedef Graph::Node Node;
115.195 + typedef Graph::Edge Edge;
115.196 + typedef Graph::EdgeMap<int> WeightMap;
115.197 +
115.198 + Graph g;
115.199 + Node n;
115.200 + Edge e;
115.201 + WeightMap w(g);
115.202 +
115.203 + MaxWeightedPerfectFractionalMatching<Graph> mat_test(g, w);
115.204 + const MaxWeightedPerfectFractionalMatching<Graph>&
115.205 + const_mat_test = mat_test;
115.206 +
115.207 + mat_test.init();
115.208 + mat_test.start();
115.209 + mat_test.run();
115.210 +
115.211 + const_mat_test.matchingWeight();
115.212 + const_mat_test.matching(e);
115.213 + const_mat_test.matching(n);
115.214 + const MaxWeightedPerfectFractionalMatching<Graph>::MatchingMap& mmap =
115.215 + const_mat_test.matchingMap();
115.216 + e = mmap[n];
115.217 +
115.218 + const_mat_test.dualValue();
115.219 + const_mat_test.nodeValue(n);
115.220 +}
115.221 +
115.222 +void checkFractionalMatching(const SmartGraph& graph,
115.223 + const MaxFractionalMatching<SmartGraph>& mfm,
115.224 + bool allow_loops = true) {
115.225 + int pv = 0;
115.226 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
115.227 + int indeg = 0;
115.228 + for (InArcIt a(graph, n); a != INVALID; ++a) {
115.229 + if (mfm.matching(graph.source(a)) == a) {
115.230 + ++indeg;
115.231 + }
115.232 + }
115.233 + if (mfm.matching(n) != INVALID) {
115.234 + check(indeg == 1, "Invalid matching");
115.235 + ++pv;
115.236 + } else {
115.237 + check(indeg == 0, "Invalid matching");
115.238 + }
115.239 + }
115.240 + check(pv == mfm.matchingSize(), "Wrong matching size");
115.241 +
115.242 + for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
115.243 + check((e == mfm.matching(graph.u(e)) ? 1 : 0) +
115.244 + (e == mfm.matching(graph.v(e)) ? 1 : 0) ==
115.245 + mfm.matching(e), "Invalid matching");
115.246 + }
115.247 +
115.248 + SmartGraph::NodeMap<bool> processed(graph, false);
115.249 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
115.250 + if (processed[n]) continue;
115.251 + processed[n] = true;
115.252 + if (mfm.matching(n) == INVALID) continue;
115.253 + int num = 1;
115.254 + Node v = graph.target(mfm.matching(n));
115.255 + while (v != n) {
115.256 + processed[v] = true;
115.257 + ++num;
115.258 + v = graph.target(mfm.matching(v));
115.259 + }
115.260 + check(num == 2 || num % 2 == 1, "Wrong cycle size");
115.261 + check(allow_loops || num != 1, "Wrong cycle size");
115.262 + }
115.263 +
115.264 + int anum = 0, bnum = 0;
115.265 + SmartGraph::NodeMap<bool> neighbours(graph, false);
115.266 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
115.267 + if (!mfm.barrier(n)) continue;
115.268 + ++anum;
115.269 + for (SmartGraph::InArcIt a(graph, n); a != INVALID; ++a) {
115.270 + Node u = graph.source(a);
115.271 + if (!allow_loops && u == n) continue;
115.272 + if (!neighbours[u]) {
115.273 + neighbours[u] = true;
115.274 + ++bnum;
115.275 + }
115.276 + }
115.277 + }
115.278 + check(anum - bnum + mfm.matchingSize() == countNodes(graph),
115.279 + "Wrong barrier");
115.280 +}
115.281 +
115.282 +void checkPerfectFractionalMatching(const SmartGraph& graph,
115.283 + const MaxFractionalMatching<SmartGraph>& mfm,
115.284 + bool perfect, bool allow_loops = true) {
115.285 + if (perfect) {
115.286 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
115.287 + int indeg = 0;
115.288 + for (InArcIt a(graph, n); a != INVALID; ++a) {
115.289 + if (mfm.matching(graph.source(a)) == a) {
115.290 + ++indeg;
115.291 + }
115.292 + }
115.293 + check(mfm.matching(n) != INVALID, "Invalid matching");
115.294 + check(indeg == 1, "Invalid matching");
115.295 + }
115.296 + for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
115.297 + check((e == mfm.matching(graph.u(e)) ? 1 : 0) +
115.298 + (e == mfm.matching(graph.v(e)) ? 1 : 0) ==
115.299 + mfm.matching(e), "Invalid matching");
115.300 + }
115.301 + } else {
115.302 + int anum = 0, bnum = 0;
115.303 + SmartGraph::NodeMap<bool> neighbours(graph, false);
115.304 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
115.305 + if (!mfm.barrier(n)) continue;
115.306 + ++anum;
115.307 + for (SmartGraph::InArcIt a(graph, n); a != INVALID; ++a) {
115.308 + Node u = graph.source(a);
115.309 + if (!allow_loops && u == n) continue;
115.310 + if (!neighbours[u]) {
115.311 + neighbours[u] = true;
115.312 + ++bnum;
115.313 + }
115.314 + }
115.315 + }
115.316 + check(anum - bnum > 0, "Wrong barrier");
115.317 + }
115.318 +}
115.319 +
115.320 +void checkWeightedFractionalMatching(const SmartGraph& graph,
115.321 + const SmartGraph::EdgeMap<int>& weight,
115.322 + const MaxWeightedFractionalMatching<SmartGraph>& mwfm,
115.323 + bool allow_loops = true) {
115.324 + for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
115.325 + if (graph.u(e) == graph.v(e) && !allow_loops) continue;
115.326 + int rw = mwfm.nodeValue(graph.u(e)) + mwfm.nodeValue(graph.v(e))
115.327 + - weight[e] * mwfm.dualScale;
115.328 +
115.329 + check(rw >= 0, "Negative reduced weight");
115.330 + check(rw == 0 || !mwfm.matching(e),
115.331 + "Non-zero reduced weight on matching edge");
115.332 + }
115.333 +
115.334 + int pv = 0;
115.335 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
115.336 + int indeg = 0;
115.337 + for (InArcIt a(graph, n); a != INVALID; ++a) {
115.338 + if (mwfm.matching(graph.source(a)) == a) {
115.339 + ++indeg;
115.340 + }
115.341 + }
115.342 + check(indeg <= 1, "Invalid matching");
115.343 + if (mwfm.matching(n) != INVALID) {
115.344 + check(mwfm.nodeValue(n) >= 0, "Invalid node value");
115.345 + check(indeg == 1, "Invalid matching");
115.346 + pv += weight[mwfm.matching(n)];
115.347 + SmartGraph::Node o = graph.target(mwfm.matching(n));
115.348 + } else {
115.349 + check(mwfm.nodeValue(n) == 0, "Invalid matching");
115.350 + check(indeg == 0, "Invalid matching");
115.351 + }
115.352 + }
115.353 +
115.354 + for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
115.355 + check((e == mwfm.matching(graph.u(e)) ? 1 : 0) +
115.356 + (e == mwfm.matching(graph.v(e)) ? 1 : 0) ==
115.357 + mwfm.matching(e), "Invalid matching");
115.358 + }
115.359 +
115.360 + int dv = 0;
115.361 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
115.362 + dv += mwfm.nodeValue(n);
115.363 + }
115.364 +
115.365 + check(pv * mwfm.dualScale == dv * 2, "Wrong duality");
115.366 +
115.367 + SmartGraph::NodeMap<bool> processed(graph, false);
115.368 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
115.369 + if (processed[n]) continue;
115.370 + processed[n] = true;
115.371 + if (mwfm.matching(n) == INVALID) continue;
115.372 + int num = 1;
115.373 + Node v = graph.target(mwfm.matching(n));
115.374 + while (v != n) {
115.375 + processed[v] = true;
115.376 + ++num;
115.377 + v = graph.target(mwfm.matching(v));
115.378 + }
115.379 + check(num == 2 || num % 2 == 1, "Wrong cycle size");
115.380 + check(allow_loops || num != 1, "Wrong cycle size");
115.381 + }
115.382 +
115.383 + return;
115.384 +}
115.385 +
115.386 +void checkWeightedPerfectFractionalMatching(const SmartGraph& graph,
115.387 + const SmartGraph::EdgeMap<int>& weight,
115.388 + const MaxWeightedPerfectFractionalMatching<SmartGraph>& mwpfm,
115.389 + bool allow_loops = true) {
115.390 + for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
115.391 + if (graph.u(e) == graph.v(e) && !allow_loops) continue;
115.392 + int rw = mwpfm.nodeValue(graph.u(e)) + mwpfm.nodeValue(graph.v(e))
115.393 + - weight[e] * mwpfm.dualScale;
115.394 +
115.395 + check(rw >= 0, "Negative reduced weight");
115.396 + check(rw == 0 || !mwpfm.matching(e),
115.397 + "Non-zero reduced weight on matching edge");
115.398 + }
115.399 +
115.400 + int pv = 0;
115.401 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
115.402 + int indeg = 0;
115.403 + for (InArcIt a(graph, n); a != INVALID; ++a) {
115.404 + if (mwpfm.matching(graph.source(a)) == a) {
115.405 + ++indeg;
115.406 + }
115.407 + }
115.408 + check(mwpfm.matching(n) != INVALID, "Invalid perfect matching");
115.409 + check(indeg == 1, "Invalid perfect matching");
115.410 + pv += weight[mwpfm.matching(n)];
115.411 + SmartGraph::Node o = graph.target(mwpfm.matching(n));
115.412 + }
115.413 +
115.414 + for (SmartGraph::EdgeIt e(graph); e != INVALID; ++e) {
115.415 + check((e == mwpfm.matching(graph.u(e)) ? 1 : 0) +
115.416 + (e == mwpfm.matching(graph.v(e)) ? 1 : 0) ==
115.417 + mwpfm.matching(e), "Invalid matching");
115.418 + }
115.419 +
115.420 + int dv = 0;
115.421 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
115.422 + dv += mwpfm.nodeValue(n);
115.423 + }
115.424 +
115.425 + check(pv * mwpfm.dualScale == dv * 2, "Wrong duality");
115.426 +
115.427 + SmartGraph::NodeMap<bool> processed(graph, false);
115.428 + for (SmartGraph::NodeIt n(graph); n != INVALID; ++n) {
115.429 + if (processed[n]) continue;
115.430 + processed[n] = true;
115.431 + if (mwpfm.matching(n) == INVALID) continue;
115.432 + int num = 1;
115.433 + Node v = graph.target(mwpfm.matching(n));
115.434 + while (v != n) {
115.435 + processed[v] = true;
115.436 + ++num;
115.437 + v = graph.target(mwpfm.matching(v));
115.438 + }
115.439 + check(num == 2 || num % 2 == 1, "Wrong cycle size");
115.440 + check(allow_loops || num != 1, "Wrong cycle size");
115.441 + }
115.442 +
115.443 + return;
115.444 +}
115.445 +
115.446 +
115.447 +int main() {
115.448 +
115.449 + for (int i = 0; i < lgfn; ++i) {
115.450 + SmartGraph graph;
115.451 + SmartGraph::EdgeMap<int> weight(graph);
115.452 +
115.453 + istringstream lgfs(lgf[i]);
115.454 + graphReader(graph, lgfs).
115.455 + edgeMap("weight", weight).run();
115.456 +
115.457 + bool perfect_with_loops;
115.458 + {
115.459 + MaxFractionalMatching<SmartGraph> mfm(graph, true);
115.460 + mfm.run();
115.461 + checkFractionalMatching(graph, mfm, true);
115.462 + perfect_with_loops = mfm.matchingSize() == countNodes(graph);
115.463 + }
115.464 +
115.465 + bool perfect_without_loops;
115.466 + {
115.467 + MaxFractionalMatching<SmartGraph> mfm(graph, false);
115.468 + mfm.run();
115.469 + checkFractionalMatching(graph, mfm, false);
115.470 + perfect_without_loops = mfm.matchingSize() == countNodes(graph);
115.471 + }
115.472 +
115.473 + {
115.474 + MaxFractionalMatching<SmartGraph> mfm(graph, true);
115.475 + bool result = mfm.runPerfect();
115.476 + checkPerfectFractionalMatching(graph, mfm, result, true);
115.477 + check(result == perfect_with_loops, "Wrong perfect matching");
115.478 + }
115.479 +
115.480 + {
115.481 + MaxFractionalMatching<SmartGraph> mfm(graph, false);
115.482 + bool result = mfm.runPerfect();
115.483 + checkPerfectFractionalMatching(graph, mfm, result, false);
115.484 + check(result == perfect_without_loops, "Wrong perfect matching");
115.485 + }
115.486 +
115.487 + {
115.488 + MaxWeightedFractionalMatching<SmartGraph> mwfm(graph, weight, true);
115.489 + mwfm.run();
115.490 + checkWeightedFractionalMatching(graph, weight, mwfm, true);
115.491 + }
115.492 +
115.493 + {
115.494 + MaxWeightedFractionalMatching<SmartGraph> mwfm(graph, weight, false);
115.495 + mwfm.run();
115.496 + checkWeightedFractionalMatching(graph, weight, mwfm, false);
115.497 + }
115.498 +
115.499 + {
115.500 + MaxWeightedPerfectFractionalMatching<SmartGraph> mwpfm(graph, weight,
115.501 + true);
115.502 + bool perfect = mwpfm.run();
115.503 + check(perfect == (mwpfm.matchingSize() == countNodes(graph)),
115.504 + "Perfect matching found");
115.505 + check(perfect == perfect_with_loops, "Wrong perfect matching");
115.506 +
115.507 + if (perfect) {
115.508 + checkWeightedPerfectFractionalMatching(graph, weight, mwpfm, true);
115.509 + }
115.510 + }
115.511 +
115.512 + {
115.513 + MaxWeightedPerfectFractionalMatching<SmartGraph> mwpfm(graph, weight,
115.514 + false);
115.515 + bool perfect = mwpfm.run();
115.516 + check(perfect == (mwpfm.matchingSize() == countNodes(graph)),
115.517 + "Perfect matching found");
115.518 + check(perfect == perfect_without_loops, "Wrong perfect matching");
115.519 +
115.520 + if (perfect) {
115.521 + checkWeightedPerfectFractionalMatching(graph, weight, mwpfm, false);
115.522 + }
115.523 + }
115.524 +
115.525 + }
115.526 +
115.527 + return 0;
115.528 +}
116.1 --- a/test/gomory_hu_test.cc Tue Dec 20 17:44:38 2011 +0100
116.2 +++ b/test/gomory_hu_test.cc Tue Dec 20 18:15:14 2011 +0100
116.3 @@ -1,3 +1,21 @@
116.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
116.5 + *
116.6 + * This file is a part of LEMON, a generic C++ optimization library.
116.7 + *
116.8 + * Copyright (C) 2003-2010
116.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
116.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
116.11 + *
116.12 + * Permission to use, modify and distribute this software is granted
116.13 + * provided that this copyright notice appears in all copies. For
116.14 + * precise terms see the accompanying LICENSE file.
116.15 + *
116.16 + * This software is provided "AS IS" with no warranty of any kind,
116.17 + * express or implied, and with no claim as to its suitability for any
116.18 + * purpose.
116.19 + *
116.20 + */
116.21 +
116.22 #include <iostream>
116.23
116.24 #include "test_tools.h"
116.25 @@ -33,7 +51,7 @@
116.26 "@attributes\n"
116.27 "source 0\n"
116.28 "target 3\n";
116.29 -
116.30 +
116.31 void checkGomoryHuCompile()
116.32 {
116.33 typedef int Value;
116.34 @@ -69,7 +87,7 @@
116.35 typedef Graph::NodeMap<bool> BoolNodeMap;
116.36
116.37 int cutValue(const Graph& graph, const BoolNodeMap& cut,
116.38 - const IntEdgeMap& capacity) {
116.39 + const IntEdgeMap& capacity) {
116.40
116.41 int sum = 0;
116.42 for (EdgeIt e(graph); e != INVALID; ++e) {
116.43 @@ -107,7 +125,7 @@
116.44
116.45 int sum=0;
116.46 for(GomoryHu<Graph>::MinCutEdgeIt a(ght, u, v);a!=INVALID;++a)
116.47 - sum+=capacity[a];
116.48 + sum+=capacity[a];
116.49 check(sum == ght.minCutValue(u, v), "Problem with MinCutEdgeIt");
116.50
116.51 sum=0;
116.52 @@ -118,6 +136,6 @@
116.53 check(sum == countNodes(graph), "Problem with MinCutNodeIt");
116.54 }
116.55 }
116.56 -
116.57 +
116.58 return 0;
116.59 }
117.1 --- a/test/graph_test.cc Tue Dec 20 17:44:38 2011 +0100
117.2 +++ b/test/graph_test.cc Tue Dec 20 18:15:14 2011 +0100
117.3 @@ -2,7 +2,7 @@
117.4 *
117.5 * This file is a part of LEMON, a generic C++ optimization library.
117.6 *
117.7 - * Copyright (C) 2003-2009
117.8 + * Copyright (C) 2003-2010
117.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
117.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
117.11 *
117.12 @@ -38,6 +38,9 @@
117.13 checkGraphEdgeList(G, 0);
117.14 checkGraphArcList(G, 0);
117.15
117.16 + G.reserveNode(3);
117.17 + G.reserveEdge(3);
117.18 +
117.19 Node
117.20 n1 = G.addNode(),
117.21 n2 = G.addNode(),
117.22 @@ -256,6 +259,15 @@
117.23 G.addEdge(G.addNode(), G.addNode());
117.24
117.25 snapshot.restore();
117.26 + snapshot.save(G);
117.27 +
117.28 + checkGraphNodeList(G, 4);
117.29 + checkGraphEdgeList(G, 3);
117.30 + checkGraphArcList(G, 6);
117.31 +
117.32 + G.addEdge(G.addNode(), G.addNode());
117.33 +
117.34 + snapshot.restore();
117.35
117.36 checkGraphNodeList(G, 4);
117.37 checkGraphEdgeList(G, 3);
117.38 @@ -267,6 +279,13 @@
117.39 GRAPH_TYPEDEFS(Graph);
117.40
117.41 Graph G(num);
117.42 + check(G.nodeNum() == num && G.edgeNum() == num * (num - 1) / 2,
117.43 + "Wrong size");
117.44 +
117.45 + G.resize(num);
117.46 + check(G.nodeNum() == num && G.edgeNum() == num * (num - 1) / 2,
117.47 + "Wrong size");
117.48 +
117.49 checkGraphNodeList(G, num);
117.50 checkGraphEdgeList(G, num * (num - 1) / 2);
117.51
117.52 @@ -411,6 +430,10 @@
117.53 check(G.width() == width, "Wrong column number");
117.54 check(G.height() == height, "Wrong row number");
117.55
117.56 + G.resize(width, height);
117.57 + check(G.width() == width, "Wrong column number");
117.58 + check(G.height() == height, "Wrong row number");
117.59 +
117.60 for (int i = 0; i < width; ++i) {
117.61 for (int j = 0; j < height; ++j) {
117.62 check(G.col(G(i, j)) == i, "Wrong column");
117.63 @@ -486,6 +509,11 @@
117.64 GRAPH_TYPEDEFS(HypercubeGraph);
117.65
117.66 HypercubeGraph G(dim);
117.67 + check(G.dimension() == dim, "Wrong dimension");
117.68 +
117.69 + G.resize(dim);
117.70 + check(G.dimension() == dim, "Wrong dimension");
117.71 +
117.72 checkGraphNodeList(G, 1 << dim);
117.73 checkGraphEdgeList(G, dim * (1 << (dim-1)));
117.74 checkGraphArcList(G, dim * (1 << dim));
118.1 --- a/test/hao_orlin_test.cc Tue Dec 20 17:44:38 2011 +0100
118.2 +++ b/test/hao_orlin_test.cc Tue Dec 20 18:15:14 2011 +0100
118.3 @@ -2,7 +2,7 @@
118.4 *
118.5 * This file is a part of LEMON, a generic C++ optimization library.
118.6 *
118.7 - * Copyright (C) 2003-2009
118.8 + * Copyright (C) 2003-2010
118.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
118.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
118.11 *
118.12 @@ -83,7 +83,7 @@
118.13 }
118.14
118.15 template <typename Graph, typename CapMap, typename CutMap>
118.16 -typename CapMap::Value
118.17 +typename CapMap::Value
118.18 cutValue(const Graph& graph, const CapMap& cap, const CutMap& cut)
118.19 {
118.20 typename CapMap::Value sum = 0;
118.21 @@ -110,7 +110,7 @@
118.22 HaoOrlin<SmartDigraph> ho(graph, cap1);
118.23 ho.run();
118.24 ho.minCutMap(cut);
118.25 -
118.26 +
118.27 check(ho.minCutValue() == 1, "Wrong cut value");
118.28 check(ho.minCutValue() == cutValue(graph, cap1, cut), "Wrong cut value");
118.29 }
118.30 @@ -126,19 +126,19 @@
118.31 HaoOrlin<SmartDigraph> ho(graph, cap3);
118.32 ho.run();
118.33 ho.minCutMap(cut);
118.34 -
118.35 +
118.36 check(ho.minCutValue() == 1, "Wrong cut value");
118.37 check(ho.minCutValue() == cutValue(graph, cap3, cut), "Wrong cut value");
118.38 }
118.39 -
118.40 +
118.41 typedef Undirector<SmartDigraph> UGraph;
118.42 UGraph ugraph(graph);
118.43 -
118.44 +
118.45 {
118.46 HaoOrlin<UGraph, SmartDigraph::ArcMap<int> > ho(ugraph, cap1);
118.47 ho.run();
118.48 ho.minCutMap(cut);
118.49 -
118.50 +
118.51 check(ho.minCutValue() == 2, "Wrong cut value");
118.52 check(ho.minCutValue() == cutValue(ugraph, cap1, cut), "Wrong cut value");
118.53 }
118.54 @@ -146,7 +146,7 @@
118.55 HaoOrlin<UGraph, SmartDigraph::ArcMap<int> > ho(ugraph, cap2);
118.56 ho.run();
118.57 ho.minCutMap(cut);
118.58 -
118.59 +
118.60 check(ho.minCutValue() == 5, "Wrong cut value");
118.61 check(ho.minCutValue() == cutValue(ugraph, cap2, cut), "Wrong cut value");
118.62 }
118.63 @@ -154,7 +154,7 @@
118.64 HaoOrlin<UGraph, SmartDigraph::ArcMap<int> > ho(ugraph, cap3);
118.65 ho.run();
118.66 ho.minCutMap(cut);
118.67 -
118.68 +
118.69 check(ho.minCutValue() == 5, "Wrong cut value");
118.70 check(ho.minCutValue() == cutValue(ugraph, cap3, cut), "Wrong cut value");
118.71 }
119.1 --- a/test/heap_test.cc Tue Dec 20 17:44:38 2011 +0100
119.2 +++ b/test/heap_test.cc Tue Dec 20 18:15:14 2011 +0100
119.3 @@ -25,14 +25,17 @@
119.4 #include <lemon/concepts/heap.h>
119.5
119.6 #include <lemon/smart_graph.h>
119.7 -
119.8 #include <lemon/lgf_reader.h>
119.9 #include <lemon/dijkstra.h>
119.10 #include <lemon/maps.h>
119.11
119.12 #include <lemon/bin_heap.h>
119.13 +#include <lemon/quad_heap.h>
119.14 +#include <lemon/dheap.h>
119.15 #include <lemon/fib_heap.h>
119.16 +#include <lemon/pairing_heap.h>
119.17 #include <lemon/radix_heap.h>
119.18 +#include <lemon/binomial_heap.h>
119.19 #include <lemon/bucket_heap.h>
119.20
119.21 #include "test_tools.h"
119.22 @@ -89,18 +92,16 @@
119.23 template <typename Heap>
119.24 void heapSortTest() {
119.25 RangeMap<int> map(test_len, -1);
119.26 -
119.27 Heap heap(map);
119.28
119.29 std::vector<int> v(test_len);
119.30 -
119.31 for (int i = 0; i < test_len; ++i) {
119.32 v[i] = test_seq[i];
119.33 heap.push(i, v[i]);
119.34 }
119.35 std::sort(v.begin(), v.end());
119.36 for (int i = 0; i < test_len; ++i) {
119.37 - check(v[i] == heap.prio() ,"Wrong order in heap sort.");
119.38 + check(v[i] == heap.prio(), "Wrong order in heap sort.");
119.39 heap.pop();
119.40 }
119.41 }
119.42 @@ -112,7 +113,6 @@
119.43 Heap heap(map);
119.44
119.45 std::vector<int> v(test_len);
119.46 -
119.47 for (int i = 0; i < test_len; ++i) {
119.48 v[i] = test_seq[i];
119.49 heap.push(i, v[i]);
119.50 @@ -123,13 +123,11 @@
119.51 }
119.52 std::sort(v.begin(), v.end());
119.53 for (int i = 0; i < test_len; ++i) {
119.54 - check(v[i] == heap.prio() ,"Wrong order in heap increase test.");
119.55 + check(v[i] == heap.prio(), "Wrong order in heap increase test.");
119.56 heap.pop();
119.57 }
119.58 }
119.59
119.60 -
119.61 -
119.62 template <typename Heap>
119.63 void dijkstraHeapTest(const Digraph& digraph, const IntArcMap& length,
119.64 Node source) {
119.65 @@ -144,7 +142,7 @@
119.66 Node t = digraph.target(a);
119.67 if (dijkstra.reached(s)) {
119.68 check( dijkstra.dist(t) - dijkstra.dist(s) <= length[a],
119.69 - "Error in a shortest path tree!");
119.70 + "Error in shortest path tree.");
119.71 }
119.72 }
119.73
119.74 @@ -153,7 +151,7 @@
119.75 Arc a = dijkstra.predArc(n);
119.76 Node s = digraph.source(a);
119.77 check( dijkstra.dist(n) - dijkstra.dist(s) == length[a],
119.78 - "Error in a shortest path tree!");
119.79 + "Error in shortest path tree.");
119.80 }
119.81 }
119.82
119.83 @@ -175,6 +173,7 @@
119.84 node("source", source).
119.85 run();
119.86
119.87 + // BinHeap
119.88 {
119.89 typedef BinHeap<Prio, ItemIntMap> IntHeap;
119.90 checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
119.91 @@ -186,6 +185,93 @@
119.92 dijkstraHeapTest<NodeHeap>(digraph, length, source);
119.93 }
119.94
119.95 + // QuadHeap
119.96 + {
119.97 + typedef QuadHeap<Prio, ItemIntMap> IntHeap;
119.98 + checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
119.99 + heapSortTest<IntHeap>();
119.100 + heapIncreaseTest<IntHeap>();
119.101 +
119.102 + typedef QuadHeap<Prio, IntNodeMap > NodeHeap;
119.103 + checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
119.104 + dijkstraHeapTest<NodeHeap>(digraph, length, source);
119.105 + }
119.106 +
119.107 + // DHeap
119.108 + {
119.109 + typedef DHeap<Prio, ItemIntMap> IntHeap;
119.110 + checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
119.111 + heapSortTest<IntHeap>();
119.112 + heapIncreaseTest<IntHeap>();
119.113 +
119.114 + typedef DHeap<Prio, IntNodeMap > NodeHeap;
119.115 + checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
119.116 + dijkstraHeapTest<NodeHeap>(digraph, length, source);
119.117 + }
119.118 +
119.119 + // FibHeap
119.120 + {
119.121 + typedef FibHeap<Prio, ItemIntMap> IntHeap;
119.122 + checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
119.123 + heapSortTest<IntHeap>();
119.124 + heapIncreaseTest<IntHeap>();
119.125 +
119.126 + typedef FibHeap<Prio, IntNodeMap > NodeHeap;
119.127 + checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
119.128 + dijkstraHeapTest<NodeHeap>(digraph, length, source);
119.129 + }
119.130 +
119.131 + // PairingHeap
119.132 + {
119.133 + typedef PairingHeap<Prio, ItemIntMap> IntHeap;
119.134 + checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
119.135 + heapSortTest<IntHeap>();
119.136 + heapIncreaseTest<IntHeap>();
119.137 +
119.138 + typedef PairingHeap<Prio, IntNodeMap > NodeHeap;
119.139 + checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
119.140 + dijkstraHeapTest<NodeHeap>(digraph, length, source);
119.141 + }
119.142 +
119.143 + // RadixHeap
119.144 + {
119.145 + typedef RadixHeap<ItemIntMap> IntHeap;
119.146 + checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
119.147 + heapSortTest<IntHeap>();
119.148 + heapIncreaseTest<IntHeap>();
119.149 +
119.150 + typedef RadixHeap<IntNodeMap > NodeHeap;
119.151 + checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
119.152 + dijkstraHeapTest<NodeHeap>(digraph, length, source);
119.153 + }
119.154 +
119.155 + // BinomialHeap
119.156 + {
119.157 + typedef BinomialHeap<Prio, ItemIntMap> IntHeap;
119.158 + checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
119.159 + heapSortTest<IntHeap>();
119.160 + heapIncreaseTest<IntHeap>();
119.161 +
119.162 + typedef BinomialHeap<Prio, IntNodeMap > NodeHeap;
119.163 + checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
119.164 + dijkstraHeapTest<NodeHeap>(digraph, length, source);
119.165 + }
119.166 +
119.167 + // BucketHeap, SimpleBucketHeap
119.168 + {
119.169 + typedef BucketHeap<ItemIntMap> IntHeap;
119.170 + checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
119.171 + heapSortTest<IntHeap>();
119.172 + heapIncreaseTest<IntHeap>();
119.173 +
119.174 + typedef BucketHeap<IntNodeMap > NodeHeap;
119.175 + checkConcept<Heap<Prio, IntNodeMap >, NodeHeap>();
119.176 + dijkstraHeapTest<NodeHeap>(digraph, length, source);
119.177 +
119.178 + typedef SimpleBucketHeap<ItemIntMap> SimpleIntHeap;
119.179 + heapSortTest<SimpleIntHeap>();
119.180 + }
119.181 +
119.182 {
119.183 typedef FibHeap<Prio, ItemIntMap> IntHeap;
119.184 checkConcept<Heap<Prio, ItemIntMap>, IntHeap>();
120.1 --- a/test/maps_test.cc Tue Dec 20 17:44:38 2011 +0100
120.2 +++ b/test/maps_test.cc Tue Dec 20 18:15:14 2011 +0100
120.3 @@ -2,7 +2,7 @@
120.4 *
120.5 * This file is a part of LEMON, a generic C++ optimization library.
120.6 *
120.7 - * Copyright (C) 2003-2009
120.8 + * Copyright (C) 2003-2010
120.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
120.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
120.11 *
120.12 @@ -23,6 +23,10 @@
120.13 #include <lemon/concepts/maps.h>
120.14 #include <lemon/maps.h>
120.15 #include <lemon/list_graph.h>
120.16 +#include <lemon/smart_graph.h>
120.17 +#include <lemon/adaptors.h>
120.18 +#include <lemon/dfs.h>
120.19 +#include <algorithm>
120.20
120.21 #include "test_tools.h"
120.22
120.23 @@ -34,9 +38,22 @@
120.24 struct B {};
120.25
120.26 class C {
120.27 - int x;
120.28 + int _x;
120.29 public:
120.30 - C(int _x) : x(_x) {}
120.31 + C(int x) : _x(x) {}
120.32 + int get() const { return _x; }
120.33 +};
120.34 +inline bool operator<(C c1, C c2) { return c1.get() < c2.get(); }
120.35 +inline bool operator==(C c1, C c2) { return c1.get() == c2.get(); }
120.36 +
120.37 +C createC(int x) { return C(x); }
120.38 +
120.39 +template <typename T>
120.40 +class Less {
120.41 + T _t;
120.42 +public:
120.43 + Less(T t): _t(t) {}
120.44 + bool operator()(const T& t) const { return t < _t; }
120.45 };
120.46
120.47 class F {
120.48 @@ -53,6 +70,14 @@
120.49
120.50 int binc(int a, B) { return a+1; }
120.51
120.52 +template <typename T>
120.53 +class Sum {
120.54 + T& _sum;
120.55 +public:
120.56 + Sum(T& sum) : _sum(sum) {}
120.57 + void operator()(const T& t) { _sum += t; }
120.58 +};
120.59 +
120.60 typedef ReadMap<A, double> DoubleMap;
120.61 typedef ReadWriteMap<A, double> DoubleWriteMap;
120.62 typedef ReferenceMap<A, double, double&, const double&> DoubleRefMap;
120.63 @@ -200,7 +225,8 @@
120.64 B b = functorToMap(F())[A()];
120.65
120.66 checkConcept<ReadMap<A,B>, MapToFunctor<ReadMap<A,B> > >();
120.67 - MapToFunctor<ReadMap<A,B> > map = MapToFunctor<ReadMap<A,B> >(ReadMap<A,B>());
120.68 + MapToFunctor<ReadMap<A,B> > map =
120.69 + MapToFunctor<ReadMap<A,B> >(ReadMap<A,B>());
120.70
120.71 check(functorToMap(&func)[A()] == 3,
120.72 "Something is wrong with FunctorToMap");
120.73 @@ -329,6 +355,10 @@
120.74 // LoggerBoolMap
120.75 {
120.76 typedef std::vector<int> vec;
120.77 + checkConcept<WriteMap<int, bool>, LoggerBoolMap<vec::iterator> >();
120.78 + checkConcept<WriteMap<int, bool>,
120.79 + LoggerBoolMap<std::back_insert_iterator<vec> > >();
120.80 +
120.81 vec v1;
120.82 vec v2(10);
120.83 LoggerBoolMap<std::back_insert_iterator<vec> >
120.84 @@ -348,8 +378,158 @@
120.85 for ( LoggerBoolMap<vec::iterator>::Iterator it = map2.begin();
120.86 it != map2.end(); ++it )
120.87 check(v1[i++] == *it, "Something is wrong with LoggerBoolMap");
120.88 +
120.89 + typedef ListDigraph Graph;
120.90 + DIGRAPH_TYPEDEFS(Graph);
120.91 + Graph gr;
120.92 +
120.93 + Node n0 = gr.addNode();
120.94 + Node n1 = gr.addNode();
120.95 + Node n2 = gr.addNode();
120.96 + Node n3 = gr.addNode();
120.97 +
120.98 + gr.addArc(n3, n0);
120.99 + gr.addArc(n3, n2);
120.100 + gr.addArc(n0, n2);
120.101 + gr.addArc(n2, n1);
120.102 + gr.addArc(n0, n1);
120.103 +
120.104 + {
120.105 + std::vector<Node> v;
120.106 + dfs(gr).processedMap(loggerBoolMap(std::back_inserter(v))).run();
120.107 +
120.108 + check(v.size()==4 && v[0]==n1 && v[1]==n2 && v[2]==n0 && v[3]==n3,
120.109 + "Something is wrong with LoggerBoolMap");
120.110 + }
120.111 + {
120.112 + std::vector<Node> v(countNodes(gr));
120.113 + dfs(gr).processedMap(loggerBoolMap(v.begin())).run();
120.114 +
120.115 + check(v.size()==4 && v[0]==n1 && v[1]==n2 && v[2]==n0 && v[3]==n3,
120.116 + "Something is wrong with LoggerBoolMap");
120.117 + }
120.118 }
120.119 -
120.120 +
120.121 + // IdMap, RangeIdMap
120.122 + {
120.123 + typedef ListDigraph Graph;
120.124 + DIGRAPH_TYPEDEFS(Graph);
120.125 +
120.126 + checkConcept<ReadMap<Node, int>, IdMap<Graph, Node> >();
120.127 + checkConcept<ReadMap<Arc, int>, IdMap<Graph, Arc> >();
120.128 + checkConcept<ReadMap<Node, int>, RangeIdMap<Graph, Node> >();
120.129 + checkConcept<ReadMap<Arc, int>, RangeIdMap<Graph, Arc> >();
120.130 +
120.131 + Graph gr;
120.132 + IdMap<Graph, Node> nmap(gr);
120.133 + IdMap<Graph, Arc> amap(gr);
120.134 + RangeIdMap<Graph, Node> nrmap(gr);
120.135 + RangeIdMap<Graph, Arc> armap(gr);
120.136 +
120.137 + Node n0 = gr.addNode();
120.138 + Node n1 = gr.addNode();
120.139 + Node n2 = gr.addNode();
120.140 +
120.141 + Arc a0 = gr.addArc(n0, n1);
120.142 + Arc a1 = gr.addArc(n0, n2);
120.143 + Arc a2 = gr.addArc(n2, n1);
120.144 + Arc a3 = gr.addArc(n2, n0);
120.145 +
120.146 + check(nmap[n0] == gr.id(n0) && nmap(gr.id(n0)) == n0, "Wrong IdMap");
120.147 + check(nmap[n1] == gr.id(n1) && nmap(gr.id(n1)) == n1, "Wrong IdMap");
120.148 + check(nmap[n2] == gr.id(n2) && nmap(gr.id(n2)) == n2, "Wrong IdMap");
120.149 +
120.150 + check(amap[a0] == gr.id(a0) && amap(gr.id(a0)) == a0, "Wrong IdMap");
120.151 + check(amap[a1] == gr.id(a1) && amap(gr.id(a1)) == a1, "Wrong IdMap");
120.152 + check(amap[a2] == gr.id(a2) && amap(gr.id(a2)) == a2, "Wrong IdMap");
120.153 + check(amap[a3] == gr.id(a3) && amap(gr.id(a3)) == a3, "Wrong IdMap");
120.154 +
120.155 + check(nmap.inverse()[gr.id(n0)] == n0, "Wrong IdMap::InverseMap");
120.156 + check(amap.inverse()[gr.id(a0)] == a0, "Wrong IdMap::InverseMap");
120.157 +
120.158 + check(nrmap.size() == 3 && armap.size() == 4,
120.159 + "Wrong RangeIdMap::size()");
120.160 +
120.161 + check(nrmap[n0] == 0 && nrmap(0) == n0, "Wrong RangeIdMap");
120.162 + check(nrmap[n1] == 1 && nrmap(1) == n1, "Wrong RangeIdMap");
120.163 + check(nrmap[n2] == 2 && nrmap(2) == n2, "Wrong RangeIdMap");
120.164 +
120.165 + check(armap[a0] == 0 && armap(0) == a0, "Wrong RangeIdMap");
120.166 + check(armap[a1] == 1 && armap(1) == a1, "Wrong RangeIdMap");
120.167 + check(armap[a2] == 2 && armap(2) == a2, "Wrong RangeIdMap");
120.168 + check(armap[a3] == 3 && armap(3) == a3, "Wrong RangeIdMap");
120.169 +
120.170 + check(nrmap.inverse()[0] == n0, "Wrong RangeIdMap::InverseMap");
120.171 + check(armap.inverse()[0] == a0, "Wrong RangeIdMap::InverseMap");
120.172 +
120.173 + gr.erase(n1);
120.174 +
120.175 + if (nrmap[n0] == 1) nrmap.swap(n0, n2);
120.176 + nrmap.swap(n2, n0);
120.177 + if (armap[a1] == 1) armap.swap(a1, a3);
120.178 + armap.swap(a3, a1);
120.179 +
120.180 + check(nrmap.size() == 2 && armap.size() == 2,
120.181 + "Wrong RangeIdMap::size()");
120.182 +
120.183 + check(nrmap[n0] == 1 && nrmap(1) == n0, "Wrong RangeIdMap");
120.184 + check(nrmap[n2] == 0 && nrmap(0) == n2, "Wrong RangeIdMap");
120.185 +
120.186 + check(armap[a1] == 1 && armap(1) == a1, "Wrong RangeIdMap");
120.187 + check(armap[a3] == 0 && armap(0) == a3, "Wrong RangeIdMap");
120.188 +
120.189 + check(nrmap.inverse()[0] == n2, "Wrong RangeIdMap::InverseMap");
120.190 + check(armap.inverse()[0] == a3, "Wrong RangeIdMap::InverseMap");
120.191 + }
120.192 +
120.193 + // SourceMap, TargetMap, ForwardMap, BackwardMap, InDegMap, OutDegMap
120.194 + {
120.195 + typedef ListGraph Graph;
120.196 + GRAPH_TYPEDEFS(Graph);
120.197 +
120.198 + checkConcept<ReadMap<Arc, Node>, SourceMap<Graph> >();
120.199 + checkConcept<ReadMap<Arc, Node>, TargetMap<Graph> >();
120.200 + checkConcept<ReadMap<Edge, Arc>, ForwardMap<Graph> >();
120.201 + checkConcept<ReadMap<Edge, Arc>, BackwardMap<Graph> >();
120.202 + checkConcept<ReadMap<Node, int>, InDegMap<Graph> >();
120.203 + checkConcept<ReadMap<Node, int>, OutDegMap<Graph> >();
120.204 +
120.205 + Graph gr;
120.206 + Node n0 = gr.addNode();
120.207 + Node n1 = gr.addNode();
120.208 + Node n2 = gr.addNode();
120.209 +
120.210 + gr.addEdge(n0,n1);
120.211 + gr.addEdge(n1,n2);
120.212 + gr.addEdge(n0,n2);
120.213 + gr.addEdge(n2,n1);
120.214 + gr.addEdge(n1,n2);
120.215 + gr.addEdge(n0,n1);
120.216 +
120.217 + for (EdgeIt e(gr); e != INVALID; ++e) {
120.218 + check(forwardMap(gr)[e] == gr.direct(e, true), "Wrong ForwardMap");
120.219 + check(backwardMap(gr)[e] == gr.direct(e, false), "Wrong BackwardMap");
120.220 + }
120.221 +
120.222 + check(mapCompare(gr,
120.223 + sourceMap(orienter(gr, constMap<Edge, bool>(true))),
120.224 + targetMap(orienter(gr, constMap<Edge, bool>(false)))),
120.225 + "Wrong SourceMap or TargetMap");
120.226 +
120.227 + typedef Orienter<Graph, const ConstMap<Edge, bool> > Digraph;
120.228 + Digraph dgr(gr, constMap<Edge, bool>(true));
120.229 + OutDegMap<Digraph> odm(dgr);
120.230 + InDegMap<Digraph> idm(dgr);
120.231 +
120.232 + check(odm[n0] == 3 && odm[n1] == 2 && odm[n2] == 1, "Wrong OutDegMap");
120.233 + check(idm[n0] == 0 && idm[n1] == 3 && idm[n2] == 3, "Wrong InDegMap");
120.234 +
120.235 + gr.addEdge(n2, n0);
120.236 +
120.237 + check(odm[n0] == 3 && odm[n1] == 2 && odm[n2] == 2, "Wrong OutDegMap");
120.238 + check(idm[n0] == 1 && idm[n1] == 3 && idm[n2] == 3, "Wrong InDegMap");
120.239 + }
120.240 +
120.241 // CrossRefMap
120.242 {
120.243 typedef ListDigraph Graph;
120.244 @@ -357,16 +537,83 @@
120.245
120.246 checkConcept<ReadWriteMap<Node, int>,
120.247 CrossRefMap<Graph, Node, int> >();
120.248 -
120.249 + checkConcept<ReadWriteMap<Node, bool>,
120.250 + CrossRefMap<Graph, Node, bool> >();
120.251 + checkConcept<ReadWriteMap<Node, double>,
120.252 + CrossRefMap<Graph, Node, double> >();
120.253 +
120.254 + Graph gr;
120.255 + typedef CrossRefMap<Graph, Node, char> CRMap;
120.256 + CRMap map(gr);
120.257 +
120.258 + Node n0 = gr.addNode();
120.259 + Node n1 = gr.addNode();
120.260 + Node n2 = gr.addNode();
120.261 +
120.262 + map.set(n0, 'A');
120.263 + map.set(n1, 'B');
120.264 + map.set(n2, 'C');
120.265 +
120.266 + check(map[n0] == 'A' && map('A') == n0 && map.inverse()['A'] == n0,
120.267 + "Wrong CrossRefMap");
120.268 + check(map[n1] == 'B' && map('B') == n1 && map.inverse()['B'] == n1,
120.269 + "Wrong CrossRefMap");
120.270 + check(map[n2] == 'C' && map('C') == n2 && map.inverse()['C'] == n2,
120.271 + "Wrong CrossRefMap");
120.272 + check(map.count('A') == 1 && map.count('B') == 1 && map.count('C') == 1,
120.273 + "Wrong CrossRefMap::count()");
120.274 +
120.275 + CRMap::ValueIt it = map.beginValue();
120.276 + check(*it++ == 'A' && *it++ == 'B' && *it++ == 'C' &&
120.277 + it == map.endValue(), "Wrong value iterator");
120.278 +
120.279 + map.set(n2, 'A');
120.280 +
120.281 + check(map[n0] == 'A' && map[n1] == 'B' && map[n2] == 'A',
120.282 + "Wrong CrossRefMap");
120.283 + check(map('A') == n0 && map.inverse()['A'] == n0, "Wrong CrossRefMap");
120.284 + check(map('B') == n1 && map.inverse()['B'] == n1, "Wrong CrossRefMap");
120.285 + check(map('C') == INVALID && map.inverse()['C'] == INVALID,
120.286 + "Wrong CrossRefMap");
120.287 + check(map.count('A') == 2 && map.count('B') == 1 && map.count('C') == 0,
120.288 + "Wrong CrossRefMap::count()");
120.289 +
120.290 + it = map.beginValue();
120.291 + check(*it++ == 'A' && *it++ == 'A' && *it++ == 'B' &&
120.292 + it == map.endValue(), "Wrong value iterator");
120.293 +
120.294 + map.set(n0, 'C');
120.295 +
120.296 + check(map[n0] == 'C' && map[n1] == 'B' && map[n2] == 'A',
120.297 + "Wrong CrossRefMap");
120.298 + check(map('A') == n2 && map.inverse()['A'] == n2, "Wrong CrossRefMap");
120.299 + check(map('B') == n1 && map.inverse()['B'] == n1, "Wrong CrossRefMap");
120.300 + check(map('C') == n0 && map.inverse()['C'] == n0, "Wrong CrossRefMap");
120.301 + check(map.count('A') == 1 && map.count('B') == 1 && map.count('C') == 1,
120.302 + "Wrong CrossRefMap::count()");
120.303 +
120.304 + it = map.beginValue();
120.305 + check(*it++ == 'A' && *it++ == 'B' && *it++ == 'C' &&
120.306 + it == map.endValue(), "Wrong value iterator");
120.307 + }
120.308 +
120.309 + // CrossRefMap
120.310 + {
120.311 + typedef SmartDigraph Graph;
120.312 + DIGRAPH_TYPEDEFS(Graph);
120.313 +
120.314 + checkConcept<ReadWriteMap<Node, int>,
120.315 + CrossRefMap<Graph, Node, int> >();
120.316 +
120.317 Graph gr;
120.318 typedef CrossRefMap<Graph, Node, char> CRMap;
120.319 typedef CRMap::ValueIterator ValueIt;
120.320 CRMap map(gr);
120.321 -
120.322 +
120.323 Node n0 = gr.addNode();
120.324 Node n1 = gr.addNode();
120.325 Node n2 = gr.addNode();
120.326 -
120.327 +
120.328 map.set(n0, 'A');
120.329 map.set(n1, 'B');
120.330 map.set(n2, 'C');
120.331 @@ -384,5 +631,373 @@
120.332 it == map.endValue(), "Wrong value iterator");
120.333 }
120.334
120.335 + // Iterable bool map
120.336 + {
120.337 + typedef SmartGraph Graph;
120.338 + typedef SmartGraph::Node Item;
120.339 +
120.340 + typedef IterableBoolMap<SmartGraph, SmartGraph::Node> Ibm;
120.341 + checkConcept<ReferenceMap<Item, bool, bool&, const bool&>, Ibm>();
120.342 +
120.343 + const int num = 10;
120.344 + Graph g;
120.345 + Ibm map0(g, true);
120.346 + std::vector<Item> items;
120.347 + for (int i = 0; i < num; ++i) {
120.348 + items.push_back(g.addNode());
120.349 + }
120.350 +
120.351 + Ibm map1(g, true);
120.352 + int n = 0;
120.353 + for (Ibm::TrueIt it(map1); it != INVALID; ++it) {
120.354 + check(map1[static_cast<Item>(it)], "Wrong TrueIt");
120.355 + ++n;
120.356 + }
120.357 + check(n == num, "Wrong number");
120.358 +
120.359 + n = 0;
120.360 + for (Ibm::ItemIt it(map1, true); it != INVALID; ++it) {
120.361 + check(map1[static_cast<Item>(it)], "Wrong ItemIt for true");
120.362 + ++n;
120.363 + }
120.364 + check(n == num, "Wrong number");
120.365 + check(Ibm::FalseIt(map1) == INVALID, "Wrong FalseIt");
120.366 + check(Ibm::ItemIt(map1, false) == INVALID, "Wrong ItemIt for false");
120.367 +
120.368 + map1[items[5]] = true;
120.369 +
120.370 + n = 0;
120.371 + for (Ibm::ItemIt it(map1, true); it != INVALID; ++it) {
120.372 + check(map1[static_cast<Item>(it)], "Wrong ItemIt for true");
120.373 + ++n;
120.374 + }
120.375 + check(n == num, "Wrong number");
120.376 +
120.377 + map1[items[num / 2]] = false;
120.378 + check(map1[items[num / 2]] == false, "Wrong map value");
120.379 +
120.380 + n = 0;
120.381 + for (Ibm::TrueIt it(map1); it != INVALID; ++it) {
120.382 + check(map1[static_cast<Item>(it)], "Wrong TrueIt for true");
120.383 + ++n;
120.384 + }
120.385 + check(n == num - 1, "Wrong number");
120.386 +
120.387 + n = 0;
120.388 + for (Ibm::FalseIt it(map1); it != INVALID; ++it) {
120.389 + check(!map1[static_cast<Item>(it)], "Wrong FalseIt for true");
120.390 + ++n;
120.391 + }
120.392 + check(n == 1, "Wrong number");
120.393 +
120.394 + map1[items[0]] = false;
120.395 + check(map1[items[0]] == false, "Wrong map value");
120.396 +
120.397 + map1[items[num - 1]] = false;
120.398 + check(map1[items[num - 1]] == false, "Wrong map value");
120.399 +
120.400 + n = 0;
120.401 + for (Ibm::TrueIt it(map1); it != INVALID; ++it) {
120.402 + check(map1[static_cast<Item>(it)], "Wrong TrueIt for true");
120.403 + ++n;
120.404 + }
120.405 + check(n == num - 3, "Wrong number");
120.406 + check(map1.trueNum() == num - 3, "Wrong number");
120.407 +
120.408 + n = 0;
120.409 + for (Ibm::FalseIt it(map1); it != INVALID; ++it) {
120.410 + check(!map1[static_cast<Item>(it)], "Wrong FalseIt for true");
120.411 + ++n;
120.412 + }
120.413 + check(n == 3, "Wrong number");
120.414 + check(map1.falseNum() == 3, "Wrong number");
120.415 + }
120.416 +
120.417 + // Iterable int map
120.418 + {
120.419 + typedef SmartGraph Graph;
120.420 + typedef SmartGraph::Node Item;
120.421 + typedef IterableIntMap<SmartGraph, SmartGraph::Node> Iim;
120.422 +
120.423 + checkConcept<ReferenceMap<Item, int, int&, const int&>, Iim>();
120.424 +
120.425 + const int num = 10;
120.426 + Graph g;
120.427 + Iim map0(g, 0);
120.428 + std::vector<Item> items;
120.429 + for (int i = 0; i < num; ++i) {
120.430 + items.push_back(g.addNode());
120.431 + }
120.432 +
120.433 + Iim map1(g);
120.434 + check(map1.size() == 0, "Wrong size");
120.435 +
120.436 + for (int i = 0; i < num; ++i) {
120.437 + map1[items[i]] = i;
120.438 + }
120.439 + check(map1.size() == num, "Wrong size");
120.440 +
120.441 + for (int i = 0; i < num; ++i) {
120.442 + Iim::ItemIt it(map1, i);
120.443 + check(static_cast<Item>(it) == items[i], "Wrong value");
120.444 + ++it;
120.445 + check(static_cast<Item>(it) == INVALID, "Wrong value");
120.446 + }
120.447 +
120.448 + for (int i = 0; i < num; ++i) {
120.449 + map1[items[i]] = i % 2;
120.450 + }
120.451 + check(map1.size() == 2, "Wrong size");
120.452 +
120.453 + int n = 0;
120.454 + for (Iim::ItemIt it(map1, 0); it != INVALID; ++it) {
120.455 + check(map1[static_cast<Item>(it)] == 0, "Wrong value");
120.456 + ++n;
120.457 + }
120.458 + check(n == (num + 1) / 2, "Wrong number");
120.459 +
120.460 + for (Iim::ItemIt it(map1, 1); it != INVALID; ++it) {
120.461 + check(map1[static_cast<Item>(it)] == 1, "Wrong value");
120.462 + ++n;
120.463 + }
120.464 + check(n == num, "Wrong number");
120.465 +
120.466 + }
120.467 +
120.468 + // Iterable value map
120.469 + {
120.470 + typedef SmartGraph Graph;
120.471 + typedef SmartGraph::Node Item;
120.472 + typedef IterableValueMap<SmartGraph, SmartGraph::Node, double> Ivm;
120.473 +
120.474 + checkConcept<ReadWriteMap<Item, double>, Ivm>();
120.475 +
120.476 + const int num = 10;
120.477 + Graph g;
120.478 + Ivm map0(g, 0.0);
120.479 + std::vector<Item> items;
120.480 + for (int i = 0; i < num; ++i) {
120.481 + items.push_back(g.addNode());
120.482 + }
120.483 +
120.484 + Ivm map1(g, 0.0);
120.485 + check(distance(map1.beginValue(), map1.endValue()) == 1, "Wrong size");
120.486 + check(*map1.beginValue() == 0.0, "Wrong value");
120.487 +
120.488 + for (int i = 0; i < num; ++i) {
120.489 + map1.set(items[i], static_cast<double>(i));
120.490 + }
120.491 + check(distance(map1.beginValue(), map1.endValue()) == num, "Wrong size");
120.492 +
120.493 + for (int i = 0; i < num; ++i) {
120.494 + Ivm::ItemIt it(map1, static_cast<double>(i));
120.495 + check(static_cast<Item>(it) == items[i], "Wrong value");
120.496 + ++it;
120.497 + check(static_cast<Item>(it) == INVALID, "Wrong value");
120.498 + }
120.499 +
120.500 + for (Ivm::ValueIt vit = map1.beginValue();
120.501 + vit != map1.endValue(); ++vit) {
120.502 + check(map1[static_cast<Item>(Ivm::ItemIt(map1, *vit))] == *vit,
120.503 + "Wrong ValueIt");
120.504 + }
120.505 +
120.506 + for (int i = 0; i < num; ++i) {
120.507 + map1.set(items[i], static_cast<double>(i % 2));
120.508 + }
120.509 + check(distance(map1.beginValue(), map1.endValue()) == 2, "Wrong size");
120.510 +
120.511 + int n = 0;
120.512 + for (Ivm::ItemIt it(map1, 0.0); it != INVALID; ++it) {
120.513 + check(map1[static_cast<Item>(it)] == 0.0, "Wrong value");
120.514 + ++n;
120.515 + }
120.516 + check(n == (num + 1) / 2, "Wrong number");
120.517 +
120.518 + for (Ivm::ItemIt it(map1, 1.0); it != INVALID; ++it) {
120.519 + check(map1[static_cast<Item>(it)] == 1.0, "Wrong value");
120.520 + ++n;
120.521 + }
120.522 + check(n == num, "Wrong number");
120.523 +
120.524 + }
120.525 +
120.526 + // Graph map utilities:
120.527 + // mapMin(), mapMax(), mapMinValue(), mapMaxValue()
120.528 + // mapFind(), mapFindIf(), mapCount(), mapCountIf()
120.529 + // mapCopy(), mapCompare(), mapFill()
120.530 + {
120.531 + DIGRAPH_TYPEDEFS(SmartDigraph);
120.532 +
120.533 + SmartDigraph g;
120.534 + Node n1 = g.addNode();
120.535 + Node n2 = g.addNode();
120.536 + Node n3 = g.addNode();
120.537 +
120.538 + SmartDigraph::NodeMap<int> map1(g);
120.539 + SmartDigraph::ArcMap<char> map2(g);
120.540 + ConstMap<Node, A> cmap1 = A();
120.541 + ConstMap<Arc, C> cmap2 = C(0);
120.542 +
120.543 + map1[n1] = 10;
120.544 + map1[n2] = 5;
120.545 + map1[n3] = 12;
120.546 +
120.547 + // mapMin(), mapMax(), mapMinValue(), mapMaxValue()
120.548 + check(mapMin(g, map1) == n2, "Wrong mapMin()");
120.549 + check(mapMax(g, map1) == n3, "Wrong mapMax()");
120.550 + check(mapMin(g, map1, std::greater<int>()) == n3, "Wrong mapMin()");
120.551 + check(mapMax(g, map1, std::greater<int>()) == n2, "Wrong mapMax()");
120.552 + check(mapMinValue(g, map1) == 5, "Wrong mapMinValue()");
120.553 + check(mapMaxValue(g, map1) == 12, "Wrong mapMaxValue()");
120.554 +
120.555 + check(mapMin(g, map2) == INVALID, "Wrong mapMin()");
120.556 + check(mapMax(g, map2) == INVALID, "Wrong mapMax()");
120.557 +
120.558 + check(mapMin(g, cmap1) != INVALID, "Wrong mapMin()");
120.559 + check(mapMax(g, cmap2) == INVALID, "Wrong mapMax()");
120.560 +
120.561 + Arc a1 = g.addArc(n1, n2);
120.562 + Arc a2 = g.addArc(n1, n3);
120.563 + Arc a3 = g.addArc(n2, n3);
120.564 + Arc a4 = g.addArc(n3, n1);
120.565 +
120.566 + map2[a1] = 'b';
120.567 + map2[a2] = 'a';
120.568 + map2[a3] = 'b';
120.569 + map2[a4] = 'c';
120.570 +
120.571 + // mapMin(), mapMax(), mapMinValue(), mapMaxValue()
120.572 + check(mapMin(g, map2) == a2, "Wrong mapMin()");
120.573 + check(mapMax(g, map2) == a4, "Wrong mapMax()");
120.574 + check(mapMin(g, map2, std::greater<int>()) == a4, "Wrong mapMin()");
120.575 + check(mapMax(g, map2, std::greater<int>()) == a2, "Wrong mapMax()");
120.576 + check(mapMinValue(g, map2, std::greater<int>()) == 'c',
120.577 + "Wrong mapMinValue()");
120.578 + check(mapMaxValue(g, map2, std::greater<int>()) == 'a',
120.579 + "Wrong mapMaxValue()");
120.580 +
120.581 + check(mapMin(g, cmap1) != INVALID, "Wrong mapMin()");
120.582 + check(mapMax(g, cmap2) != INVALID, "Wrong mapMax()");
120.583 + check(mapMaxValue(g, cmap2) == C(0), "Wrong mapMaxValue()");
120.584 +
120.585 + check(mapMin(g, composeMap(functorToMap(&createC), map2)) == a2,
120.586 + "Wrong mapMin()");
120.587 + check(mapMax(g, composeMap(functorToMap(&createC), map2)) == a4,
120.588 + "Wrong mapMax()");
120.589 + check(mapMinValue(g, composeMap(functorToMap(&createC), map2)) == C('a'),
120.590 + "Wrong mapMinValue()");
120.591 + check(mapMaxValue(g, composeMap(functorToMap(&createC), map2)) == C('c'),
120.592 + "Wrong mapMaxValue()");
120.593 +
120.594 + // mapFind(), mapFindIf()
120.595 + check(mapFind(g, map1, 5) == n2, "Wrong mapFind()");
120.596 + check(mapFind(g, map1, 6) == INVALID, "Wrong mapFind()");
120.597 + check(mapFind(g, map2, 'a') == a2, "Wrong mapFind()");
120.598 + check(mapFind(g, map2, 'e') == INVALID, "Wrong mapFind()");
120.599 + check(mapFind(g, cmap2, C(0)) == ArcIt(g), "Wrong mapFind()");
120.600 + check(mapFind(g, cmap2, C(1)) == INVALID, "Wrong mapFind()");
120.601 +
120.602 + check(mapFindIf(g, map1, Less<int>(7)) == n2,
120.603 + "Wrong mapFindIf()");
120.604 + check(mapFindIf(g, map1, Less<int>(5)) == INVALID,
120.605 + "Wrong mapFindIf()");
120.606 + check(mapFindIf(g, map2, Less<char>('d')) == ArcIt(g),
120.607 + "Wrong mapFindIf()");
120.608 + check(mapFindIf(g, map2, Less<char>('a')) == INVALID,
120.609 + "Wrong mapFindIf()");
120.610 +
120.611 + // mapCount(), mapCountIf()
120.612 + check(mapCount(g, map1, 5) == 1, "Wrong mapCount()");
120.613 + check(mapCount(g, map1, 6) == 0, "Wrong mapCount()");
120.614 + check(mapCount(g, map2, 'a') == 1, "Wrong mapCount()");
120.615 + check(mapCount(g, map2, 'b') == 2, "Wrong mapCount()");
120.616 + check(mapCount(g, map2, 'e') == 0, "Wrong mapCount()");
120.617 + check(mapCount(g, cmap2, C(0)) == 4, "Wrong mapCount()");
120.618 + check(mapCount(g, cmap2, C(1)) == 0, "Wrong mapCount()");
120.619 +
120.620 + check(mapCountIf(g, map1, Less<int>(11)) == 2,
120.621 + "Wrong mapCountIf()");
120.622 + check(mapCountIf(g, map1, Less<int>(13)) == 3,
120.623 + "Wrong mapCountIf()");
120.624 + check(mapCountIf(g, map1, Less<int>(5)) == 0,
120.625 + "Wrong mapCountIf()");
120.626 + check(mapCountIf(g, map2, Less<char>('d')) == 4,
120.627 + "Wrong mapCountIf()");
120.628 + check(mapCountIf(g, map2, Less<char>('c')) == 3,
120.629 + "Wrong mapCountIf()");
120.630 + check(mapCountIf(g, map2, Less<char>('a')) == 0,
120.631 + "Wrong mapCountIf()");
120.632 +
120.633 + // MapIt, ConstMapIt
120.634 +/*
120.635 +These tests can be used after applying bugfix #330
120.636 + typedef SmartDigraph::NodeMap<int>::MapIt MapIt;
120.637 + typedef SmartDigraph::NodeMap<int>::ConstMapIt ConstMapIt;
120.638 + check(*std::min_element(MapIt(map1), MapIt(INVALID)) == 5,
120.639 + "Wrong NodeMap<>::MapIt");
120.640 + check(*std::max_element(ConstMapIt(map1), ConstMapIt(INVALID)) == 12,
120.641 + "Wrong NodeMap<>::MapIt");
120.642 +
120.643 + int sum = 0;
120.644 + std::for_each(MapIt(map1), MapIt(INVALID), Sum<int>(sum));
120.645 + check(sum == 27, "Wrong NodeMap<>::MapIt");
120.646 + std::for_each(ConstMapIt(map1), ConstMapIt(INVALID), Sum<int>(sum));
120.647 + check(sum == 54, "Wrong NodeMap<>::ConstMapIt");
120.648 +*/
120.649 +
120.650 + // mapCopy(), mapCompare(), mapFill()
120.651 + check(mapCompare(g, map1, map1), "Wrong mapCompare()");
120.652 + check(mapCompare(g, cmap2, cmap2), "Wrong mapCompare()");
120.653 + check(mapCompare(g, map1, shiftMap(map1, 0)), "Wrong mapCompare()");
120.654 + check(mapCompare(g, map2, scaleMap(map2, 1)), "Wrong mapCompare()");
120.655 + check(!mapCompare(g, map1, shiftMap(map1, 1)), "Wrong mapCompare()");
120.656 +
120.657 + SmartDigraph::NodeMap<int> map3(g, 0);
120.658 + SmartDigraph::ArcMap<char> map4(g, 'a');
120.659 +
120.660 + check(!mapCompare(g, map1, map3), "Wrong mapCompare()");
120.661 + check(!mapCompare(g, map2, map4), "Wrong mapCompare()");
120.662 +
120.663 + mapCopy(g, map1, map3);
120.664 + mapCopy(g, map2, map4);
120.665 +
120.666 + check(mapCompare(g, map1, map3), "Wrong mapCompare() or mapCopy()");
120.667 + check(mapCompare(g, map2, map4), "Wrong mapCompare() or mapCopy()");
120.668 +
120.669 + Undirector<SmartDigraph> ug(g);
120.670 + Undirector<SmartDigraph>::EdgeMap<char> umap1(ug, 'x');
120.671 + Undirector<SmartDigraph>::ArcMap<double> umap2(ug, 3.14);
120.672 +
120.673 + check(!mapCompare(g, map2, umap1), "Wrong mapCompare() or mapCopy()");
120.674 + check(!mapCompare(g, umap1, map2), "Wrong mapCompare() or mapCopy()");
120.675 + check(!mapCompare(ug, map2, umap1), "Wrong mapCompare() or mapCopy()");
120.676 + check(!mapCompare(ug, umap1, map2), "Wrong mapCompare() or mapCopy()");
120.677 +
120.678 + mapCopy(g, map2, umap1);
120.679 +
120.680 + check(mapCompare(g, map2, umap1), "Wrong mapCompare() or mapCopy()");
120.681 + check(mapCompare(g, umap1, map2), "Wrong mapCompare() or mapCopy()");
120.682 + check(mapCompare(ug, map2, umap1), "Wrong mapCompare() or mapCopy()");
120.683 + check(mapCompare(ug, umap1, map2), "Wrong mapCompare() or mapCopy()");
120.684 +
120.685 + mapCopy(g, map2, umap1);
120.686 + mapCopy(g, umap1, map2);
120.687 + mapCopy(ug, map2, umap1);
120.688 + mapCopy(ug, umap1, map2);
120.689 +
120.690 + check(!mapCompare(ug, umap1, umap2), "Wrong mapCompare() or mapCopy()");
120.691 + mapCopy(ug, umap1, umap2);
120.692 + check(mapCompare(ug, umap1, umap2), "Wrong mapCompare() or mapCopy()");
120.693 +
120.694 + check(!mapCompare(g, map1, constMap<Node>(2)), "Wrong mapCompare()");
120.695 + mapFill(g, map1, 2);
120.696 + check(mapCompare(g, constMap<Node>(2), map1), "Wrong mapFill()");
120.697 +
120.698 + check(!mapCompare(g, map2, constMap<Arc>('z')), "Wrong mapCompare()");
120.699 + mapCopy(g, constMap<Arc>('z'), map2);
120.700 + check(mapCompare(g, constMap<Arc>('z'), map2), "Wrong mapCopy()");
120.701 + }
120.702 +
120.703 return 0;
120.704 }
121.1 --- a/test/matching_test.cc Tue Dec 20 17:44:38 2011 +0100
121.2 +++ b/test/matching_test.cc Tue Dec 20 18:15:14 2011 +0100
121.3 @@ -2,7 +2,7 @@
121.4 *
121.5 * This file is a part of LEMON, a generic C++ optimization library.
121.6 *
121.7 - * Copyright (C) 2003-2009
121.8 + * Copyright (C) 2003-2010
121.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
121.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
121.11 *
121.12 @@ -134,7 +134,7 @@
121.13 mat_test.startSparse();
121.14 mat_test.startDense();
121.15 mat_test.run();
121.16 -
121.17 +
121.18 const_mat_test.matchingSize();
121.19 const_mat_test.matching(e);
121.20 const_mat_test.matching(n);
121.21 @@ -143,7 +143,7 @@
121.22 e = mmap[n];
121.23 const_mat_test.mate(n);
121.24
121.25 - MaxMatching<Graph>::Status stat =
121.26 + MaxMatching<Graph>::Status stat =
121.27 const_mat_test.status(n);
121.28 const MaxMatching<Graph>::StatusMap& smap =
121.29 const_mat_test.statusMap();
121.30 @@ -170,7 +170,7 @@
121.31 mat_test.init();
121.32 mat_test.start();
121.33 mat_test.run();
121.34 -
121.35 +
121.36 const_mat_test.matchingWeight();
121.37 const_mat_test.matchingSize();
121.38 const_mat_test.matching(e);
121.39 @@ -179,7 +179,7 @@
121.40 const_mat_test.matchingMap();
121.41 e = mmap[n];
121.42 const_mat_test.mate(n);
121.43 -
121.44 +
121.45 int k = 0;
121.46 const_mat_test.dualValue();
121.47 const_mat_test.nodeValue(n);
121.48 @@ -207,7 +207,7 @@
121.49 mat_test.init();
121.50 mat_test.start();
121.51 mat_test.run();
121.52 -
121.53 +
121.54 const_mat_test.matchingWeight();
121.55 const_mat_test.matching(e);
121.56 const_mat_test.matching(n);
121.57 @@ -215,7 +215,7 @@
121.58 const_mat_test.matchingMap();
121.59 e = mmap[n];
121.60 const_mat_test.mate(n);
121.61 -
121.62 +
121.63 int k = 0;
121.64 const_mat_test.dualValue();
121.65 const_mat_test.nodeValue(n);
121.66 @@ -401,22 +401,46 @@
121.67 graphReader(graph, lgfs).
121.68 edgeMap("weight", weight).run();
121.69
121.70 - MaxMatching<SmartGraph> mm(graph);
121.71 - mm.run();
121.72 - checkMatching(graph, mm);
121.73 + bool perfect;
121.74 + {
121.75 + MaxMatching<SmartGraph> mm(graph);
121.76 + mm.run();
121.77 + checkMatching(graph, mm);
121.78 + perfect = 2 * mm.matchingSize() == countNodes(graph);
121.79 + }
121.80
121.81 - MaxWeightedMatching<SmartGraph> mwm(graph, weight);
121.82 - mwm.run();
121.83 - checkWeightedMatching(graph, weight, mwm);
121.84 + {
121.85 + MaxWeightedMatching<SmartGraph> mwm(graph, weight);
121.86 + mwm.run();
121.87 + checkWeightedMatching(graph, weight, mwm);
121.88 + }
121.89
121.90 - MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
121.91 - bool perfect = mwpm.run();
121.92 + {
121.93 + MaxWeightedMatching<SmartGraph> mwm(graph, weight);
121.94 + mwm.init();
121.95 + mwm.start();
121.96 + checkWeightedMatching(graph, weight, mwm);
121.97 + }
121.98
121.99 - check(perfect == (mm.matchingSize() * 2 == countNodes(graph)),
121.100 - "Perfect matching found");
121.101 + {
121.102 + MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
121.103 + bool result = mwpm.run();
121.104
121.105 - if (perfect) {
121.106 - checkWeightedPerfectMatching(graph, weight, mwpm);
121.107 + check(result == perfect, "Perfect matching found");
121.108 + if (perfect) {
121.109 + checkWeightedPerfectMatching(graph, weight, mwpm);
121.110 + }
121.111 + }
121.112 +
121.113 + {
121.114 + MaxWeightedPerfectMatching<SmartGraph> mwpm(graph, weight);
121.115 + mwpm.init();
121.116 + bool result = mwpm.start();
121.117 +
121.118 + check(result == perfect, "Perfect matching found");
121.119 + if (perfect) {
121.120 + checkWeightedPerfectMatching(graph, weight, mwpm);
121.121 + }
121.122 }
121.123 }
121.124
122.1 --- a/test/min_cost_arborescence_test.cc Tue Dec 20 17:44:38 2011 +0100
122.2 +++ b/test/min_cost_arborescence_test.cc Tue Dec 20 18:15:14 2011 +0100
122.3 @@ -2,7 +2,7 @@
122.4 *
122.5 * This file is a part of LEMON, a generic C++ optimization library.
122.6 *
122.7 - * Copyright (C) 2003-2008
122.8 + * Copyright (C) 2003-2010
122.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
122.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
122.11 *
122.12 @@ -110,7 +110,7 @@
122.13 n = mcarb_test.processNextNode();
122.14 b = const_mcarb_test.emptyQueue();
122.15 i = const_mcarb_test.queueSize();
122.16 -
122.17 +
122.18 c = const_mcarb_test.arborescenceCost();
122.19 b = const_mcarb_test.arborescence(e);
122.20 e = const_mcarb_test.pred(n);
122.21 @@ -120,12 +120,12 @@
122.22 const_mcarb_test.predMap();
122.23 b = const_mcarb_test.reached(n);
122.24 b = const_mcarb_test.processed(n);
122.25 -
122.26 +
122.27 i = const_mcarb_test.dualNum();
122.28 c = const_mcarb_test.dualValue();
122.29 i = const_mcarb_test.dualSize(i);
122.30 c = const_mcarb_test.dualValue(i);
122.31 -
122.32 +
122.33 ignore_unused_variable_warning(am);
122.34 ignore_unused_variable_warning(pm);
122.35 }
123.1 --- a/test/min_cost_flow_test.cc Tue Dec 20 17:44:38 2011 +0100
123.2 +++ b/test/min_cost_flow_test.cc Tue Dec 20 18:15:14 2011 +0100
123.3 @@ -2,7 +2,7 @@
123.4 *
123.5 * This file is a part of LEMON, a generic C++ optimization library.
123.6 *
123.7 - * Copyright (C) 2003-2009
123.8 + * Copyright (C) 2003-2010
123.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
123.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
123.11 *
123.12 @@ -24,14 +24,19 @@
123.13 #include <lemon/lgf_reader.h>
123.14
123.15 #include <lemon/network_simplex.h>
123.16 +#include <lemon/capacity_scaling.h>
123.17 +#include <lemon/cost_scaling.h>
123.18 +#include <lemon/cycle_canceling.h>
123.19
123.20 #include <lemon/concepts/digraph.h>
123.21 +#include <lemon/concepts/heap.h>
123.22 #include <lemon/concept_check.h>
123.23
123.24 #include "test_tools.h"
123.25
123.26 using namespace lemon;
123.27
123.28 +// Test networks
123.29 char test_lgf[] =
123.30 "@nodes\n"
123.31 "label sup1 sup2 sup3 sup4 sup5 sup6\n"
123.32 @@ -47,7 +52,7 @@
123.33 " 10 -2 0 0 0 -7 -2\n"
123.34 " 11 0 0 0 0 -10 0\n"
123.35 " 12 -20 -27 0 -30 -30 -20\n"
123.36 - "\n"
123.37 + "\n"
123.38 "@arcs\n"
123.39 " cost cap low1 low2 low3\n"
123.40 " 1 2 70 11 0 8 8\n"
123.41 @@ -76,6 +81,58 @@
123.42 "source 1\n"
123.43 "target 12\n";
123.44
123.45 +char test_neg1_lgf[] =
123.46 + "@nodes\n"
123.47 + "label sup\n"
123.48 + " 1 100\n"
123.49 + " 2 0\n"
123.50 + " 3 0\n"
123.51 + " 4 -100\n"
123.52 + " 5 0\n"
123.53 + " 6 0\n"
123.54 + " 7 0\n"
123.55 + "@arcs\n"
123.56 + " cost low1 low2\n"
123.57 + "1 2 100 0 0\n"
123.58 + "1 3 30 0 0\n"
123.59 + "2 4 20 0 0\n"
123.60 + "3 4 80 0 0\n"
123.61 + "3 2 50 0 0\n"
123.62 + "5 3 10 0 0\n"
123.63 + "5 6 80 0 1000\n"
123.64 + "6 7 30 0 -1000\n"
123.65 + "7 5 -120 0 0\n";
123.66 +
123.67 +char test_neg2_lgf[] =
123.68 + "@nodes\n"
123.69 + "label sup\n"
123.70 + " 1 100\n"
123.71 + " 2 -300\n"
123.72 + "@arcs\n"
123.73 + " cost\n"
123.74 + "1 2 -1\n";
123.75 +
123.76 +
123.77 +// Test data
123.78 +typedef ListDigraph Digraph;
123.79 +DIGRAPH_TYPEDEFS(ListDigraph);
123.80 +
123.81 +Digraph gr;
123.82 +Digraph::ArcMap<int> c(gr), l1(gr), l2(gr), l3(gr), u(gr);
123.83 +Digraph::NodeMap<int> s1(gr), s2(gr), s3(gr), s4(gr), s5(gr), s6(gr);
123.84 +ConstMap<Arc, int> cc(1), cu(std::numeric_limits<int>::max());
123.85 +Node v, w;
123.86 +
123.87 +Digraph neg1_gr;
123.88 +Digraph::ArcMap<int> neg1_c(neg1_gr), neg1_l1(neg1_gr), neg1_l2(neg1_gr);
123.89 +ConstMap<Arc, int> neg1_u1(std::numeric_limits<int>::max()), neg1_u2(5000);
123.90 +Digraph::NodeMap<int> neg1_s(neg1_gr);
123.91 +
123.92 +Digraph neg2_gr;
123.93 +Digraph::ArcMap<int> neg2_c(neg2_gr);
123.94 +ConstMap<Arc, int> neg2_l(0), neg2_u(1000);
123.95 +Digraph::NodeMap<int> neg2_s(neg2_gr);
123.96 +
123.97
123.98 enum SupplyType {
123.99 EQ,
123.100 @@ -83,6 +140,7 @@
123.101 LEQ
123.102 };
123.103
123.104 +
123.105 // Check the interface of an MCF algorithm
123.106 template <typename GR, typename Value, typename Cost>
123.107 class McfClassConcept
123.108 @@ -93,13 +151,13 @@
123.109 struct Constraints {
123.110 void constraints() {
123.111 checkConcept<concepts::Digraph, GR>();
123.112 -
123.113 +
123.114 const Constraints& me = *this;
123.115
123.116 MCF mcf(me.g);
123.117 const MCF& const_mcf = mcf;
123.118
123.119 - b = mcf.reset()
123.120 + b = mcf.reset().resetParams()
123.121 .lowerMap(me.lower)
123.122 .upperMap(me.upper)
123.123 .costMap(me.cost)
123.124 @@ -122,7 +180,7 @@
123.125 typedef concepts::ReadMap<Arc, Cost> CAM;
123.126 typedef concepts::WriteMap<Arc, Value> FlowMap;
123.127 typedef concepts::WriteMap<Node, Cost> PotMap;
123.128 -
123.129 +
123.130 GR g;
123.131 VAM lower;
123.132 VAM upper;
123.133 @@ -176,7 +234,7 @@
123.134 template < typename GR, typename LM, typename UM,
123.135 typename CM, typename SM, typename FM, typename PM >
123.136 bool checkPotential( const GR& gr, const LM& lower, const UM& upper,
123.137 - const CM& cost, const SM& supply, const FM& flow,
123.138 + const CM& cost, const SM& supply, const FM& flow,
123.139 const PM& pi, SupplyType type )
123.140 {
123.141 TEMPLATE_DIGRAPH_TYPEDEFS(GR);
123.142 @@ -189,7 +247,7 @@
123.143 (red_cost > 0 && flow[e] == lower[e]) ||
123.144 (red_cost < 0 && flow[e] == upper[e]);
123.145 }
123.146 -
123.147 +
123.148 for (NodeIt n(gr); opt && n != INVALID; ++n) {
123.149 typename SM::Value sum = 0;
123.150 for (OutArcIt e(gr, n); e != INVALID; ++e)
123.151 @@ -202,7 +260,7 @@
123.152 opt = (pi[n] >= 0) && (sum == supply[n] || pi[n] == 0);
123.153 }
123.154 }
123.155 -
123.156 +
123.157 return opt;
123.158 }
123.159
123.160 @@ -227,7 +285,7 @@
123.161 red_supply[gr.target(a)] += lower[a];
123.162 }
123.163 }
123.164 -
123.165 +
123.166 for (NodeIt n(gr); n != INVALID; ++n) {
123.167 dual_cost -= red_supply[n] * pi[n];
123.168 }
123.169 @@ -236,7 +294,7 @@
123.170 cost[a] + pi[gr.source(a)] - pi[gr.target(a)];
123.171 dual_cost -= (upper[a] - lower[a]) * std::max(-red_cost, 0);
123.172 }
123.173 -
123.174 +
123.175 return dual_cost == total;
123.176 }
123.177
123.178 @@ -268,30 +326,99 @@
123.179 }
123.180 }
123.181
123.182 +template < typename MCF, typename Param >
123.183 +void runMcfGeqTests( Param param,
123.184 + const std::string &test_str = "",
123.185 + bool full_neg_cost_support = false )
123.186 +{
123.187 + MCF mcf1(gr), mcf2(neg1_gr), mcf3(neg2_gr);
123.188 +
123.189 + // Basic tests
123.190 + mcf1.upperMap(u).costMap(c).supplyMap(s1);
123.191 + checkMcf(mcf1, mcf1.run(param), gr, l1, u, c, s1,
123.192 + mcf1.OPTIMAL, true, 5240, test_str + "-1");
123.193 + mcf1.stSupply(v, w, 27);
123.194 + checkMcf(mcf1, mcf1.run(param), gr, l1, u, c, s2,
123.195 + mcf1.OPTIMAL, true, 7620, test_str + "-2");
123.196 + mcf1.lowerMap(l2).supplyMap(s1);
123.197 + checkMcf(mcf1, mcf1.run(param), gr, l2, u, c, s1,
123.198 + mcf1.OPTIMAL, true, 5970, test_str + "-3");
123.199 + mcf1.stSupply(v, w, 27);
123.200 + checkMcf(mcf1, mcf1.run(param), gr, l2, u, c, s2,
123.201 + mcf1.OPTIMAL, true, 8010, test_str + "-4");
123.202 + mcf1.resetParams().supplyMap(s1);
123.203 + checkMcf(mcf1, mcf1.run(param), gr, l1, cu, cc, s1,
123.204 + mcf1.OPTIMAL, true, 74, test_str + "-5");
123.205 + mcf1.lowerMap(l2).stSupply(v, w, 27);
123.206 + checkMcf(mcf1, mcf1.run(param), gr, l2, cu, cc, s2,
123.207 + mcf1.OPTIMAL, true, 94, test_str + "-6");
123.208 + mcf1.reset();
123.209 + checkMcf(mcf1, mcf1.run(param), gr, l1, cu, cc, s3,
123.210 + mcf1.OPTIMAL, true, 0, test_str + "-7");
123.211 + mcf1.lowerMap(l2).upperMap(u);
123.212 + checkMcf(mcf1, mcf1.run(param), gr, l2, u, cc, s3,
123.213 + mcf1.INFEASIBLE, false, 0, test_str + "-8");
123.214 + mcf1.lowerMap(l3).upperMap(u).costMap(c).supplyMap(s4);
123.215 + checkMcf(mcf1, mcf1.run(param), gr, l3, u, c, s4,
123.216 + mcf1.OPTIMAL, true, 6360, test_str + "-9");
123.217 +
123.218 + // Tests for the GEQ form
123.219 + mcf1.resetParams().upperMap(u).costMap(c).supplyMap(s5);
123.220 + checkMcf(mcf1, mcf1.run(param), gr, l1, u, c, s5,
123.221 + mcf1.OPTIMAL, true, 3530, test_str + "-10", GEQ);
123.222 + mcf1.lowerMap(l2);
123.223 + checkMcf(mcf1, mcf1.run(param), gr, l2, u, c, s5,
123.224 + mcf1.OPTIMAL, true, 4540, test_str + "-11", GEQ);
123.225 + mcf1.supplyMap(s6);
123.226 + checkMcf(mcf1, mcf1.run(param), gr, l2, u, c, s6,
123.227 + mcf1.INFEASIBLE, false, 0, test_str + "-12", GEQ);
123.228 +
123.229 + // Tests with negative costs
123.230 + mcf2.lowerMap(neg1_l1).costMap(neg1_c).supplyMap(neg1_s);
123.231 + checkMcf(mcf2, mcf2.run(param), neg1_gr, neg1_l1, neg1_u1, neg1_c, neg1_s,
123.232 + mcf2.UNBOUNDED, false, 0, test_str + "-13");
123.233 + mcf2.upperMap(neg1_u2);
123.234 + checkMcf(mcf2, mcf2.run(param), neg1_gr, neg1_l1, neg1_u2, neg1_c, neg1_s,
123.235 + mcf2.OPTIMAL, true, -40000, test_str + "-14");
123.236 + mcf2.resetParams().lowerMap(neg1_l2).costMap(neg1_c).supplyMap(neg1_s);
123.237 + checkMcf(mcf2, mcf2.run(param), neg1_gr, neg1_l2, neg1_u1, neg1_c, neg1_s,
123.238 + mcf2.UNBOUNDED, false, 0, test_str + "-15");
123.239 +
123.240 + mcf3.costMap(neg2_c).supplyMap(neg2_s);
123.241 + if (full_neg_cost_support) {
123.242 + checkMcf(mcf3, mcf3.run(param), neg2_gr, neg2_l, neg2_u, neg2_c, neg2_s,
123.243 + mcf3.OPTIMAL, true, -300, test_str + "-16", GEQ);
123.244 + } else {
123.245 + checkMcf(mcf3, mcf3.run(param), neg2_gr, neg2_l, neg2_u, neg2_c, neg2_s,
123.246 + mcf3.UNBOUNDED, false, 0, test_str + "-17", GEQ);
123.247 + }
123.248 + mcf3.upperMap(neg2_u);
123.249 + checkMcf(mcf3, mcf3.run(param), neg2_gr, neg2_l, neg2_u, neg2_c, neg2_s,
123.250 + mcf3.OPTIMAL, true, -300, test_str + "-18", GEQ);
123.251 +}
123.252 +
123.253 +template < typename MCF, typename Param >
123.254 +void runMcfLeqTests( Param param,
123.255 + const std::string &test_str = "" )
123.256 +{
123.257 + // Tests for the LEQ form
123.258 + MCF mcf1(gr);
123.259 + mcf1.supplyType(mcf1.LEQ);
123.260 + mcf1.upperMap(u).costMap(c).supplyMap(s6);
123.261 + checkMcf(mcf1, mcf1.run(param), gr, l1, u, c, s6,
123.262 + mcf1.OPTIMAL, true, 5080, test_str + "-19", LEQ);
123.263 + mcf1.lowerMap(l2);
123.264 + checkMcf(mcf1, mcf1.run(param), gr, l2, u, c, s6,
123.265 + mcf1.OPTIMAL, true, 5930, test_str + "-20", LEQ);
123.266 + mcf1.supplyMap(s5);
123.267 + checkMcf(mcf1, mcf1.run(param), gr, l2, u, c, s5,
123.268 + mcf1.INFEASIBLE, false, 0, test_str + "-21", LEQ);
123.269 +}
123.270 +
123.271 +
123.272 int main()
123.273 {
123.274 - // Check the interfaces
123.275 - {
123.276 - typedef concepts::Digraph GR;
123.277 - checkConcept< McfClassConcept<GR, int, int>,
123.278 - NetworkSimplex<GR> >();
123.279 - checkConcept< McfClassConcept<GR, double, double>,
123.280 - NetworkSimplex<GR, double> >();
123.281 - checkConcept< McfClassConcept<GR, int, double>,
123.282 - NetworkSimplex<GR, int, double> >();
123.283 - }
123.284 -
123.285 - // Run various MCF tests
123.286 - typedef ListDigraph Digraph;
123.287 - DIGRAPH_TYPEDEFS(ListDigraph);
123.288 -
123.289 - // Read the test digraph
123.290 - Digraph gr;
123.291 - Digraph::ArcMap<int> c(gr), l1(gr), l2(gr), l3(gr), u(gr);
123.292 - Digraph::NodeMap<int> s1(gr), s2(gr), s3(gr), s4(gr), s5(gr), s6(gr);
123.293 - ConstMap<Arc, int> cc(1), cu(std::numeric_limits<int>::max());
123.294 - Node v, w;
123.295 -
123.296 + // Read the test networks
123.297 std::istringstream input(test_lgf);
123.298 DigraphReader<Digraph>(gr, input)
123.299 .arcMap("cost", c)
123.300 @@ -308,142 +435,107 @@
123.301 .node("source", v)
123.302 .node("target", w)
123.303 .run();
123.304 -
123.305 - // Build test digraphs with negative costs
123.306 - Digraph neg_gr;
123.307 - Node n1 = neg_gr.addNode();
123.308 - Node n2 = neg_gr.addNode();
123.309 - Node n3 = neg_gr.addNode();
123.310 - Node n4 = neg_gr.addNode();
123.311 - Node n5 = neg_gr.addNode();
123.312 - Node n6 = neg_gr.addNode();
123.313 - Node n7 = neg_gr.addNode();
123.314 -
123.315 - Arc a1 = neg_gr.addArc(n1, n2);
123.316 - Arc a2 = neg_gr.addArc(n1, n3);
123.317 - Arc a3 = neg_gr.addArc(n2, n4);
123.318 - Arc a4 = neg_gr.addArc(n3, n4);
123.319 - Arc a5 = neg_gr.addArc(n3, n2);
123.320 - Arc a6 = neg_gr.addArc(n5, n3);
123.321 - Arc a7 = neg_gr.addArc(n5, n6);
123.322 - Arc a8 = neg_gr.addArc(n6, n7);
123.323 - Arc a9 = neg_gr.addArc(n7, n5);
123.324 -
123.325 - Digraph::ArcMap<int> neg_c(neg_gr), neg_l1(neg_gr, 0), neg_l2(neg_gr, 0);
123.326 - ConstMap<Arc, int> neg_u1(std::numeric_limits<int>::max()), neg_u2(5000);
123.327 - Digraph::NodeMap<int> neg_s(neg_gr, 0);
123.328 -
123.329 - neg_l2[a7] = 1000;
123.330 - neg_l2[a8] = -1000;
123.331 -
123.332 - neg_s[n1] = 100;
123.333 - neg_s[n4] = -100;
123.334 -
123.335 - neg_c[a1] = 100;
123.336 - neg_c[a2] = 30;
123.337 - neg_c[a3] = 20;
123.338 - neg_c[a4] = 80;
123.339 - neg_c[a5] = 50;
123.340 - neg_c[a6] = 10;
123.341 - neg_c[a7] = 80;
123.342 - neg_c[a8] = 30;
123.343 - neg_c[a9] = -120;
123.344
123.345 - Digraph negs_gr;
123.346 - Digraph::NodeMap<int> negs_s(negs_gr);
123.347 - Digraph::ArcMap<int> negs_c(negs_gr);
123.348 - ConstMap<Arc, int> negs_l(0), negs_u(1000);
123.349 - n1 = negs_gr.addNode();
123.350 - n2 = negs_gr.addNode();
123.351 - negs_s[n1] = 100;
123.352 - negs_s[n2] = -300;
123.353 - negs_c[negs_gr.addArc(n1, n2)] = -1;
123.354 + std::istringstream neg_inp1(test_neg1_lgf);
123.355 + DigraphReader<Digraph>(neg1_gr, neg_inp1)
123.356 + .arcMap("cost", neg1_c)
123.357 + .arcMap("low1", neg1_l1)
123.358 + .arcMap("low2", neg1_l2)
123.359 + .nodeMap("sup", neg1_s)
123.360 + .run();
123.361
123.362 + std::istringstream neg_inp2(test_neg2_lgf);
123.363 + DigraphReader<Digraph>(neg2_gr, neg_inp2)
123.364 + .arcMap("cost", neg2_c)
123.365 + .nodeMap("sup", neg2_s)
123.366 + .run();
123.367
123.368 - // A. Test NetworkSimplex with the default pivot rule
123.369 + // Check the interface of NetworkSimplex
123.370 {
123.371 - NetworkSimplex<Digraph> mcf(gr);
123.372 -
123.373 - // Check the equality form
123.374 - mcf.upperMap(u).costMap(c);
123.375 - checkMcf(mcf, mcf.supplyMap(s1).run(),
123.376 - gr, l1, u, c, s1, mcf.OPTIMAL, true, 5240, "#A1");
123.377 - checkMcf(mcf, mcf.stSupply(v, w, 27).run(),
123.378 - gr, l1, u, c, s2, mcf.OPTIMAL, true, 7620, "#A2");
123.379 - mcf.lowerMap(l2);
123.380 - checkMcf(mcf, mcf.supplyMap(s1).run(),
123.381 - gr, l2, u, c, s1, mcf.OPTIMAL, true, 5970, "#A3");
123.382 - checkMcf(mcf, mcf.stSupply(v, w, 27).run(),
123.383 - gr, l2, u, c, s2, mcf.OPTIMAL, true, 8010, "#A4");
123.384 - mcf.reset();
123.385 - checkMcf(mcf, mcf.supplyMap(s1).run(),
123.386 - gr, l1, cu, cc, s1, mcf.OPTIMAL, true, 74, "#A5");
123.387 - checkMcf(mcf, mcf.lowerMap(l2).stSupply(v, w, 27).run(),
123.388 - gr, l2, cu, cc, s2, mcf.OPTIMAL, true, 94, "#A6");
123.389 - mcf.reset();
123.390 - checkMcf(mcf, mcf.run(),
123.391 - gr, l1, cu, cc, s3, mcf.OPTIMAL, true, 0, "#A7");
123.392 - checkMcf(mcf, mcf.lowerMap(l2).upperMap(u).run(),
123.393 - gr, l2, u, cc, s3, mcf.INFEASIBLE, false, 0, "#A8");
123.394 - mcf.reset().lowerMap(l3).upperMap(u).costMap(c).supplyMap(s4);
123.395 - checkMcf(mcf, mcf.run(),
123.396 - gr, l3, u, c, s4, mcf.OPTIMAL, true, 6360, "#A9");
123.397 -
123.398 - // Check the GEQ form
123.399 - mcf.reset().upperMap(u).costMap(c).supplyMap(s5);
123.400 - checkMcf(mcf, mcf.run(),
123.401 - gr, l1, u, c, s5, mcf.OPTIMAL, true, 3530, "#A10", GEQ);
123.402 - mcf.supplyType(mcf.GEQ);
123.403 - checkMcf(mcf, mcf.lowerMap(l2).run(),
123.404 - gr, l2, u, c, s5, mcf.OPTIMAL, true, 4540, "#A11", GEQ);
123.405 - mcf.supplyMap(s6);
123.406 - checkMcf(mcf, mcf.run(),
123.407 - gr, l2, u, c, s6, mcf.INFEASIBLE, false, 0, "#A12", GEQ);
123.408 -
123.409 - // Check the LEQ form
123.410 - mcf.reset().supplyType(mcf.LEQ);
123.411 - mcf.upperMap(u).costMap(c).supplyMap(s6);
123.412 - checkMcf(mcf, mcf.run(),
123.413 - gr, l1, u, c, s6, mcf.OPTIMAL, true, 5080, "#A13", LEQ);
123.414 - checkMcf(mcf, mcf.lowerMap(l2).run(),
123.415 - gr, l2, u, c, s6, mcf.OPTIMAL, true, 5930, "#A14", LEQ);
123.416 - mcf.supplyMap(s5);
123.417 - checkMcf(mcf, mcf.run(),
123.418 - gr, l2, u, c, s5, mcf.INFEASIBLE, false, 0, "#A15", LEQ);
123.419 -
123.420 - // Check negative costs
123.421 - NetworkSimplex<Digraph> neg_mcf(neg_gr);
123.422 - neg_mcf.lowerMap(neg_l1).costMap(neg_c).supplyMap(neg_s);
123.423 - checkMcf(neg_mcf, neg_mcf.run(), neg_gr, neg_l1, neg_u1,
123.424 - neg_c, neg_s, neg_mcf.UNBOUNDED, false, 0, "#A16");
123.425 - neg_mcf.upperMap(neg_u2);
123.426 - checkMcf(neg_mcf, neg_mcf.run(), neg_gr, neg_l1, neg_u2,
123.427 - neg_c, neg_s, neg_mcf.OPTIMAL, true, -40000, "#A17");
123.428 - neg_mcf.reset().lowerMap(neg_l2).costMap(neg_c).supplyMap(neg_s);
123.429 - checkMcf(neg_mcf, neg_mcf.run(), neg_gr, neg_l2, neg_u1,
123.430 - neg_c, neg_s, neg_mcf.UNBOUNDED, false, 0, "#A18");
123.431 -
123.432 - NetworkSimplex<Digraph> negs_mcf(negs_gr);
123.433 - negs_mcf.costMap(negs_c).supplyMap(negs_s);
123.434 - checkMcf(negs_mcf, negs_mcf.run(), negs_gr, negs_l, negs_u,
123.435 - negs_c, negs_s, negs_mcf.OPTIMAL, true, -300, "#A19", GEQ);
123.436 + typedef concepts::Digraph GR;
123.437 + checkConcept< McfClassConcept<GR, int, int>,
123.438 + NetworkSimplex<GR> >();
123.439 + checkConcept< McfClassConcept<GR, double, double>,
123.440 + NetworkSimplex<GR, double> >();
123.441 + checkConcept< McfClassConcept<GR, int, double>,
123.442 + NetworkSimplex<GR, int, double> >();
123.443 }
123.444
123.445 - // B. Test NetworkSimplex with each pivot rule
123.446 + // Check the interface of CapacityScaling
123.447 {
123.448 - NetworkSimplex<Digraph> mcf(gr);
123.449 - mcf.supplyMap(s1).costMap(c).upperMap(u).lowerMap(l2);
123.450 + typedef concepts::Digraph GR;
123.451 + checkConcept< McfClassConcept<GR, int, int>,
123.452 + CapacityScaling<GR> >();
123.453 + checkConcept< McfClassConcept<GR, double, double>,
123.454 + CapacityScaling<GR, double> >();
123.455 + checkConcept< McfClassConcept<GR, int, double>,
123.456 + CapacityScaling<GR, int, double> >();
123.457 + typedef CapacityScaling<GR>::
123.458 + SetHeap<concepts::Heap<int, RangeMap<int> > >::Create CAS;
123.459 + checkConcept< McfClassConcept<GR, int, int>, CAS >();
123.460 + }
123.461
123.462 - checkMcf(mcf, mcf.run(NetworkSimplex<Digraph>::FIRST_ELIGIBLE),
123.463 - gr, l2, u, c, s1, mcf.OPTIMAL, true, 5970, "#B1");
123.464 - checkMcf(mcf, mcf.run(NetworkSimplex<Digraph>::BEST_ELIGIBLE),
123.465 - gr, l2, u, c, s1, mcf.OPTIMAL, true, 5970, "#B2");
123.466 - checkMcf(mcf, mcf.run(NetworkSimplex<Digraph>::BLOCK_SEARCH),
123.467 - gr, l2, u, c, s1, mcf.OPTIMAL, true, 5970, "#B3");
123.468 - checkMcf(mcf, mcf.run(NetworkSimplex<Digraph>::CANDIDATE_LIST),
123.469 - gr, l2, u, c, s1, mcf.OPTIMAL, true, 5970, "#B4");
123.470 - checkMcf(mcf, mcf.run(NetworkSimplex<Digraph>::ALTERING_LIST),
123.471 - gr, l2, u, c, s1, mcf.OPTIMAL, true, 5970, "#B5");
123.472 + // Check the interface of CostScaling
123.473 + {
123.474 + typedef concepts::Digraph GR;
123.475 + checkConcept< McfClassConcept<GR, int, int>,
123.476 + CostScaling<GR> >();
123.477 + checkConcept< McfClassConcept<GR, double, double>,
123.478 + CostScaling<GR, double> >();
123.479 + checkConcept< McfClassConcept<GR, int, double>,
123.480 + CostScaling<GR, int, double> >();
123.481 + typedef CostScaling<GR>::
123.482 + SetLargeCost<double>::Create COS;
123.483 + checkConcept< McfClassConcept<GR, int, int>, COS >();
123.484 + }
123.485 +
123.486 + // Check the interface of CycleCanceling
123.487 + {
123.488 + typedef concepts::Digraph GR;
123.489 + checkConcept< McfClassConcept<GR, int, int>,
123.490 + CycleCanceling<GR> >();
123.491 + checkConcept< McfClassConcept<GR, double, double>,
123.492 + CycleCanceling<GR, double> >();
123.493 + checkConcept< McfClassConcept<GR, int, double>,
123.494 + CycleCanceling<GR, int, double> >();
123.495 + }
123.496 +
123.497 + // Test NetworkSimplex
123.498 + {
123.499 + typedef NetworkSimplex<Digraph> MCF;
123.500 + runMcfGeqTests<MCF>(MCF::FIRST_ELIGIBLE, "NS-FE", true);
123.501 + runMcfLeqTests<MCF>(MCF::FIRST_ELIGIBLE, "NS-FE");
123.502 + runMcfGeqTests<MCF>(MCF::BEST_ELIGIBLE, "NS-BE", true);
123.503 + runMcfLeqTests<MCF>(MCF::BEST_ELIGIBLE, "NS-BE");
123.504 + runMcfGeqTests<MCF>(MCF::BLOCK_SEARCH, "NS-BS", true);
123.505 + runMcfLeqTests<MCF>(MCF::BLOCK_SEARCH, "NS-BS");
123.506 + runMcfGeqTests<MCF>(MCF::CANDIDATE_LIST, "NS-CL", true);
123.507 + runMcfLeqTests<MCF>(MCF::CANDIDATE_LIST, "NS-CL");
123.508 + runMcfGeqTests<MCF>(MCF::ALTERING_LIST, "NS-AL", true);
123.509 + runMcfLeqTests<MCF>(MCF::ALTERING_LIST, "NS-AL");
123.510 + }
123.511 +
123.512 + // Test CapacityScaling
123.513 + {
123.514 + typedef CapacityScaling<Digraph> MCF;
123.515 + runMcfGeqTests<MCF>(0, "SSP");
123.516 + runMcfGeqTests<MCF>(2, "CAS");
123.517 + }
123.518 +
123.519 + // Test CostScaling
123.520 + {
123.521 + typedef CostScaling<Digraph> MCF;
123.522 + runMcfGeqTests<MCF>(MCF::PUSH, "COS-PR");
123.523 + runMcfGeqTests<MCF>(MCF::AUGMENT, "COS-AR");
123.524 + runMcfGeqTests<MCF>(MCF::PARTIAL_AUGMENT, "COS-PAR");
123.525 + }
123.526 +
123.527 + // Test CycleCanceling
123.528 + {
123.529 + typedef CycleCanceling<Digraph> MCF;
123.530 + runMcfGeqTests<MCF>(MCF::SIMPLE_CYCLE_CANCELING, "SCC");
123.531 + runMcfGeqTests<MCF>(MCF::MINIMUM_MEAN_CYCLE_CANCELING, "MMCC");
123.532 + runMcfGeqTests<MCF>(MCF::CANCEL_AND_TIGHTEN, "CAT");
123.533 }
123.534
123.535 return 0;
124.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
124.2 +++ b/test/min_mean_cycle_test.cc Tue Dec 20 18:15:14 2011 +0100
124.3 @@ -0,0 +1,216 @@
124.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
124.5 + *
124.6 + * This file is a part of LEMON, a generic C++ optimization library.
124.7 + *
124.8 + * Copyright (C) 2003-2010
124.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
124.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
124.11 + *
124.12 + * Permission to use, modify and distribute this software is granted
124.13 + * provided that this copyright notice appears in all copies. For
124.14 + * precise terms see the accompanying LICENSE file.
124.15 + *
124.16 + * This software is provided "AS IS" with no warranty of any kind,
124.17 + * express or implied, and with no claim as to its suitability for any
124.18 + * purpose.
124.19 + *
124.20 + */
124.21 +
124.22 +#include <iostream>
124.23 +#include <sstream>
124.24 +
124.25 +#include <lemon/smart_graph.h>
124.26 +#include <lemon/lgf_reader.h>
124.27 +#include <lemon/path.h>
124.28 +#include <lemon/concepts/digraph.h>
124.29 +#include <lemon/concept_check.h>
124.30 +
124.31 +#include <lemon/karp_mmc.h>
124.32 +#include <lemon/hartmann_orlin_mmc.h>
124.33 +#include <lemon/howard_mmc.h>
124.34 +
124.35 +#include "test_tools.h"
124.36 +
124.37 +using namespace lemon;
124.38 +
124.39 +char test_lgf[] =
124.40 + "@nodes\n"
124.41 + "label\n"
124.42 + "1\n"
124.43 + "2\n"
124.44 + "3\n"
124.45 + "4\n"
124.46 + "5\n"
124.47 + "6\n"
124.48 + "7\n"
124.49 + "@arcs\n"
124.50 + " len1 len2 len3 len4 c1 c2 c3 c4\n"
124.51 + "1 2 1 1 1 1 0 0 0 0\n"
124.52 + "2 4 5 5 5 5 1 0 0 0\n"
124.53 + "2 3 8 8 8 8 0 0 0 0\n"
124.54 + "3 2 -2 0 0 0 1 0 0 0\n"
124.55 + "3 4 4 4 4 4 0 0 0 0\n"
124.56 + "3 7 -4 -4 -4 -4 0 0 0 0\n"
124.57 + "4 1 2 2 2 2 0 0 0 0\n"
124.58 + "4 3 3 3 3 3 1 0 0 0\n"
124.59 + "4 4 3 3 0 0 0 0 1 0\n"
124.60 + "5 2 4 4 4 4 0 0 0 0\n"
124.61 + "5 6 3 3 3 3 0 1 0 0\n"
124.62 + "6 5 2 2 2 2 0 1 0 0\n"
124.63 + "6 4 -1 -1 -1 -1 0 0 0 0\n"
124.64 + "6 7 1 1 1 1 0 0 0 0\n"
124.65 + "7 7 4 4 4 -1 0 0 0 1\n";
124.66 +
124.67 +
124.68 +// Check the interface of an MMC algorithm
124.69 +template <typename GR, typename Cost>
124.70 +struct MmcClassConcept
124.71 +{
124.72 + template <typename MMC>
124.73 + struct Constraints {
124.74 + void constraints() {
124.75 + const Constraints& me = *this;
124.76 +
124.77 + typedef typename MMC
124.78 + ::template SetPath<ListPath<GR> >
124.79 + ::template SetLargeCost<Cost>
124.80 + ::Create MmcAlg;
124.81 + MmcAlg mmc(me.g, me.cost);
124.82 + const MmcAlg& const_mmc = mmc;
124.83 +
124.84 + typename MmcAlg::Tolerance tol = const_mmc.tolerance();
124.85 + mmc.tolerance(tol);
124.86 +
124.87 + b = mmc.cycle(p).run();
124.88 + b = mmc.findCycleMean();
124.89 + b = mmc.findCycle();
124.90 +
124.91 + v = const_mmc.cycleCost();
124.92 + i = const_mmc.cycleSize();
124.93 + d = const_mmc.cycleMean();
124.94 + p = const_mmc.cycle();
124.95 + }
124.96 +
124.97 + typedef concepts::ReadMap<typename GR::Arc, Cost> CM;
124.98 +
124.99 + GR g;
124.100 + CM cost;
124.101 + ListPath<GR> p;
124.102 + Cost v;
124.103 + int i;
124.104 + double d;
124.105 + bool b;
124.106 + };
124.107 +};
124.108 +
124.109 +// Perform a test with the given parameters
124.110 +template <typename MMC>
124.111 +void checkMmcAlg(const SmartDigraph& gr,
124.112 + const SmartDigraph::ArcMap<int>& lm,
124.113 + const SmartDigraph::ArcMap<int>& cm,
124.114 + int cost, int size) {
124.115 + MMC alg(gr, lm);
124.116 + alg.findCycleMean();
124.117 + check(alg.cycleMean() == static_cast<double>(cost) / size,
124.118 + "Wrong cycle mean");
124.119 + alg.findCycle();
124.120 + check(alg.cycleCost() == cost && alg.cycleSize() == size,
124.121 + "Wrong path");
124.122 + SmartDigraph::ArcMap<int> cycle(gr, 0);
124.123 + for (typename MMC::Path::ArcIt a(alg.cycle()); a != INVALID; ++a) {
124.124 + ++cycle[a];
124.125 + }
124.126 + for (SmartDigraph::ArcIt a(gr); a != INVALID; ++a) {
124.127 + check(cm[a] == cycle[a], "Wrong path");
124.128 + }
124.129 +}
124.130 +
124.131 +// Class for comparing types
124.132 +template <typename T1, typename T2>
124.133 +struct IsSameType {
124.134 + static const int result = 0;
124.135 +};
124.136 +
124.137 +template <typename T>
124.138 +struct IsSameType<T,T> {
124.139 + static const int result = 1;
124.140 +};
124.141 +
124.142 +
124.143 +int main() {
124.144 + #ifdef LEMON_HAVE_LONG_LONG
124.145 + typedef long long long_int;
124.146 + #else
124.147 + typedef long long_int;
124.148 + #endif
124.149 +
124.150 + // Check the interface
124.151 + {
124.152 + typedef concepts::Digraph GR;
124.153 +
124.154 + // KarpMmc
124.155 + checkConcept< MmcClassConcept<GR, int>,
124.156 + KarpMmc<GR, concepts::ReadMap<GR::Arc, int> > >();
124.157 + checkConcept< MmcClassConcept<GR, float>,
124.158 + KarpMmc<GR, concepts::ReadMap<GR::Arc, float> > >();
124.159 +
124.160 + // HartmannOrlinMmc
124.161 + checkConcept< MmcClassConcept<GR, int>,
124.162 + HartmannOrlinMmc<GR, concepts::ReadMap<GR::Arc, int> > >();
124.163 + checkConcept< MmcClassConcept<GR, float>,
124.164 + HartmannOrlinMmc<GR, concepts::ReadMap<GR::Arc, float> > >();
124.165 +
124.166 + // HowardMmc
124.167 + checkConcept< MmcClassConcept<GR, int>,
124.168 + HowardMmc<GR, concepts::ReadMap<GR::Arc, int> > >();
124.169 + checkConcept< MmcClassConcept<GR, float>,
124.170 + HowardMmc<GR, concepts::ReadMap<GR::Arc, float> > >();
124.171 +
124.172 + check((IsSameType<HowardMmc<GR, concepts::ReadMap<GR::Arc, int> >
124.173 + ::LargeCost, long_int>::result == 1), "Wrong LargeCost type");
124.174 + check((IsSameType<HowardMmc<GR, concepts::ReadMap<GR::Arc, float> >
124.175 + ::LargeCost, double>::result == 1), "Wrong LargeCost type");
124.176 + }
124.177 +
124.178 + // Run various tests
124.179 + {
124.180 + typedef SmartDigraph GR;
124.181 + DIGRAPH_TYPEDEFS(GR);
124.182 +
124.183 + GR gr;
124.184 + IntArcMap l1(gr), l2(gr), l3(gr), l4(gr);
124.185 + IntArcMap c1(gr), c2(gr), c3(gr), c4(gr);
124.186 +
124.187 + std::istringstream input(test_lgf);
124.188 + digraphReader(gr, input).
124.189 + arcMap("len1", l1).
124.190 + arcMap("len2", l2).
124.191 + arcMap("len3", l3).
124.192 + arcMap("len4", l4).
124.193 + arcMap("c1", c1).
124.194 + arcMap("c2", c2).
124.195 + arcMap("c3", c3).
124.196 + arcMap("c4", c4).
124.197 + run();
124.198 +
124.199 + // Karp
124.200 + checkMmcAlg<KarpMmc<GR, IntArcMap> >(gr, l1, c1, 6, 3);
124.201 + checkMmcAlg<KarpMmc<GR, IntArcMap> >(gr, l2, c2, 5, 2);
124.202 + checkMmcAlg<KarpMmc<GR, IntArcMap> >(gr, l3, c3, 0, 1);
124.203 + checkMmcAlg<KarpMmc<GR, IntArcMap> >(gr, l4, c4, -1, 1);
124.204 +
124.205 + // HartmannOrlin
124.206 + checkMmcAlg<HartmannOrlinMmc<GR, IntArcMap> >(gr, l1, c1, 6, 3);
124.207 + checkMmcAlg<HartmannOrlinMmc<GR, IntArcMap> >(gr, l2, c2, 5, 2);
124.208 + checkMmcAlg<HartmannOrlinMmc<GR, IntArcMap> >(gr, l3, c3, 0, 1);
124.209 + checkMmcAlg<HartmannOrlinMmc<GR, IntArcMap> >(gr, l4, c4, -1, 1);
124.210 +
124.211 + // Howard
124.212 + checkMmcAlg<HowardMmc<GR, IntArcMap> >(gr, l1, c1, 6, 3);
124.213 + checkMmcAlg<HowardMmc<GR, IntArcMap> >(gr, l2, c2, 5, 2);
124.214 + checkMmcAlg<HowardMmc<GR, IntArcMap> >(gr, l3, c3, 0, 1);
124.215 + checkMmcAlg<HowardMmc<GR, IntArcMap> >(gr, l4, c4, -1, 1);
124.216 + }
124.217 +
124.218 + return 0;
124.219 +}
125.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
125.2 +++ b/test/planarity_test.cc Tue Dec 20 18:15:14 2011 +0100
125.3 @@ -0,0 +1,262 @@
125.4 +/* -*- mode: C++; indent-tabs-mode: nil; -*-
125.5 + *
125.6 + * This file is a part of LEMON, a generic C++ optimization library.
125.7 + *
125.8 + * Copyright (C) 2003-2009
125.9 + * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
125.10 + * (Egervary Research Group on Combinatorial Optimization, EGRES).
125.11 + *
125.12 + * Permission to use, modify and distribute this software is granted
125.13 + * provided that this copyright notice appears in all copies. For
125.14 + * precise terms see the accompanying LICENSE file.
125.15 + *
125.16 + * This software is provided "AS IS" with no warranty of any kind,
125.17 + * express or implied, and with no claim as to its suitability for any
125.18 + * purpose.
125.19 + *
125.20 + */
125.21 +
125.22 +#include <iostream>
125.23 +
125.24 +#include <lemon/planarity.h>
125.25 +
125.26 +#include <lemon/smart_graph.h>
125.27 +#include <lemon/lgf_reader.h>
125.28 +#include <lemon/connectivity.h>
125.29 +#include <lemon/dim2.h>
125.30 +
125.31 +#include "test_tools.h"
125.32 +
125.33 +using namespace lemon;
125.34 +using namespace lemon::dim2;
125.35 +
125.36 +const int lgfn = 4;
125.37 +const std::string lgf[lgfn] = {
125.38 + "@nodes\n"
125.39 + "label\n"
125.40 + "0\n"
125.41 + "1\n"
125.42 + "2\n"
125.43 + "3\n"
125.44 + "4\n"
125.45 + "@edges\n"
125.46 + " label\n"
125.47 + "0 1 0\n"
125.48 + "0 2 0\n"
125.49 + "0 3 0\n"
125.50 + "0 4 0\n"
125.51 + "1 2 0\n"
125.52 + "1 3 0\n"
125.53 + "1 4 0\n"
125.54 + "2 3 0\n"
125.55 + "2 4 0\n"
125.56 + "3 4 0\n",
125.57 +
125.58 + "@nodes\n"
125.59 + "label\n"
125.60 + "0\n"
125.61 + "1\n"
125.62 + "2\n"
125.63 + "3\n"
125.64 + "4\n"
125.65 + "@edges\n"
125.66 + " label\n"
125.67 + "0 1 0\n"
125.68 + "0 2 0\n"
125.69 + "0 3 0\n"
125.70 + "0 4 0\n"
125.71 + "1 2 0\n"
125.72 + "1 3 0\n"
125.73 + "2 3 0\n"
125.74 + "2 4 0\n"
125.75 + "3 4 0\n",
125.76 +
125.77 + "@nodes\n"
125.78 + "label\n"
125.79 + "0\n"
125.80 + "1\n"
125.81 + "2\n"
125.82 + "3\n"
125.83 + "4\n"
125.84 + "5\n"
125.85 + "@edges\n"
125.86 + " label\n"
125.87 + "0 3 0\n"
125.88 + "0 4 0\n"
125.89 + "0 5 0\n"
125.90 + "1 3 0\n"
125.91 + "1 4 0\n"
125.92 + "1 5 0\n"
125.93 + "2 3 0\n"
125.94 + "2 4 0\n"
125.95 + "2 5 0\n",
125.96 +
125.97 + "@nodes\n"
125.98 + "label\n"
125.99 + "0\n"
125.100 + "1\n"
125.101 + "2\n"
125.102 + "3\n"
125.103 + "4\n"
125.104 + "5\n"
125.105 + "@edges\n"
125.106 + " label\n"
125.107 + "0 3 0\n"
125.108 + "0 4 0\n"
125.109 + "0 5 0\n"
125.110 + "1 3 0\n"
125.111 + "1 4 0\n"
125.112 + "1 5 0\n"
125.113 + "2 3 0\n"
125.114 + "2 5 0\n"
125.115 +};
125.116 +
125.117 +
125.118 +
125.119 +typedef SmartGraph Graph;
125.120 +GRAPH_TYPEDEFS(Graph);
125.121 +
125.122 +typedef PlanarEmbedding<SmartGraph> PE;
125.123 +typedef PlanarDrawing<SmartGraph> PD;
125.124 +typedef PlanarColoring<SmartGraph> PC;
125.125 +
125.126 +void checkEmbedding(const Graph& graph, PE& pe) {
125.127 + int face_num = 0;
125.128 +
125.129 + Graph::ArcMap<int> face(graph, -1);
125.130 +
125.131 + for (ArcIt a(graph); a != INVALID; ++a) {
125.132 + if (face[a] == -1) {
125.133 + Arc b = a;
125.134 + while (face[b] == -1) {
125.135 + face[b] = face_num;
125.136 + b = pe.next(graph.oppositeArc(b));
125.137 + }
125.138 + check(face[b] == face_num, "Wrong face");
125.139 + ++face_num;
125.140 + }
125.141 + }
125.142 + check(face_num + countNodes(graph) - countConnectedComponents(graph) ==
125.143 + countEdges(graph) + 1, "Euler test does not passed");
125.144 +}
125.145 +
125.146 +void checkKuratowski(const Graph& graph, PE& pe) {
125.147 + std::map<int, int> degs;
125.148 + for (NodeIt n(graph); n != INVALID; ++n) {
125.149 + int deg = 0;
125.150 + for (IncEdgeIt e(graph, n); e != INVALID; ++e) {
125.151 + if (pe.kuratowski(e)) {
125.152 + ++deg;
125.153 + }
125.154 + }
125.155 + ++degs[deg];
125.156 + }
125.157 + for (std::map<int, int>::iterator it = degs.begin(); it != degs.end(); ++it) {
125.158 + check(it->first == 0 || it->first == 2 ||
125.159 + (it->first == 3 && it->second == 6) ||
125.160 + (it->first == 4 && it->second == 5),
125.161 + "Wrong degree in Kuratowski graph");
125.162 + }
125.163 +
125.164 + // Not full test
125.165 + check((degs[3] == 0) != (degs[4] == 0), "Wrong Kuratowski graph");
125.166 +}
125.167 +
125.168 +bool intersect(Point<int> e1, Point<int> e2, Point<int> f1, Point<int> f2) {
125.169 + int l, r;
125.170 + if (std::min(e1.x, e2.x) > std::max(f1.x, f2.x)) return false;
125.171 + if (std::max(e1.x, e2.x) < std::min(f1.x, f2.x)) return false;
125.172 + if (std::min(e1.y, e2.y) > std::max(f1.y, f2.y)) return false;
125.173 + if (std::max(e1.y, e2.y) < std::min(f1.y, f2.y)) return false;
125.174 +
125.175 + l = (e2.x - e1.x) * (f1.y - e1.y) - (e2.y - e1.y) * (f1.x - e1.x);
125.176 + r = (e2.x - e1.x) * (f2.y - e1.y) - (e2.y - e1.y) * (f2.x - e1.x);
125.177 + if (!((l >= 0 && r <= 0) || (l <= 0 && r >= 0))) return false;
125.178 + l = (f2.x - f1.x) * (e1.y - f1.y) - (f2.y - f1.y) * (e1.x - f1.x);
125.179 + r = (f2.x - f1.x) * (e2.y - f1.y) - (f2.y - f1.y) * (e2.x - f1.x);
125.180 + if (!((l >= 0 && r <= 0) || (l <= 0 && r >= 0))) return false;
125.181 + return true;
125.182 +}
125.183 +
125.184 +bool collinear(Point<int> p, Point<int> q, Point<int> r) {
125.185 + int v;
125.186 + v = (q.x - p.x) * (r.y - p.y) - (q.y - p.y) * (r.x - p.x);
125.187 + if (v != 0) return false;
125.188 + v = (q.x - p.x) * (r.x - p.x) + (q.y - p.y) * (r.y - p.y);
125.189 + if (v < 0) return false;
125.190 + return true;
125.191 +}
125.192 +
125.193 +void checkDrawing(const Graph& graph, PD& pd) {
125.194 + for (Graph::NodeIt n(graph); n != INVALID; ++n) {
125.195 + Graph::NodeIt m(n);
125.196 + for (++m; m != INVALID; ++m) {
125.197 + check(pd[m] != pd[n], "Two nodes with identical coordinates");
125.198 + }
125.199 + }
125.200 +
125.201 + for (Graph::EdgeIt e(graph); e != INVALID; ++e) {
125.202 + for (Graph::EdgeIt f(e); f != e; ++f) {
125.203 + Point<int> e1 = pd[graph.u(e)];
125.204 + Point<int> e2 = pd[graph.v(e)];
125.205 + Point<int> f1 = pd[graph.u(f)];
125.206 + Point<int> f2 = pd[graph.v(f)];
125.207 +
125.208 + if (graph.u(e) == graph.u(f)) {
125.209 + check(!collinear(e1, e2, f2), "Wrong drawing");
125.210 + } else if (graph.u(e) == graph.v(f)) {
125.211 + check(!collinear(e1, e2, f1), "Wrong drawing");
125.212 + } else if (graph.v(e) == graph.u(f)) {
125.213 + check(!collinear(e2, e1, f2), "Wrong drawing");
125.214 + } else if (graph.v(e) == graph.v(f)) {
125.215 + check(!collinear(e2, e1, f1), "Wrong drawing");
125.216 + } else {
125.217 + check(!intersect(e1, e2, f1, f2), "Wrong drawing");
125.218 + }
125.219 + }
125.220 + }
125.221 +}
125.222 +
125.223 +void checkColoring(const Graph& graph, PC& pc, int num) {
125.224 + for (NodeIt n(graph); n != INVALID; ++n) {
125.225 + check(pc.colorIndex(n) >= 0 && pc.colorIndex(n) < num,
125.226 + "Wrong coloring");
125.227 + }
125.228 + for (EdgeIt e(graph); e != INVALID; ++e) {
125.229 + check(pc.colorIndex(graph.u(e)) != pc.colorIndex(graph.v(e)),
125.230 + "Wrong coloring");
125.231 + }
125.232 +}
125.233 +
125.234 +int main() {
125.235 +
125.236 + for (int i = 0; i < lgfn; ++i) {
125.237 + std::istringstream lgfs(lgf[i]);
125.238 +
125.239 + SmartGraph graph;
125.240 + graphReader(graph, lgfs).run();
125.241 +
125.242 + check(simpleGraph(graph), "Test graphs must be simple");
125.243 +
125.244 + PE pe(graph);
125.245 + bool planar = pe.run();
125.246 + check(checkPlanarity(graph) == planar, "Planarity checking failed");
125.247 +
125.248 + if (planar) {
125.249 + checkEmbedding(graph, pe);
125.250 +
125.251 + PlanarDrawing<Graph> pd(graph);
125.252 + pd.run(pe.embeddingMap());
125.253 + checkDrawing(graph, pd);
125.254 +
125.255 + PlanarColoring<Graph> pc(graph);
125.256 + pc.runFiveColoring(pe.embeddingMap());
125.257 + checkColoring(graph, pc, 5);
125.258 +
125.259 + } else {
125.260 + checkKuratowski(graph, pe);
125.261 + }
125.262 + }
125.263 +
125.264 + return 0;
125.265 +}
126.1 --- a/test/preflow_test.cc Tue Dec 20 17:44:38 2011 +0100
126.2 +++ b/test/preflow_test.cc Tue Dec 20 18:15:14 2011 +0100
126.3 @@ -2,7 +2,7 @@
126.4 *
126.5 * This file is a part of LEMON, a generic C++ optimization library.
126.6 *
126.7 - * Copyright (C) 2003-2009
126.8 + * Copyright (C) 2003-2010
126.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
126.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
126.11 *
126.12 @@ -95,6 +95,11 @@
126.13 PreflowType preflow_test(g, cap, n, n);
126.14 const PreflowType& const_preflow_test = preflow_test;
126.15
126.16 + const PreflowType::Elevator& elev = const_preflow_test.elevator();
126.17 + preflow_test.elevator(const_cast<PreflowType::Elevator&>(elev));
126.18 + PreflowType::Tolerance tol = const_preflow_test.tolerance();
126.19 + preflow_test.tolerance(tol);
126.20 +
126.21 preflow_test
126.22 .capacityMap(cap)
126.23 .flowMap(flow)
126.24 @@ -113,7 +118,7 @@
126.25 const FlowMap& fm = const_preflow_test.flowMap();
126.26 b = const_preflow_test.minCut(n);
126.27 const_preflow_test.minCutMap(cut);
126.28 -
126.29 +
126.30 ignore_unused_variable_warning(fm);
126.31 }
126.32
127.1 --- a/test/suurballe_test.cc Tue Dec 20 17:44:38 2011 +0100
127.2 +++ b/test/suurballe_test.cc Tue Dec 20 18:15:14 2011 +0100
127.3 @@ -2,7 +2,7 @@
127.4 *
127.5 * This file is a part of LEMON, a generic C++ optimization library.
127.6 *
127.7 - * Copyright (C) 2003-2009
127.8 + * Copyright (C) 2003-2010
127.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
127.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
127.11 *
127.12 @@ -23,6 +23,7 @@
127.13 #include <lemon/path.h>
127.14 #include <lemon/suurballe.h>
127.15 #include <lemon/concepts/digraph.h>
127.16 +#include <lemon/concepts/heap.h>
127.17
127.18 #include "test_tools.h"
127.19
127.20 @@ -80,8 +81,14 @@
127.21 typedef Digraph::Node Node;
127.22 typedef Digraph::Arc Arc;
127.23 typedef concepts::ReadMap<Arc, VType> LengthMap;
127.24 -
127.25 - typedef Suurballe<Digraph, LengthMap> SuurballeType;
127.26 +
127.27 + typedef Suurballe<Digraph, LengthMap> ST;
127.28 + typedef Suurballe<Digraph, LengthMap>
127.29 + ::SetFlowMap<ST::FlowMap>
127.30 + ::SetPotentialMap<ST::PotentialMap>
127.31 + ::SetPath<SimplePath<Digraph> >
127.32 + ::SetHeap<concepts::Heap<VType, Digraph::NodeMap<int> > >
127.33 + ::Create SuurballeType;
127.34
127.35 Digraph g;
127.36 Node n;
127.37 @@ -101,10 +108,13 @@
127.38 k = suurb_test.run(n, n);
127.39 k = suurb_test.run(n, n, k);
127.40 suurb_test.init(n);
127.41 + suurb_test.fullInit(n);
127.42 + suurb_test.start(n);
127.43 + suurb_test.start(n, k);
127.44 k = suurb_test.findFlow(n);
127.45 k = suurb_test.findFlow(n, k);
127.46 suurb_test.findPaths();
127.47 -
127.48 +
127.49 int f;
127.50 VType c;
127.51 c = const_suurb_test.totalLength();
127.52 @@ -116,7 +126,7 @@
127.53 const_suurb_test.potentialMap();
127.54 k = const_suurb_test.pathNum();
127.55 Path<Digraph> p = const_suurb_test.path(k);
127.56 -
127.57 +
127.58 ignore_unused_variable_warning(fm);
127.59 ignore_unused_variable_warning(pm);
127.60 }
127.61 @@ -195,9 +205,11 @@
127.62 node("target", t).
127.63 run();
127.64
127.65 - // Find 2 paths
127.66 + // Check run()
127.67 {
127.68 Suurballe<ListDigraph> suurballe(digraph, length);
127.69 +
127.70 + // Find 2 paths
127.71 check(suurballe.run(s, t) == 2, "Wrong number of paths");
127.72 check(checkFlow(digraph, suurballe.flowMap(), s, t, 2),
127.73 "The flow is not feasible");
127.74 @@ -207,11 +219,8 @@
127.75 "Wrong potentials");
127.76 for (int i = 0; i < suurballe.pathNum(); ++i)
127.77 check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
127.78 - }
127.79
127.80 - // Find 3 paths
127.81 - {
127.82 - Suurballe<ListDigraph> suurballe(digraph, length);
127.83 + // Find 3 paths
127.84 check(suurballe.run(s, t, 3) == 3, "Wrong number of paths");
127.85 check(checkFlow(digraph, suurballe.flowMap(), s, t, 3),
127.86 "The flow is not feasible");
127.87 @@ -221,11 +230,8 @@
127.88 "Wrong potentials");
127.89 for (int i = 0; i < suurballe.pathNum(); ++i)
127.90 check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
127.91 - }
127.92
127.93 - // Find 5 paths (only 3 can be found)
127.94 - {
127.95 - Suurballe<ListDigraph> suurballe(digraph, length);
127.96 + // Find 5 paths (only 3 can be found)
127.97 check(suurballe.run(s, t, 5) == 3, "Wrong number of paths");
127.98 check(checkFlow(digraph, suurballe.flowMap(), s, t, 3),
127.99 "The flow is not feasible");
127.100 @@ -237,5 +243,23 @@
127.101 check(checkPath(digraph, suurballe.path(i), s, t), "Wrong path");
127.102 }
127.103
127.104 + // Check fullInit() + start()
127.105 + {
127.106 + Suurballe<ListDigraph> suurballe(digraph, length);
127.107 + suurballe.fullInit(s);
127.108 +
127.109 + // Find 2 paths
127.110 + check(suurballe.start(t) == 2, "Wrong number of paths");
127.111 + check(suurballe.totalLength() == 510, "The flow is not optimal");
127.112 +
127.113 + // Find 3 paths
127.114 + check(suurballe.start(t, 3) == 3, "Wrong number of paths");
127.115 + check(suurballe.totalLength() == 1040, "The flow is not optimal");
127.116 +
127.117 + // Find 5 paths (only 3 can be found)
127.118 + check(suurballe.start(t, 5) == 3, "Wrong number of paths");
127.119 + check(suurballe.totalLength() == 1040, "The flow is not optimal");
127.120 + }
127.121 +
127.122 return 0;
127.123 }
128.1 --- a/test/test_tools.h Tue Dec 20 17:44:38 2011 +0100
128.2 +++ b/test/test_tools.h Tue Dec 20 18:15:14 2011 +0100
128.3 @@ -2,7 +2,7 @@
128.4 *
128.5 * This file is a part of LEMON, a generic C++ optimization library.
128.6 *
128.7 - * Copyright (C) 2003-2009
128.8 + * Copyright (C) 2003-2010
128.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
128.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
128.11 *
128.12 @@ -37,10 +37,14 @@
128.13 ///\code check(0==1,"This is obviously false.");\endcode will
128.14 ///print something like this (and then exits).
128.15 ///\verbatim file_name.cc:123: error: This is obviously false. \endverbatim
128.16 -#define check(rc, msg) \
128.17 - if(!(rc)) { \
128.18 - std::cerr << __FILE__ ":" << __LINE__ << ": error: " << msg << std::endl; \
128.19 - abort(); \
128.20 - } else { } \
128.21 +#define check(rc, msg) \
128.22 + { \
128.23 + if(!(rc)) { \
128.24 + std::cerr << __FILE__ ":" << __LINE__ << ": error: " \
128.25 + << msg << std::endl; \
128.26 + abort(); \
128.27 + } else { } \
128.28 + } \
128.29 +
128.30
128.31 #endif
129.1 --- a/tools/dimacs-solver.cc Tue Dec 20 17:44:38 2011 +0100
129.2 +++ b/tools/dimacs-solver.cc Tue Dec 20 18:15:14 2011 +0100
129.3 @@ -2,7 +2,7 @@
129.4 *
129.5 * This file is a part of LEMON, a generic C++ optimization library.
129.6 *
129.7 - * Copyright (C) 2003-2009
129.8 + * Copyright (C) 2003-2010
129.9 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
129.10 * (Egervary Research Group on Combinatorial Optimization, EGRES).
129.11 *
129.12 @@ -88,10 +88,10 @@
129.13 ti.restart();
129.14 pre.run();
129.15 if(report) std::cerr << "Run Preflow: " << ti << '\n';
129.16 - if(report) std::cerr << "\nMax flow value: " << pre.flowValue() << '\n';
129.17 + if(report) std::cerr << "\nMax flow value: " << pre.flowValue() << '\n';
129.18 }
129.19
129.20 -template<class Value>
129.21 +template<class Value, class LargeValue>
129.22 void solve_min(ArgParser &ap, std::istream &is, std::ostream &,
129.23 Value infty, DimacsDescriptor &desc)
129.24 {
129.25 @@ -127,7 +127,8 @@
129.26 if (report) {
129.27 std::cerr << "Run NetworkSimplex: " << ti << "\n\n";
129.28 std::cerr << "Feasible flow: " << (res ? "found" : "not found") << '\n';
129.29 - if (res) std::cerr << "Min flow cost: " << ns.totalCost() << '\n';
129.30 + if (res) std::cerr << "Min flow cost: "
129.31 + << ns.template totalCost<LargeValue>() << '\n';
129.32 }
129.33 }
129.34
129.35 @@ -147,11 +148,11 @@
129.36 mat.run();
129.37 if(report) std::cerr << "Run MaxMatching: " << ti << '\n';
129.38 if(report) std::cerr << "\nCardinality of max matching: "
129.39 - << mat.matchingSize() << '\n';
129.40 + << mat.matchingSize() << '\n';
129.41 }
129.42
129.43
129.44 -template<class Value>
129.45 +template<class Value, class LargeValue>
129.46 void solve(ArgParser &ap, std::istream &is, std::ostream &os,
129.47 DimacsDescriptor &desc)
129.48 {
129.49 @@ -165,11 +166,11 @@
129.50 << std::endl;
129.51 exit(1);
129.52 }
129.53 -
129.54 +
129.55 switch(desc.type)
129.56 {
129.57 case DimacsDescriptor::MIN:
129.58 - solve_min<Value>(ap,is,os,infty,desc);
129.59 + solve_min<Value, LargeValue>(ap,is,os,infty,desc);
129.60 break;
129.61 case DimacsDescriptor::MAX:
129.62 solve_max<Value>(ap,is,os,infty,desc);
129.63 @@ -237,7 +238,7 @@
129.64 std::ostream& os = (ap.files().size()<2 ? std::cout : output);
129.65
129.66 DimacsDescriptor desc = dimacsType(is);
129.67 -
129.68 +
129.69 if(!ap.given("q"))
129.70 {
129.71 std::cout << "Problem type: ";
129.72 @@ -262,16 +263,18 @@
129.73 std::cout << "\nNum of arcs: " << desc.edgeNum;
129.74 std::cout << "\n\n";
129.75 }
129.76 -
129.77 +
129.78 if(ap.given("double"))
129.79 - solve<double>(ap,is,os,desc);
129.80 + solve<double, double>(ap,is,os,desc);
129.81 else if(ap.given("ldouble"))
129.82 - solve<long double>(ap,is,os,desc);
129.83 + solve<long double, long double>(ap,is,os,desc);
129.84 #ifdef LEMON_HAVE_LONG_LONG
129.85 else if(ap.given("long"))
129.86 - solve<long long>(ap,is,os,desc);
129.87 + solve<long long, long long>(ap,is,os,desc);
129.88 + else solve<int, long long>(ap,is,os,desc);
129.89 +#else
129.90 + else solve<int, long>(ap,is,os,desc);
129.91 #endif
129.92 - else solve<int>(ap,is,os,desc);
129.93
129.94 return 0;
129.95 }
130.1 --- a/tools/lemon-0.x-to-1.x.sh Tue Dec 20 17:44:38 2011 +0100
130.2 +++ b/tools/lemon-0.x-to-1.x.sh Tue Dec 20 18:15:14 2011 +0100
130.3 @@ -35,10 +35,10 @@
130.4 -e "s/IncEdgeIt/_In_cEd_geIt_label_/g"\
130.5 -e "s/Edge\>/_Ar_c_label_/g"\
130.6 -e "s/\<edge\>/_ar_c_label_/g"\
130.7 - -e "s/_edge\>/_ar_c_label_/g"\
130.8 + -e "s/_edge\>/__ar_c_label_/g"\
130.9 -e "s/Edges\>/_Ar_c_label_s/g"\
130.10 -e "s/\<edges\>/_ar_c_label_s/g"\
130.11 - -e "s/_edges\>/_ar_c_label_s/g"\
130.12 + -e "s/_edges\>/__ar_c_label_s/g"\
130.13 -e "s/\([Ee]\)dge\([a-z]\)/_\1d_ge_label_\2/g"\
130.14 -e "s/\([a-z]\)edge/\1_ed_ge_label_/g"\
130.15 -e "s/Edge/_Ar_c_label_/g"\
130.16 @@ -68,6 +68,11 @@
130.17 -e "s/_blu_e_label_/blue/g"\
130.18 -e "s/_GR_APH_TY_PEDE_FS_label_/GRAPH_TYPEDEFS/g"\
130.19 -e "s/_DIGR_APH_TY_PEDE_FS_label_/DIGRAPH_TYPEDEFS/g"\
130.20 + -e "s/\<digraph_adaptor\.h\>/adaptors.h/g"\
130.21 + -e "s/\<digraph_utils\.h\>/core.h/g"\
130.22 + -e "s/\<digraph_reader\.h\>/lgf_reader.h/g"\
130.23 + -e "s/\<digraph_writer\.h\>/lgf_writer.h/g"\
130.24 + -e "s/\<topology\.h\>/connectivity.h/g"\
130.25 -e "s/DigraphToEps/GraphToEps/g"\
130.26 -e "s/digraphToEps/graphToEps/g"\
130.27 -e "s/\<DefPredMap\>/SetPredMap/g"\